OSDN Git Service

pcm: fix the pcm_frames_diff -> pcm_frame_diff typo
[android-x86/external-alsa-lib.git] / src / pcm / pcm_dmix.c
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  */
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
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
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
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
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
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
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  */
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  */
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 = slave_hw_ptr - old_slave_hw_ptr;
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         if (diff < 0) {
404                 slave_hw_ptr += dmix->slave_boundary;
405                 diff = slave_hw_ptr - old_slave_hw_ptr;
406         }
407         dmix->hw_ptr += diff;
408         dmix->hw_ptr %= pcm->boundary;
409         if (pcm->stop_threshold >= pcm->boundary)       /* don't care */
410                 return 0;
411         avail = snd_pcm_mmap_playback_avail(pcm);
412         if (avail > dmix->avail_max)
413                 dmix->avail_max = avail;
414         if (avail >= pcm->stop_threshold) {
415                 snd_timer_stop(dmix->timer);
416                 gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
417                 if (dmix->state == SND_PCM_STATE_RUNNING) {
418                         dmix->state = SND_PCM_STATE_XRUN;
419                         return -EPIPE;
420                 }
421                 dmix->state = SND_PCM_STATE_SETUP;
422                 /* clear queue to remove pending poll events */
423                 snd_pcm_direct_clear_timer_queue(dmix);
424         }
425         return 0;
426 }
427
428 static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
429 {
430         snd_pcm_direct_t *dmix = pcm->private_data;
431         int err;
432
433         switch (snd_pcm_state(dmix->spcm)) {
434         case SND_PCM_STATE_DISCONNECTED:
435                 dmix->state = SND_PCM_STATE_DISCONNECTED;
436                 return -ENODEV;
437         case SND_PCM_STATE_XRUN:
438                 if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
439                         return err;
440                 break;
441         default:
442                 break;
443         }
444         if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
445                 return -EPIPE;
446         if (dmix->slowptr)
447                 snd_pcm_hwsync(dmix->spcm);
448
449         return snd_pcm_dmix_sync_ptr0(pcm, *dmix->spcm->hw.ptr);
450 }
451
452 /*
453  *  plugin implementation
454  */
455
456 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
457 {
458         snd_pcm_direct_t *dmix = pcm->private_data;
459         int err;
460         snd_pcm_state_t state;
461         state = snd_pcm_state(dmix->spcm);
462         switch (state) {
463         case SND_PCM_STATE_SUSPENDED:
464         case SND_PCM_STATE_DISCONNECTED:
465                 dmix->state = state;
466                 return state;
467         case SND_PCM_STATE_XRUN:
468                 if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
469                         return err;
470                 break;
471         default:
472                 break;
473         }
474         snd_pcm_direct_client_chk_xrun(dmix, pcm);
475         if (dmix->state == STATE_RUN_PENDING)
476                 return SNDRV_PCM_STATE_RUNNING;
477         return dmix->state;
478 }
479
480 static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
481 {
482         snd_pcm_direct_t *dmix = pcm->private_data;
483
484         memset(status, 0, sizeof(*status));
485         snd_pcm_status(dmix->spcm, status);
486
487         switch (dmix->state) {
488         case SNDRV_PCM_STATE_DRAINING:
489         case SNDRV_PCM_STATE_RUNNING:
490                 snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr);
491                 status->delay += snd_pcm_mmap_playback_delay(pcm)
492                                 + status->avail - dmix->spcm->buffer_size;
493                 break;
494         default:
495                 break;
496         }
497
498         status->state = snd_pcm_dmix_state(pcm);
499         status->trigger_tstamp = dmix->trigger_tstamp;
500         status->avail = snd_pcm_mmap_playback_avail(pcm);
501         status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
502         dmix->avail_max = 0;
503         return 0;
504 }
505
506 static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
507 {
508         snd_pcm_direct_t *dmix = pcm->private_data;
509         int err;
510         
511         switch(dmix->state) {
512         case SNDRV_PCM_STATE_DRAINING:
513         case SNDRV_PCM_STATE_RUNNING:
514                 err = snd_pcm_dmix_sync_ptr(pcm);
515                 if (err < 0)
516                         return err;
517                 /* fallthru */
518         case SNDRV_PCM_STATE_PREPARED:
519         case SNDRV_PCM_STATE_SUSPENDED:
520         case STATE_RUN_PENDING:
521                 *delayp = snd_pcm_mmap_playback_hw_avail(pcm);
522                 return 0;
523         case SNDRV_PCM_STATE_XRUN:
524                 return -EPIPE;
525         case SNDRV_PCM_STATE_DISCONNECTED:
526                 return -ENODEV;
527         default:
528                 return -EBADFD;
529         }
530 }
531
532 static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm)
533 {
534         snd_pcm_direct_t *dmix = pcm->private_data;
535
536         switch(dmix->state) {
537         case SNDRV_PCM_STATE_DRAINING:
538         case SNDRV_PCM_STATE_RUNNING:
539                 /* sync slave PCM */
540                 return snd_pcm_dmix_sync_ptr(pcm);
541         case SNDRV_PCM_STATE_PREPARED:
542         case SNDRV_PCM_STATE_SUSPENDED:
543         case STATE_RUN_PENDING:
544                 return 0;
545         case SNDRV_PCM_STATE_XRUN:
546                 return -EPIPE;
547         case SNDRV_PCM_STATE_DISCONNECTED:
548                 return -ENODEV;
549         default:
550                 return -EBADFD;
551         }
552 }
553
554 static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
555 {
556         snd_pcm_direct_t *dmix = pcm->private_data;
557         dmix->hw_ptr %= pcm->period_size;
558         dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
559         dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
560         snd_pcm_direct_reset_slave_ptr(pcm, dmix);
561         return 0;
562 }
563
564 static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
565 {
566         int err;
567
568         snd_pcm_hwsync(dmix->spcm);
569         dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
570         snd_pcm_direct_reset_slave_ptr(pcm, dmix);
571         err = snd_timer_start(dmix->timer);
572         if (err < 0)
573                 return err;
574         dmix->state = SND_PCM_STATE_RUNNING;
575         return 0;
576 }
577
578 static int snd_pcm_dmix_start(snd_pcm_t *pcm)
579 {
580         snd_pcm_direct_t *dmix = pcm->private_data;
581         snd_pcm_sframes_t avail;
582         int err;
583         
584         if (dmix->state != SND_PCM_STATE_PREPARED)
585                 return -EBADFD;
586         avail = snd_pcm_mmap_playback_hw_avail(pcm);
587         if (avail == 0)
588                 dmix->state = STATE_RUN_PENDING;
589         else if (avail < 0)
590                 return 0;
591         else {
592                 if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
593                         return err;
594                 snd_pcm_dmix_sync_area(pcm);
595         }
596         gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
597         return 0;
598 }
599
600 static int snd_pcm_dmix_drop(snd_pcm_t *pcm)
601 {
602         snd_pcm_direct_t *dmix = pcm->private_data;
603         if (dmix->state == SND_PCM_STATE_OPEN)
604                 return -EBADFD;
605         dmix->state = SND_PCM_STATE_SETUP;
606         snd_pcm_direct_timer_stop(dmix);
607         return 0;
608 }
609
610 /* locked version */
611 static int __snd_pcm_dmix_drain(snd_pcm_t *pcm)
612 {
613         snd_pcm_direct_t *dmix = pcm->private_data;
614         snd_pcm_uframes_t stop_threshold;
615         int err = 0;
616
617         switch (snd_pcm_state(dmix->spcm)) {
618         case SND_PCM_STATE_SUSPENDED:
619                 return -ESTRPIPE;
620         default:
621                 break;
622         }
623
624         if (dmix->state == SND_PCM_STATE_OPEN)
625                 return -EBADFD;
626         if (dmix->state == SND_PCM_STATE_PREPARED) {
627                 if (snd_pcm_mmap_playback_hw_avail(pcm) > 0)
628                         snd_pcm_dmix_start(pcm);
629                 else {
630                         snd_pcm_dmix_drop(pcm);
631                         return 0;
632                 }
633         }
634
635         if (dmix->state == SND_PCM_STATE_XRUN) {
636                 snd_pcm_dmix_drop(pcm);
637                 return 0;
638         }
639
640         stop_threshold = pcm->stop_threshold;
641         if (pcm->stop_threshold > pcm->buffer_size)
642                 pcm->stop_threshold = pcm->buffer_size;
643         dmix->state = SND_PCM_STATE_DRAINING;
644         do {
645                 err = snd_pcm_dmix_sync_ptr(pcm);
646                 if (err < 0) {
647                         snd_pcm_dmix_drop(pcm);
648                         goto done;
649                 }
650                 if (dmix->state == SND_PCM_STATE_DRAINING) {
651                         snd_pcm_dmix_sync_area(pcm);
652                         if ((pcm->mode & SND_PCM_NONBLOCK) == 0) {
653                                 snd_pcm_wait_nocheck(pcm, -1);
654                                 snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
655                         }
656
657                         switch (snd_pcm_state(dmix->spcm)) {
658                         case SND_PCM_STATE_SUSPENDED:
659                                 err = -ESTRPIPE;
660                                 goto done;
661                         default:
662                                 break;
663                         }
664                 }
665                 if (pcm->mode & SND_PCM_NONBLOCK) {
666                         if (dmix->state == SND_PCM_STATE_DRAINING) {
667                                 err = -EAGAIN;
668                                 goto done;
669                         }
670                 }
671         } while (dmix->state == SND_PCM_STATE_DRAINING);
672 done:
673         pcm->stop_threshold = stop_threshold;
674         return err;
675 }
676
677 static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
678 {
679         int err;
680
681         snd_pcm_lock(pcm);
682         err = __snd_pcm_dmix_drain(pcm);
683         snd_pcm_unlock(pcm);
684         return err;
685 }
686
687 static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
688 {
689         return -EIO;
690 }
691
692 static snd_pcm_sframes_t snd_pcm_dmix_rewindable(snd_pcm_t *pcm)
693 {
694         return snd_pcm_mmap_playback_hw_rewindable(pcm);
695 }
696
697 static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
698 {
699         snd_pcm_direct_t *dmix = pcm->private_data;
700         snd_pcm_uframes_t slave_appl_ptr, slave_size;
701         snd_pcm_uframes_t appl_ptr, size, transfer, result, frames_to_remix;
702         int err;
703         const snd_pcm_channel_area_t *src_areas, *dst_areas;
704
705         if (dmix->state == SND_PCM_STATE_RUNNING ||
706             dmix->state == SND_PCM_STATE_DRAINING) {
707                 err = snd_pcm_dmix_hwsync(pcm);
708                 if (err < 0)
709                         return err;
710         }
711
712         /* (appl_ptr - last_appl_ptr) indicates the frames which are not
713          * already mixed
714          * (last_appl_ptr - hw_ptr)  indicates the frames which are already
715          * mixed but not played yet.
716          * So they can be remixed.
717          */
718
719         size = pcm_frame_diff(dmix->last_appl_ptr, dmix->appl_ptr, pcm->boundary);
720         if (frames < size)
721                 size = frames;
722         snd_pcm_mmap_appl_backward(pcm, size);
723         frames -= size;
724         if (!frames)
725                 return size;
726         result = size;
727
728         /* Always at this point last_appl_ptr == appl_ptr
729          * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
730          */
731         size = pcm_frame_diff(dmix->appl_ptr, dmix->hw_ptr, pcm->boundary);
732         if (size > frames)
733                 size = frames;
734         slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, pcm->boundary);
735         if (slave_size < size)
736                 size = slave_size;
737
738         /* frames which should be remixed will be saved
739          * to also backward the appl pointer on success
740          */
741         frames_to_remix = size;
742
743         /* add sample areas here */
744         src_areas = snd_pcm_mmap_areas(pcm);
745         dst_areas = snd_pcm_mmap_areas(dmix->spcm);
746         dmix->last_appl_ptr -= size;
747         dmix->last_appl_ptr %= pcm->boundary;
748         appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
749         dmix->slave_appl_ptr -= size;
750         dmix->slave_appl_ptr %= dmix->slave_boundary;
751         slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
752         dmix_down_sem(dmix);
753         for (;;) {
754                 transfer = size;
755                 if (appl_ptr + transfer > pcm->buffer_size)
756                         transfer = pcm->buffer_size - appl_ptr;
757                 if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
758                         transfer = dmix->slave_buffer_size - slave_appl_ptr;
759                 remix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
760                 size -= transfer;
761                 if (! size)
762                         break;
763                 slave_appl_ptr += transfer;
764                 slave_appl_ptr %= dmix->slave_buffer_size;
765                 appl_ptr += transfer;
766                 appl_ptr %= pcm->buffer_size;
767         }
768         dmix_up_sem(dmix);
769
770         snd_pcm_mmap_appl_backward(pcm, frames_to_remix);
771         result += frames_to_remix;
772         /* At this point last_appl_ptr and appl_ptr has to indicate the
773          * position of the first not mixed frame
774          */
775
776         return result;
777 }
778
779 static snd_pcm_sframes_t snd_pcm_dmix_forwardable(snd_pcm_t *pcm)
780 {
781         return snd_pcm_mmap_avail(pcm);
782 }
783
784 static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
785 {
786         snd_pcm_sframes_t avail;
787
788         avail = snd_pcm_dmix_forwardable(pcm);
789         if (frames > (snd_pcm_uframes_t)avail)
790                 frames = avail;
791         snd_pcm_mmap_appl_forward(pcm, frames);
792         return frames;
793 }
794
795 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)
796 {
797         return -ENODEV;
798 }
799
800 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)
801 {
802         return -ENODEV;
803 }
804
805 static int snd_pcm_dmix_close(snd_pcm_t *pcm)
806 {
807         snd_pcm_direct_t *dmix = pcm->private_data;
808
809         if (dmix->timer)
810                 snd_timer_close(dmix->timer);
811         snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
812         snd_pcm_close(dmix->spcm);
813         if (dmix->server)
814                 snd_pcm_direct_server_discard(dmix);
815         if (dmix->client)
816                 snd_pcm_direct_client_discard(dmix);
817         shm_sum_discard(dmix);
818         if (snd_pcm_direct_shm_discard(dmix)) {
819                 if (snd_pcm_direct_semaphore_discard(dmix))
820                         snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
821         } else
822                 snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
823         free(dmix->bindings);
824         pcm->private_data = NULL;
825         free(dmix);
826         return 0;
827 }
828
829 static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
830                                                   snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
831                                                   snd_pcm_uframes_t size)
832 {
833         snd_pcm_direct_t *dmix = pcm->private_data;
834         int err;
835
836         switch (snd_pcm_state(dmix->spcm)) {
837         case SND_PCM_STATE_XRUN:
838                 if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
839                         return err;
840                 break;
841         case SND_PCM_STATE_SUSPENDED:
842                 return -ESTRPIPE;
843         default:
844                 break;
845         }
846         if (snd_pcm_direct_client_chk_xrun(dmix, pcm))
847                 return -EPIPE;
848         if (! size)
849                 return 0;
850         snd_pcm_mmap_appl_forward(pcm, size);
851         if (dmix->state == STATE_RUN_PENDING) {
852                 if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
853                         return err;
854         } else if (dmix->state == SND_PCM_STATE_RUNNING ||
855                    dmix->state == SND_PCM_STATE_DRAINING) {
856                 if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
857                         return err;
858         }
859         if (dmix->state == SND_PCM_STATE_RUNNING ||
860             dmix->state == SND_PCM_STATE_DRAINING) {
861                 /* ok, we commit the changes after the validation of area */
862                 /* it's intended, although the result might be crappy */
863                 snd_pcm_dmix_sync_area(pcm);
864                 /* clear timer queue to avoid a bogus return from poll */
865                 if (snd_pcm_mmap_playback_avail(pcm) < pcm->avail_min)
866                         snd_pcm_direct_clear_timer_queue(dmix);
867         }
868         return size;
869 }
870
871 static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
872 {
873         snd_pcm_direct_t *dmix = pcm->private_data;
874         int err;
875         
876         if (dmix->state == SND_PCM_STATE_RUNNING ||
877             dmix->state == SND_PCM_STATE_DRAINING) {
878                 if ((err = snd_pcm_dmix_sync_ptr(pcm)) < 0)
879                         return err;
880         }
881         if (dmix->state == SND_PCM_STATE_XRUN)
882                 return -EPIPE;
883
884         return snd_pcm_mmap_playback_avail(pcm);
885 }
886
887 static int snd_pcm_dmix_htimestamp(snd_pcm_t *pcm,
888                                    snd_pcm_uframes_t *avail,
889                                    snd_htimestamp_t *tstamp)
890 {
891         snd_pcm_direct_t *dmix = pcm->private_data;
892         snd_pcm_uframes_t avail1;
893         int ok = 0;
894         
895         while (1) {
896                 if (dmix->state == SND_PCM_STATE_RUNNING ||
897                     dmix->state == SND_PCM_STATE_DRAINING)
898                         snd_pcm_dmix_sync_ptr(pcm);
899                 avail1 = snd_pcm_mmap_playback_avail(pcm);
900                 if (ok && *avail == avail1)
901                         break;
902                 *avail = avail1;
903                 *tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
904                 ok = 1;
905         }
906         return 0;
907 }
908
909 static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
910 {
911         snd_pcm_direct_t *dmix = pcm->private_data;
912         if (dmix->state == SND_PCM_STATE_RUNNING)
913                 snd_pcm_dmix_sync_area(pcm);
914         return snd_pcm_direct_poll_revents(pcm, pfds, nfds, revents);
915 }
916
917
918 static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)
919 {
920         snd_pcm_direct_t *dmix = pcm->private_data;
921
922         snd_output_printf(out, "Direct Stream Mixing PCM\n");
923         if (pcm->setup) {
924                 snd_output_printf(out, "Its setup is:\n");
925                 snd_pcm_dump_setup(pcm, out);
926         }
927         if (dmix->spcm)
928                 snd_pcm_dump(dmix->spcm, out);
929 }
930
931 static const snd_pcm_ops_t snd_pcm_dmix_ops = {
932         .close = snd_pcm_dmix_close,
933         .info = snd_pcm_direct_info,
934         .hw_refine = snd_pcm_direct_hw_refine,
935         .hw_params = snd_pcm_direct_hw_params,
936         .hw_free = snd_pcm_direct_hw_free,
937         .sw_params = snd_pcm_direct_sw_params,
938         .channel_info = snd_pcm_direct_channel_info,
939         .dump = snd_pcm_dmix_dump,
940         .nonblock = snd_pcm_direct_nonblock,
941         .async = snd_pcm_direct_async,
942         .mmap = snd_pcm_direct_mmap,
943         .munmap = snd_pcm_direct_munmap,
944         .query_chmaps = snd_pcm_direct_query_chmaps,
945         .get_chmap = snd_pcm_direct_get_chmap,
946         .set_chmap = snd_pcm_direct_set_chmap,
947 };
948
949 static const snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
950         .status = snd_pcm_dmix_status,
951         .state = snd_pcm_dmix_state,
952         .hwsync = snd_pcm_dmix_hwsync,
953         .delay = snd_pcm_dmix_delay,
954         .prepare = snd_pcm_direct_prepare,
955         .reset = snd_pcm_dmix_reset,
956         .start = snd_pcm_dmix_start,
957         .drop = snd_pcm_dmix_drop,
958         .drain = snd_pcm_dmix_drain,
959         .pause = snd_pcm_dmix_pause,
960         .rewindable = snd_pcm_dmix_rewindable,
961         .rewind = snd_pcm_dmix_rewind,
962         .forwardable = snd_pcm_dmix_forwardable,
963         .forward = snd_pcm_dmix_forward,
964         .resume = snd_pcm_direct_resume,
965         .link = NULL,
966         .link_slaves = NULL,
967         .unlink = NULL,
968         .writei = snd_pcm_mmap_writei,
969         .writen = snd_pcm_mmap_writen,
970         .readi = snd_pcm_dmix_readi,
971         .readn = snd_pcm_dmix_readn,
972         .avail_update = snd_pcm_dmix_avail_update,
973         .mmap_commit = snd_pcm_dmix_mmap_commit,
974         .htimestamp = snd_pcm_dmix_htimestamp,
975         .poll_descriptors = snd_pcm_direct_poll_descriptors,
976         .poll_descriptors_count = NULL,
977         .poll_revents = snd_pcm_dmix_poll_revents,
978 };
979
980 /**
981  * \brief Creates a new dmix PCM
982  * \param pcmp Returns created PCM handle
983  * \param name Name of PCM
984  * \param opts Direct PCM configurations
985  * \param params Parameters for slave
986  * \param root Configuration root
987  * \param sconf Slave configuration
988  * \param stream PCM Direction (stream)
989  * \param mode PCM Mode
990  * \retval zero on success otherwise a negative error code
991  * \warning Using of this function might be dangerous in the sense
992  *          of compatibility reasons. The prototype might be freely
993  *          changed in future.
994  */
995 int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
996                       struct snd_pcm_direct_open_conf *opts,
997                       struct slave_params *params,
998                       snd_config_t *root, snd_config_t *sconf,
999                       snd_pcm_stream_t stream, int mode)
1000 {
1001         snd_pcm_t *pcm = NULL, *spcm = NULL;
1002         snd_pcm_direct_t *dmix = NULL;
1003         int ret, first_instance;
1004         int fail_sem_loop = 10;
1005
1006         assert(pcmp);
1007
1008         if (stream != SND_PCM_STREAM_PLAYBACK) {
1009                 SNDERR("The dmix plugin supports only playback stream");
1010                 return -EINVAL;
1011         }
1012
1013         dmix = calloc(1, sizeof(snd_pcm_direct_t));
1014         if (!dmix) {
1015                 ret = -ENOMEM;
1016                 goto _err_nosem;
1017         }
1018         
1019         ret = snd_pcm_direct_parse_bindings(dmix, params, opts->bindings);
1020         if (ret < 0)
1021                 goto _err_nosem;
1022         
1023         dmix->ipc_key = opts->ipc_key;
1024         dmix->ipc_perm = opts->ipc_perm;
1025         dmix->ipc_gid = opts->ipc_gid;
1026         dmix->tstamp_type = opts->tstamp_type;
1027         dmix->semid = -1;
1028         dmix->shmid = -1;
1029
1030         ret = snd_pcm_new(&pcm, dmix->type = SND_PCM_TYPE_DMIX, name, stream, mode);
1031         if (ret < 0)
1032                 goto _err;
1033
1034         
1035         while (1) {
1036                 ret = snd_pcm_direct_semaphore_create_or_connect(dmix);
1037                 if (ret < 0) {
1038                         SNDERR("unable to create IPC semaphore");
1039                         goto _err_nosem;
1040                 }
1041                 ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
1042                 if (ret < 0) {
1043                         snd_pcm_direct_semaphore_discard(dmix);
1044                         if (--fail_sem_loop <= 0)
1045                                 goto _err_nosem;
1046                         continue;
1047                 }
1048                 break;
1049         }
1050                 
1051         first_instance = ret = snd_pcm_direct_shm_create_or_connect(dmix);
1052         if (ret < 0) {
1053                 SNDERR("unable to create IPC shm instance");
1054                 goto _err;
1055         }
1056                 
1057         pcm->ops = &snd_pcm_dmix_ops;
1058         pcm->fast_ops = &snd_pcm_dmix_fast_ops;
1059         pcm->private_data = dmix;
1060         dmix->state = SND_PCM_STATE_OPEN;
1061         dmix->slowptr = opts->slowptr;
1062         dmix->max_periods = opts->max_periods;
1063         dmix->var_periodsize = opts->var_periodsize;
1064         dmix->hw_ptr_alignment = opts->hw_ptr_alignment;
1065         dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
1066         dmix->direct_memory_access = opts->direct_memory_access;
1067
1068  retry:
1069         if (first_instance) {
1070                 /* recursion is already checked in
1071                    snd_pcm_direct_get_slave_ipc_offset() */
1072                 ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
1073                                          mode | SND_PCM_NONBLOCK, NULL);
1074                 if (ret < 0) {
1075                         SNDERR("unable to open slave");
1076                         goto _err;
1077                 }
1078         
1079                 if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
1080                         SNDERR("dmix plugin can be only connected to hw plugin");
1081                         ret = -EINVAL;
1082                         goto _err;
1083                 }
1084                 
1085                 ret = snd_pcm_direct_initialize_slave(dmix, spcm, params);
1086                 if (ret < 0) {
1087                         SNDERR("unable to initialize slave");
1088                         goto _err;
1089                 }
1090
1091                 dmix->spcm = spcm;
1092
1093                 if (dmix->shmptr->use_server) {
1094                         dmix->server_free = dmix_server_free;
1095                 
1096                         ret = snd_pcm_direct_server_create(dmix);
1097                         if (ret < 0) {
1098                                 SNDERR("unable to create server");
1099                                 goto _err;
1100                         }
1101                 }
1102
1103                 dmix->shmptr->type = spcm->type;
1104         } else {
1105                 if (dmix->shmptr->use_server) {
1106                         /* up semaphore to avoid deadlock */
1107                         snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1108                         ret = snd_pcm_direct_client_connect(dmix);
1109                         if (ret < 0) {
1110                                 SNDERR("unable to connect client");
1111                                 goto _err_nosem;
1112                         }
1113                         
1114                         snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
1115                         ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
1116                         if (ret < 0)
1117                                 goto _err;
1118                 } else {
1119
1120                         ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
1121                                                  mode | SND_PCM_NONBLOCK |
1122                                                  SND_PCM_APPEND,
1123                                                  NULL);
1124                         if (ret < 0) {
1125                                 /* all other streams have been closed;
1126                                  * retry as the first instance
1127                                  */
1128                                 if (ret == -EBADFD) {
1129                                         first_instance = 1;
1130                                         goto retry;
1131                                 }
1132                                 SNDERR("unable to open slave");
1133                                 goto _err;
1134                         }
1135                         if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
1136                                 SNDERR("dmix plugin can be only connected to hw plugin");
1137                                 ret = -EINVAL;
1138                                 goto _err;
1139                         }
1140                 
1141                         ret = snd_pcm_direct_initialize_secondary_slave(dmix, spcm, params);
1142                         if (ret < 0) {
1143                                 SNDERR("unable to initialize slave");
1144                                 goto _err;
1145                         }
1146                 }
1147
1148                 dmix->spcm = spcm;
1149         }
1150
1151         ret = shm_sum_create_or_connect(dmix);
1152         if (ret < 0) {
1153                 SNDERR("unable to initialize sum ring buffer");
1154                 goto _err;
1155         }
1156
1157         ret = snd_pcm_direct_initialize_poll_fd(dmix);
1158         if (ret < 0) {
1159                 SNDERR("unable to initialize poll_fd");
1160                 goto _err;
1161         }
1162
1163         mix_select_callbacks(dmix);
1164                 
1165         pcm->poll_fd = dmix->poll_fd;
1166         pcm->poll_events = POLLIN;      /* it's different than other plugins */
1167         pcm->tstamp_type = spcm->tstamp_type;
1168         pcm->mmap_rw = 1;
1169         snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0);
1170         snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0);
1171         
1172         if (dmix->channels == UINT_MAX)
1173                 dmix->channels = dmix->shmptr->s.channels;
1174
1175         snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1176
1177         *pcmp = pcm;
1178         return 0;
1179         
1180  _err:
1181         if (dmix->timer)
1182                 snd_timer_close(dmix->timer);
1183         if (dmix->server)
1184                 snd_pcm_direct_server_discard(dmix);
1185         if (dmix->client)
1186                 snd_pcm_direct_client_discard(dmix);
1187         if (spcm)
1188                 snd_pcm_close(spcm);
1189         if (dmix->u.dmix.shmid_sum >= 0)
1190                 shm_sum_discard(dmix);
1191         if ((dmix->shmid >= 0) && (snd_pcm_direct_shm_discard(dmix))) {
1192                 if (snd_pcm_direct_semaphore_discard(dmix))
1193                         snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
1194         } else
1195                 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1196  _err_nosem:
1197         if (dmix) {
1198                 free(dmix->bindings);
1199                 free(dmix);
1200         }
1201         if (pcm)
1202                 snd_pcm_free(pcm);
1203         return ret;
1204 }
1205
1206 /*! \page pcm_plugins
1207
1208 \section pcm_plugins_dmix Plugin: dmix
1209
1210 This plugin provides direct mixing of multiple streams. The resolution
1211 for 32-bit mixing is only 24-bit. The low significant byte is filled with
1212 zeros. The extra 8 bits are used for the saturation.
1213
1214 \code
1215 pcm.name {
1216         type dmix               # Direct mix
1217         ipc_key INT             # unique IPC key
1218         ipc_key_add_uid BOOL    # add current uid to unique IPC key
1219         ipc_perm INT            # IPC permissions (octal, default 0600)
1220         hw_ptr_alignment STR    # Slave application and hw pointer alignment type
1221                                 # STR can be one of the below strings :
1222                                 # no
1223                                 # roundup
1224                                 # rounddown
1225                                 # auto (default)
1226         tstamp_type STR         # timestamp type
1227                                 # STR can be one of the below strings :
1228                                 # default, gettimeofday, monotonic, monotonic_raw
1229         slave STR
1230         # or
1231         slave {                 # Slave definition
1232                 pcm STR         # slave PCM name
1233                 # or
1234                 pcm { }         # slave PCM definition
1235                 format STR      # format definition
1236                 rate INT        # rate definition
1237                 channels INT
1238                 period_time INT # in usec
1239                 # or
1240                 period_size INT # in frames
1241                 buffer_time INT # in usec
1242                 # or
1243                 buffer_size INT # in frames
1244                 periods INT     # when buffer_size or buffer_time is not specified
1245         }
1246         bindings {              # note: this is client independent!!!
1247                 N INT           # maps slave channel to client channel N
1248         }
1249         slowptr BOOL            # slow but more precise pointer updates
1250 }
1251 \endcode
1252
1253 <code>ipc_key</code> specfies the unique IPC key in integer.
1254 This number must be unique for each different dmix definition,
1255 since the shared memory is created with this key number.
1256 When <code>ipc_key_add_uid</code> is set true, the uid value is
1257 added to the value set in <code>ipc_key</code>.  This will
1258 avoid the confliction of the same IPC key with different users
1259 concurrently.
1260
1261 <code>hw_ptr_alignment</code> specifies slave application and hw
1262 pointer alignment type. By default hw_ptr_alignment is auto. Below are
1263 the possible configurations:
1264 - no: minimal latency with minimal frames dropped at startup. But
1265   wakeup of application (return from snd_pcm_wait() or poll()) can
1266   take up to 2 * period.
1267 - roundup: It is guaranteed that all frames will be played at
1268   startup. But the latency will increase upto period-1 frames.
1269 - rounddown: It is guaranteed that a wakeup will happen for each
1270   period and frames can be written from application. But on startup
1271   upto period-1 frames will be dropped.
1272 - auto: Selects the best approach depending on the used period and
1273   buffer size.
1274   If the application buffer size is < 2 * application period,
1275   "roundup" will be selected to avoid under runs. If the slave_period
1276   is < 10ms we could expect that there are low latency
1277   requirements. Therefore "rounddown" will be chosen to avoid long
1278   wakeup times. Such wakeup delay could otherwise end up with Xruns in
1279   case of a dependency to another sound device (e.g. forwarding of
1280   microphone to speaker). Else "no" will be chosen.
1281
1282 Note that the dmix plugin itself supports only a single configuration.
1283 That is, it supports only the fixed rate (default 48000), format
1284 (\c S16), channels (2), and period_time (125000).
1285 For using other configuration, you have to set the value explicitly
1286 in the slave PCM definition.  The rate, format and channels can be
1287 covered by an additional \ref pcm_plugins_dmix "plug plugin",
1288 but there is only one base configuration, anyway.
1289
1290 An example configuration for setting 44100 Hz, \c S32_LE format
1291 as the slave PCM of "hw:0" is like below:
1292 \code
1293 pcm.dmix_44 {
1294         type dmix
1295         ipc_key 321456  # any unique value
1296         ipc_key_add_uid true
1297         slave {
1298                 pcm "hw:0"
1299                 format S32_LE
1300                 rate 44100
1301         }
1302 }
1303 \endcode
1304 You can hear 48000 Hz samples still using this dmix pcm via plug plugin
1305 like:
1306 \code
1307 % aplay -Dplug:dmix_44 foo_48k.wav
1308 \endcode
1309
1310 For using the dmix plugin for OSS emulation device, you have to set
1311 the period and the buffer sizes in power of two.  For example,
1312 \code
1313 pcm.dmixoss {
1314         type dmix
1315         ipc_key 321456  # any unique value
1316         ipc_key_add_uid true
1317         slave {
1318                 pcm "hw:0"
1319                 period_time 0
1320                 period_size 1024  # must be power of 2
1321                 buffer_size 8192  # ditto
1322         }
1323 }
1324 \endcode
1325 <code>period_time 0</code> must be set, too, for resetting the
1326 default value.  In the case of soundcards with multi-channel IO,
1327 adding the bindings would help
1328 \code
1329 pcm.dmixoss {
1330         ...
1331         bindings {
1332                 0 0   # map from 0 to 0
1333                 1 1   # map from 1 to 1
1334         }
1335 }
1336 \endcode
1337 so that only the first two channels are used by dmix.
1338 Also, note that ICE1712 have the limited buffer size, 5513 frames
1339 (corresponding to 640 kB).  In this case, reduce the buffer_size
1340 to 4096.
1341
1342 \subsection pcm_plugins_dmix_funcref Function reference
1343
1344 <UL>
1345   <LI>snd_pcm_dmix_open()
1346   <LI>_snd_pcm_dmix_open()
1347 </UL>
1348
1349 */
1350
1351 /**
1352  * \brief Creates a new dmix PCM
1353  * \param pcmp Returns created PCM handle
1354  * \param name Name of PCM
1355  * \param root Root configuration node
1356  * \param conf Configuration node with dmix PCM description
1357  * \param stream PCM Stream
1358  * \param mode PCM Mode
1359  * \warning Using of this function might be dangerous in the sense
1360  *          of compatibility reasons. The prototype might be freely
1361  *          changed in future.
1362  */
1363 int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
1364                        snd_config_t *root, snd_config_t *conf,
1365                        snd_pcm_stream_t stream, int mode)
1366 {
1367         snd_config_t *sconf;
1368         struct slave_params params;
1369         struct snd_pcm_direct_open_conf dopen;
1370         int bsize, psize;
1371         int err;
1372
1373         err = snd_pcm_direct_parse_open_conf(root, conf, stream, &dopen);
1374         if (err < 0)
1375                 return err;
1376
1377         /* the default settings, it might be invalid for some hardware */
1378         params.format = SND_PCM_FORMAT_S16;
1379         params.rate = 48000;
1380         params.channels = 2;
1381         params.period_time = -1;
1382         params.buffer_time = -1;
1383         bsize = psize = -1;
1384         params.periods = 3;
1385
1386         err = snd_pcm_slave_conf(root, dopen.slave, &sconf, 8,
1387                                  SND_PCM_HW_PARAM_FORMAT, SCONF_UNCHANGED, &params.format,
1388                                  SND_PCM_HW_PARAM_RATE, 0, &params.rate,
1389                                  SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
1390                                  SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
1391                                  SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
1392                                  SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
1393                                  SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
1394                                  SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
1395         if (err < 0)
1396                 return err;
1397
1398         /* set a reasonable default */  
1399         if (psize == -1 && params.period_time == -1)
1400                 params.period_time = 125000;    /* 0.125 seconds */
1401
1402         if (params.format == -2)
1403                 params.format = SND_PCM_FORMAT_UNKNOWN;
1404         else if (!(dmix_supported_format & (1ULL << params.format))) {
1405                 /* sorry, limited features */
1406                 SNDERR("Unsupported format");
1407                 snd_config_delete(sconf);
1408                 return -EINVAL;
1409         }
1410
1411         params.period_size = psize;
1412         params.buffer_size = bsize;
1413
1414         err = snd_pcm_dmix_open(pcmp, name, &dopen, &params,
1415                                 root, sconf, stream, mode);
1416         snd_config_delete(sconf);
1417         return err;
1418 }
1419 #ifndef DOC_HIDDEN
1420 SND_DLSYM_BUILD_VERSION(_snd_pcm_dmix_open, SND_PCM_DLSYM_VERSION);
1421 #endif