OSDN Git Service

Fix poll after XRUN with dmix
[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@suse.cz>
6  * \date 2003
7  */
8 /*
9  *  PCM - Direct Stream Mixing
10  *  Copyright (c) 2003 by Jaroslav Kysela <perex@suse.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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 <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <sys/shm.h>
40 #include <sys/sem.h>
41 #include <sys/wait.h>
42 #include <sys/socket.h>
43 #include <sys/un.h>
44 #include <sys/mman.h>
45 #include "pcm_direct.h"
46
47 #ifndef PIC
48 /* entry for static linking */
49 const char *_snd_module_pcm_dmix = "";
50 #endif
51
52 /* start is pending - this state happens when rate plugin does a delayed commit */
53 #define STATE_RUN_PENDING       1024
54
55 /*
56  *
57  */
58
59 static int shm_sum_discard(snd_pcm_direct_t *dmix);
60
61 /*
62  *  sum ring buffer shared memory area 
63  */
64 static int shm_sum_create_or_connect(snd_pcm_direct_t *dmix)
65 {
66         struct shmid_ds buf;
67         int tmpid, err;
68         size_t size;
69
70         size = dmix->shmptr->s.channels *
71                dmix->shmptr->s.buffer_size *
72                sizeof(signed int);      
73 retryshm:
74         dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size,
75                                         IPC_CREAT | dmix->ipc_perm);
76         err = -errno;
77         if (dmix->u.dmix.shmid_sum < 0){
78                 if (errno == EINVAL)
79                 if ((tmpid = shmget(dmix->ipc_key + 1, 0, dmix->ipc_perm)) != -1)
80                 if (!shmctl(tmpid, IPC_STAT, &buf))
81                 if (!buf.shm_nattch) 
82                 /* no users so destroy the segment */
83                 if (!shmctl(tmpid, IPC_RMID, NULL))
84                     goto retryshm;
85                 return err;
86         }
87         dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0);
88         if (dmix->u.dmix.sum_buffer == (void *) -1) {
89                 shm_sum_discard(dmix);
90                 return -errno;
91         }
92         mlock(dmix->u.dmix.sum_buffer, size);
93         return 0;
94 }
95
96 static int shm_sum_discard(snd_pcm_direct_t *dmix)
97 {
98         struct shmid_ds buf;
99         int ret = 0;
100
101         if (dmix->u.dmix.shmid_sum < 0)
102                 return -EINVAL;
103         if (dmix->u.dmix.sum_buffer != (void *) -1 && shmdt(dmix->u.dmix.sum_buffer) < 0)
104                 return -errno;
105         dmix->u.dmix.sum_buffer = (void *) -1;
106         if (shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf) < 0)
107                 return -errno;
108         if (buf.shm_nattch == 0) {      /* we're the last user, destroy the segment */
109                 if (shmctl(dmix->u.dmix.shmid_sum, IPC_RMID, NULL) < 0)
110                         return -errno;
111                 ret = 1;
112         }
113         dmix->u.dmix.shmid_sum = -1;
114         return ret;
115 }
116
117 static void dmix_server_free(snd_pcm_direct_t *dmix)
118 {
119         /* remove the memory region */
120         shm_sum_create_or_connect(dmix);
121         shm_sum_discard(dmix);
122 }
123
124 /*
125  *  the main function of this plugin: mixing
126  *  FIXME: optimize it for different architectures
127  */
128
129 #if defined(__i386__)
130 #include "pcm_dmix_i386.c"
131 #elif defined(__x86_64__)
132 #include "pcm_dmix_x86_64.c"
133 #else
134 #include "pcm_dmix_generic.c"
135 #endif
136
137 static void mix_areas(snd_pcm_direct_t *dmix,
138                       const snd_pcm_channel_area_t *src_areas,
139                       const snd_pcm_channel_area_t *dst_areas,
140                       snd_pcm_uframes_t src_ofs,
141                       snd_pcm_uframes_t dst_ofs,
142                       snd_pcm_uframes_t size)
143 {
144         volatile signed int *sum;
145         unsigned int src_step, dst_step;
146         unsigned int chn, dchn, channels;
147         
148         channels = dmix->channels;
149         if (dmix->shmptr->s.format == SND_PCM_FORMAT_S16) {
150                 signed short *src;
151                 volatile signed short *dst;
152                 if (dmix->interleaved) {
153                         /*
154                          * process all areas in one loop
155                          * it optimizes the memory accesses for this case
156                          */
157                         dmix->u.dmix.mix_areas1(size * channels,
158                                          ((signed short *)dst_areas[0].addr) + (dst_ofs * channels),
159                                          ((signed short *)src_areas[0].addr) + (src_ofs * channels),
160                                          dmix->u.dmix.sum_buffer + (dst_ofs * channels),
161                                          sizeof(signed short),
162                                          sizeof(signed short),
163                                          sizeof(signed int));
164                         return;
165                 }
166                 for (chn = 0; chn < channels; chn++) {
167                         dchn = dmix->bindings ? dmix->bindings[chn] : chn;
168                         if (dchn >= dmix->shmptr->s.channels)
169                                 continue;
170                         src_step = src_areas[chn].step / 8;
171                         dst_step = dst_areas[dchn].step / 8;
172                         src = (signed short *)(((char *)src_areas[chn].addr + src_areas[chn].first / 8) + (src_ofs * src_step));
173                         dst = (signed short *)(((char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + (dst_ofs * dst_step));
174                         sum = dmix->u.dmix.sum_buffer + channels * dst_ofs + chn;
175                         dmix->u.dmix.mix_areas1(size, dst, src, sum, dst_step, src_step, channels * sizeof(signed int));
176                 }
177         } else {
178                 signed int *src;
179                 volatile signed int *dst;
180                 if (dmix->interleaved) {
181                         /*
182                          * process all areas in one loop
183                          * it optimizes the memory accesses for this case
184                          */
185                         dmix->u.dmix.mix_areas2(size * channels,
186                                          ((signed int *)dst_areas[0].addr) + (dst_ofs * channels),
187                                          ((signed int *)src_areas[0].addr) + (src_ofs * channels),
188                                          dmix->u.dmix.sum_buffer + (dst_ofs * channels),
189                                          sizeof(signed int),
190                                          sizeof(signed int),
191                                          sizeof(signed int));
192                         return;
193                 }
194                 for (chn = 0; chn < channels; chn++) {
195                         dchn = dmix->bindings ? dmix->bindings[chn] : chn;
196                         if (dchn >= dmix->shmptr->s.channels)
197                                 continue;
198                         src_step = src_areas[chn].step / 8;
199                         dst_step = dst_areas[dchn].step / 8;
200                         src = (signed int *)(((char *)src_areas[chn].addr + src_areas[chn].first / 8) + (src_ofs * src_step));
201                         dst = (signed int *)(((char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + (dst_ofs * dst_step));
202                         sum = dmix->u.dmix.sum_buffer + channels * dst_ofs + chn;
203                         dmix->u.dmix.mix_areas2(size, dst, src, sum, dst_step, src_step, channels * sizeof(signed int));
204                 }
205         }
206 }
207
208 /*
209  * if no concurrent access is allowed in the mixing routines, we need to protect
210  * the area via semaphore
211  */
212 #ifdef NO_CONCURRENT_ACCESS
213 #define dmix_down_sem(dmix) snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT)
214 #define dmix_up_sem(dmix) snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT)
215 #else
216 #define dmix_down_sem(dmix)
217 #define dmix_up_sem(dmix)
218 #endif
219
220 /*
221  *  synchronize shm ring buffer with hardware
222  */
223 static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
224 {
225         snd_pcm_direct_t *dmix = pcm->private_data;
226         snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize;
227         snd_pcm_uframes_t size, slave_hw_ptr;
228         const snd_pcm_channel_area_t *src_areas, *dst_areas;
229         
230         /* calculate the size to transfer */
231         size = dmix->appl_ptr - dmix->last_appl_ptr;
232         if (! size)
233                 return;
234         slave_bsize = dmix->shmptr->s.buffer_size;
235         slave_hw_ptr = dmix->slave_hw_ptr;
236         /* don't write on the last active period - this area may be cleared
237          * by the driver during mix operation...
238          */
239         slave_hw_ptr -= slave_hw_ptr % dmix->shmptr->s.period_size;
240         slave_hw_ptr += slave_bsize;
241         if (dmix->slave_hw_ptr > dmix->slave_appl_ptr)
242                 slave_hw_ptr -= dmix->shmptr->s.boundary;
243         if (dmix->slave_appl_ptr + size >= slave_hw_ptr)
244                 size = slave_hw_ptr - dmix->slave_appl_ptr;
245         if (! size)
246                 return;
247         /* add sample areas here */
248         src_areas = snd_pcm_mmap_areas(pcm);
249         dst_areas = snd_pcm_mmap_areas(dmix->spcm);
250         appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
251         dmix->last_appl_ptr += size;
252         dmix->last_appl_ptr %= pcm->boundary;
253         slave_appl_ptr = dmix->slave_appl_ptr % slave_bsize;
254         dmix->slave_appl_ptr += size;
255         dmix->slave_appl_ptr %= dmix->shmptr->s.boundary;
256         dmix_down_sem(dmix);
257         for (;;) {
258                 snd_pcm_uframes_t transfer = size;
259                 if (appl_ptr + transfer > pcm->buffer_size)
260                         transfer = pcm->buffer_size - appl_ptr;
261                 if (slave_appl_ptr + transfer > slave_bsize)
262                         transfer = slave_bsize - slave_appl_ptr;
263                 mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
264                 size -= transfer;
265                 if (! size)
266                         break;
267                 slave_appl_ptr += transfer;
268                 slave_appl_ptr %= dmix->shmptr->s.buffer_size;
269                 appl_ptr += transfer;
270                 appl_ptr %= pcm->buffer_size;
271         }
272         dmix_up_sem(dmix);
273 }
274
275 /*
276  *  synchronize hardware pointer (hw_ptr) with ours
277  */
278 static int _snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm, int do_slave_sync)
279 {
280         snd_pcm_direct_t *dmix = pcm->private_data;
281         snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
282         snd_pcm_sframes_t diff;
283         
284         switch (snd_pcm_state(dmix->spcm)) {
285         case SND_PCM_STATE_DISCONNECTED:
286                 dmix->state = SND_PCM_STATE_DISCONNECTED;
287                 return -ENOTTY;
288         default:
289                 break;
290         }
291         if (do_slave_sync)
292                 snd_pcm_hwsync(dmix->spcm);
293         old_slave_hw_ptr = dmix->slave_hw_ptr;
294         slave_hw_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
295         diff = slave_hw_ptr - old_slave_hw_ptr;
296         if (diff == 0)          /* fast path */
297                 return 0;
298         if (dmix->state != SND_PCM_STATE_RUNNING &&
299             dmix->state != SND_PCM_STATE_DRAINING)
300                 /* not really started yet - don't update hw_ptr */
301                 return 0;
302         if (diff < 0) {
303                 slave_hw_ptr += dmix->shmptr->s.boundary;
304                 diff = slave_hw_ptr - old_slave_hw_ptr;
305         }
306         dmix->hw_ptr += diff;
307         dmix->hw_ptr %= pcm->boundary;
308         if (pcm->stop_threshold >= pcm->boundary)       /* don't care */
309                 return 0;
310         avail = snd_pcm_mmap_playback_avail(pcm);
311         if (avail > dmix->avail_max)
312                 dmix->avail_max = avail;
313         if (avail >= pcm->stop_threshold) {
314                 struct timeval tv;
315                 snd_timer_stop(dmix->timer);
316                 gettimeofday(&tv, 0);
317                 dmix->trigger_tstamp.tv_sec = tv.tv_sec;
318                 dmix->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
319                 if (dmix->state == SND_PCM_STATE_RUNNING) {
320                         dmix->state = SND_PCM_STATE_XRUN;
321                         return -EPIPE;
322                 }
323                 dmix->state = SND_PCM_STATE_SETUP;
324                 /* clear queue to remove pending poll events */
325                 snd_pcm_direct_clear_timer_queue(dmix);
326         }
327         return 0;
328 }
329
330 static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
331 {
332         snd_pcm_direct_t *dmix = pcm->private_data;
333         return _snd_pcm_dmix_sync_ptr(pcm, dmix->slowptr);
334 }
335
336 /*
337  *  plugin implementation
338  */
339
340 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
341 {
342         snd_pcm_direct_t *dmix = pcm->private_data;
343         snd_pcm_state_t state;
344         state = snd_pcm_state(dmix->spcm);
345         switch (state) {
346         case SND_PCM_STATE_SUSPENDED:
347                 return state;
348         case SND_PCM_STATE_DISCONNECTED:
349                 return state;
350         default:
351                 break;
352         }
353         if (dmix->state == STATE_RUN_PENDING)
354                 return SNDRV_PCM_STATE_RUNNING;
355         return dmix->state;
356 }
357
358 static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
359 {
360         snd_pcm_direct_t *dmix = pcm->private_data;
361
362         switch (dmix->state) {
363         case SNDRV_PCM_STATE_DRAINING:
364         case SNDRV_PCM_STATE_RUNNING:
365                 snd_pcm_dmix_sync_ptr(pcm);
366                 break;
367         default:
368                 break;
369         }
370         memset(status, 0, sizeof(*status));
371         status->state = snd_pcm_dmix_state(pcm);
372         status->trigger_tstamp = dmix->trigger_tstamp;
373         status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
374         status->avail = snd_pcm_mmap_playback_avail(pcm);
375         status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
376         dmix->avail_max = 0;
377         return 0;
378 }
379
380 static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
381 {
382         snd_pcm_direct_t *dmix = pcm->private_data;
383         int err;
384         
385         switch(dmix->state) {
386         case SNDRV_PCM_STATE_DRAINING:
387         case SNDRV_PCM_STATE_RUNNING:
388                 err = snd_pcm_dmix_sync_ptr(pcm);
389                 if (err < 0)
390                         return err;
391                 /* fallthru */
392         case SNDRV_PCM_STATE_PREPARED:
393         case SNDRV_PCM_STATE_SUSPENDED:
394         case STATE_RUN_PENDING:
395                 *delayp = snd_pcm_mmap_playback_hw_avail(pcm);
396                 return 0;
397         case SNDRV_PCM_STATE_XRUN:
398                 return -EPIPE;
399         case SNDRV_PCM_STATE_DISCONNECTED:
400                 return -ENOTTY;
401         default:
402                 return -EBADFD;
403         }
404 }
405
406 static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm)
407 {
408         snd_pcm_direct_t *dmix = pcm->private_data;
409
410         switch(dmix->state) {
411         case SNDRV_PCM_STATE_DRAINING:
412         case SNDRV_PCM_STATE_RUNNING:
413                 /* sync slave PCM */
414                 //return _snd_pcm_dmix_sync_ptr(pcm, 1);
415                 return snd_pcm_dmix_sync_ptr(pcm);
416         case SNDRV_PCM_STATE_PREPARED:
417         case SNDRV_PCM_STATE_SUSPENDED:
418         case STATE_RUN_PENDING:
419                 return 0;
420         case SNDRV_PCM_STATE_XRUN:
421                 return -EPIPE;
422         case SNDRV_PCM_STATE_DISCONNECTED:
423                 return -ENOTTY;
424         default:
425                 return -EBADFD;
426         }
427 }
428
429 static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
430 {
431         snd_pcm_direct_t *dmix = pcm->private_data;
432
433         snd_pcm_direct_check_interleave(dmix, pcm);
434         // assert(pcm->boundary == dmix->shmptr->s.boundary);   /* for sure */
435         dmix->state = SND_PCM_STATE_PREPARED;
436         dmix->appl_ptr = dmix->last_appl_ptr = 0;
437         dmix->hw_ptr = 0;
438         return snd_pcm_direct_set_timer_params(dmix);
439 }
440
441 static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
442 {
443         snd_pcm_direct_t *dmix = pcm->private_data;
444         dmix->hw_ptr %= pcm->period_size;
445         dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
446         dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
447         return 0;
448 }
449
450 static int snd_pcm_dmix_start_timer(snd_pcm_direct_t *dmix)
451 {
452         int err;
453
454         snd_pcm_hwsync(dmix->spcm);
455         dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
456         err = snd_timer_start(dmix->timer);
457         if (err < 0)
458                 return err;
459         dmix->state = SND_PCM_STATE_RUNNING;
460         return 0;
461 }
462
463 static int snd_pcm_dmix_start(snd_pcm_t *pcm)
464 {
465         snd_pcm_direct_t *dmix = pcm->private_data;
466         snd_pcm_sframes_t avail;
467         struct timeval tv;
468         int err;
469         
470         if (dmix->state != SND_PCM_STATE_PREPARED)
471                 return -EBADFD;
472         avail = snd_pcm_mmap_playback_hw_avail(pcm);
473         if (avail == 0)
474                 dmix->state = STATE_RUN_PENDING;
475         else if (avail < 0)
476                 return 0;
477         else {
478                 if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
479                         return err;
480                 snd_pcm_dmix_sync_area(pcm);
481         }
482         gettimeofday(&tv, 0);
483         dmix->trigger_tstamp.tv_sec = tv.tv_sec;
484         dmix->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
485         return 0;
486 }
487
488 static int snd_pcm_dmix_drop(snd_pcm_t *pcm)
489 {
490         snd_pcm_direct_t *dmix = pcm->private_data;
491         if (dmix->state == SND_PCM_STATE_OPEN)
492                 return -EBADFD;
493         snd_pcm_direct_timer_stop(dmix);
494         dmix->state = SND_PCM_STATE_SETUP;
495         return 0;
496 }
497
498 static int snd_pcm_dmix_drain(snd_pcm_t *pcm)
499 {
500         snd_pcm_direct_t *dmix = pcm->private_data;
501         snd_pcm_uframes_t stop_threshold;
502         int err;
503
504         if (dmix->state == SND_PCM_STATE_OPEN)
505                 return -EBADFD;
506         if (pcm->mode & SND_PCM_NONBLOCK)
507                 return -EAGAIN;
508         if (dmix->state == SND_PCM_STATE_PREPARED) {
509                 if (snd_pcm_mmap_playback_hw_avail(pcm) > 0)
510                         snd_pcm_dmix_start(pcm);
511                 else {
512                         snd_pcm_dmix_drop(pcm);
513                         return 0;
514                 }
515         }
516         stop_threshold = pcm->stop_threshold;
517         if (pcm->stop_threshold > pcm->buffer_size)
518                 pcm->stop_threshold = pcm->buffer_size;
519         dmix->state = SND_PCM_STATE_DRAINING;
520         do {
521                 err = snd_pcm_dmix_sync_ptr(pcm);
522                 if (err < 0) {
523                         snd_pcm_dmix_drop(pcm);
524                         return err;
525                 }
526                 if (dmix->state == SND_PCM_STATE_DRAINING) {
527                         snd_pcm_dmix_sync_area(pcm);
528                         snd_pcm_wait_nocheck(pcm, -1);
529                         snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
530                 }
531         } while (dmix->state == SND_PCM_STATE_DRAINING);
532         pcm->stop_threshold = stop_threshold;
533         return 0;
534 }
535
536 static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
537 {
538         return -EIO;
539 }
540
541 static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames ATTRIBUTE_UNUSED)
542 {
543 #if 0
544         /* FIXME: substract samples from the mix ring buffer, too? */
545         snd_pcm_mmap_appl_backward(pcm, frames);
546         return frames;
547 #else
548         return -EIO;
549 #endif
550 }
551
552 static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
553 {
554         snd_pcm_sframes_t avail;
555
556         avail = snd_pcm_mmap_playback_avail(pcm);
557         if (avail < 0)
558                 return 0;
559         if (frames > (snd_pcm_uframes_t)avail)
560                 frames = avail;
561         snd_pcm_mmap_appl_forward(pcm, frames);
562         return frames;
563 }
564
565 static int snd_pcm_dmix_resume(snd_pcm_t *pcm)
566 {
567         snd_pcm_direct_t *dmix = pcm->private_data;
568         snd_pcm_resume(dmix->spcm);
569         return 0;
570 }
571
572 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)
573 {
574         return -ENODEV;
575 }
576
577 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)
578 {
579         return -ENODEV;
580 }
581
582 static int snd_pcm_dmix_close(snd_pcm_t *pcm)
583 {
584         snd_pcm_direct_t *dmix = pcm->private_data;
585
586         if (dmix->timer)
587                 snd_timer_close(dmix->timer);
588         snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
589         snd_pcm_close(dmix->spcm);
590         if (dmix->server)
591                 snd_pcm_direct_server_discard(dmix);
592         if (dmix->client)
593                 snd_pcm_direct_client_discard(dmix);
594         shm_sum_discard(dmix);
595         if (snd_pcm_direct_shm_discard(dmix) > 0) {
596                 if (snd_pcm_direct_semaphore_discard(dmix) < 0)
597                         snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
598         } else {
599                 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
600         }
601         if (dmix->bindings)
602                 free(dmix->bindings);
603         pcm->private_data = NULL;
604         free(dmix);
605         return 0;
606 }
607
608 static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
609                                                   snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
610                                                   snd_pcm_uframes_t size)
611 {
612         snd_pcm_direct_t *dmix = pcm->private_data;
613         int err;
614
615         switch (snd_pcm_state(dmix->spcm)) {
616         case SND_PCM_STATE_XRUN:
617                 return -EPIPE;
618         case SND_PCM_STATE_SUSPENDED:
619                 return -ESTRPIPE;
620         default:
621                 break;
622         }
623         if (! size)
624                 return 0;
625         snd_pcm_mmap_appl_forward(pcm, size);
626         if (dmix->state == STATE_RUN_PENDING) {
627                 if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
628                         return err;
629         } else if (dmix->state == SND_PCM_STATE_RUNNING ||
630                    dmix->state == SND_PCM_STATE_DRAINING)
631                 //_snd_pcm_dmix_sync_ptr(pcm, 1);
632                 snd_pcm_dmix_sync_ptr(pcm);
633         if (dmix->state == SND_PCM_STATE_RUNNING ||
634             dmix->state == SND_PCM_STATE_DRAINING) {
635                 /* ok, we commit the changes after the validation of area */
636                 /* it's intended, although the result might be crappy */
637                 snd_pcm_dmix_sync_area(pcm);
638                 /* clear timer queue to avoid a bogus return from poll */
639                 if (snd_pcm_mmap_playback_avail(pcm) < pcm->avail_min)
640                         snd_pcm_direct_clear_timer_queue(dmix);
641         }
642         return size;
643 }
644
645 static snd_pcm_sframes_t snd_pcm_dmix_avail_update(snd_pcm_t *pcm)
646 {
647         snd_pcm_direct_t *dmix = pcm->private_data;
648         
649         if (dmix->state == SND_PCM_STATE_RUNNING ||
650             dmix->state == SND_PCM_STATE_DRAINING)
651                 snd_pcm_dmix_sync_ptr(pcm);
652         return snd_pcm_mmap_playback_avail(pcm);
653 }
654
655 static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
656 {
657         snd_pcm_direct_t *dmix = pcm->private_data;
658         if (dmix->state == SND_PCM_STATE_RUNNING)
659                 snd_pcm_dmix_sync_area(pcm);
660         return snd_pcm_direct_poll_revents(pcm, pfds, nfds, revents);
661 }
662
663
664 static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out)
665 {
666         snd_pcm_direct_t *dmix = pcm->private_data;
667
668         snd_output_printf(out, "Direct Stream Mixing PCM\n");
669         if (pcm->setup) {
670                 snd_output_printf(out, "\nIts setup is:\n");
671                 snd_pcm_dump_setup(pcm, out);
672         }
673         if (dmix->spcm)
674                 snd_pcm_dump(dmix->spcm, out);
675 }
676
677 static snd_pcm_ops_t snd_pcm_dmix_ops = {
678         .close = snd_pcm_dmix_close,
679         .info = snd_pcm_direct_info,
680         .hw_refine = snd_pcm_direct_hw_refine,
681         .hw_params = snd_pcm_direct_hw_params,
682         .hw_free = snd_pcm_direct_hw_free,
683         .sw_params = snd_pcm_direct_sw_params,
684         .channel_info = snd_pcm_direct_channel_info,
685         .dump = snd_pcm_dmix_dump,
686         .nonblock = snd_pcm_direct_nonblock,
687         .async = snd_pcm_direct_async,
688         .poll_revents = snd_pcm_dmix_poll_revents,
689         .mmap = snd_pcm_direct_mmap,
690         .munmap = snd_pcm_direct_munmap,
691 };
692
693 static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
694         .status = snd_pcm_dmix_status,
695         .state = snd_pcm_dmix_state,
696         .hwsync = snd_pcm_dmix_hwsync,
697         .delay = snd_pcm_dmix_delay,
698         .prepare = snd_pcm_dmix_prepare,
699         .reset = snd_pcm_dmix_reset,
700         .start = snd_pcm_dmix_start,
701         .drop = snd_pcm_dmix_drop,
702         .drain = snd_pcm_dmix_drain,
703         .pause = snd_pcm_dmix_pause,
704         .rewind = snd_pcm_dmix_rewind,
705         .forward = snd_pcm_dmix_forward,
706         .resume = snd_pcm_dmix_resume,
707         .link_fd = NULL,
708         .link = NULL,
709         .unlink = NULL,
710         .writei = snd_pcm_mmap_writei,
711         .writen = snd_pcm_mmap_writen,
712         .readi = snd_pcm_dmix_readi,
713         .readn = snd_pcm_dmix_readn,
714         .avail_update = snd_pcm_dmix_avail_update,
715         .mmap_commit = snd_pcm_dmix_mmap_commit,
716 };
717
718 /**
719  * \brief Creates a new dmix PCM
720  * \param pcmp Returns created PCM handle
721  * \param name Name of PCM
722  * \param ipc_key IPC key for semaphore and shared memory
723  * \param ipc_perm IPC permissions for semaphore and shared memory
724  * \param params Parameters for slave
725  * \param bindings Channel bindings
726  * \param slowptr Slow but more precise pointer updates
727  * \param root Configuration root
728  * \param sconf Slave configuration
729  * \param stream PCM Direction (stream)
730  * \param mode PCM Mode
731  * \retval zero on success otherwise a negative error code
732  * \warning Using of this function might be dangerous in the sense
733  *          of compatibility reasons. The prototype might be freely
734  *          changed in future.
735  */
736 int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
737                       key_t ipc_key, mode_t ipc_perm,
738                       struct slave_params *params,
739                       snd_config_t *bindings,
740                       int slowptr,
741                       snd_config_t *root, snd_config_t *sconf,
742                       snd_pcm_stream_t stream, int mode)
743 {
744         snd_pcm_t *pcm = NULL, *spcm = NULL;
745         snd_pcm_direct_t *dmix = NULL;
746         int ret, first_instance;
747         int fail_sem_loop = 10;
748
749         assert(pcmp);
750
751         if (stream != SND_PCM_STREAM_PLAYBACK) {
752                 SNDERR("The dmix plugin supports only playback stream");
753                 return -EINVAL;
754         }
755
756         dmix = calloc(1, sizeof(snd_pcm_direct_t));
757         if (!dmix) {
758                 ret = -ENOMEM;
759                 goto _err;
760         }
761         
762         ret = snd_pcm_direct_parse_bindings(dmix, bindings);
763         if (ret < 0)
764                 goto _err;
765         
766         dmix->ipc_key = ipc_key;
767         dmix->ipc_perm = ipc_perm;
768         dmix->semid = -1;
769         dmix->shmid = -1;
770
771         ret = snd_pcm_new(&pcm, dmix->type = SND_PCM_TYPE_DMIX, name, stream, mode);
772         if (ret < 0)
773                 goto _err;
774
775         
776         while (1) {
777                 ret = snd_pcm_direct_semaphore_create_or_connect(dmix);
778                 if (ret < 0) {
779                         SNDERR("unable to create IPC semaphore");
780                         goto _err;
781                 }
782                 ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
783                 if (ret < 0) {
784                         snd_pcm_direct_semaphore_discard(dmix);
785                         if (--fail_sem_loop <= 0)
786                                 goto _err;
787                         continue;
788                 }
789                 break;
790         }
791                 
792         first_instance = ret = snd_pcm_direct_shm_create_or_connect(dmix);
793         if (ret < 0) {
794                 SNDERR("unable to create IPC shm instance");
795                 goto _err;
796         }
797                 
798         pcm->ops = &snd_pcm_dmix_ops;
799         pcm->fast_ops = &snd_pcm_dmix_fast_ops;
800         pcm->private_data = dmix;
801         dmix->state = SND_PCM_STATE_OPEN;
802         dmix->slowptr = slowptr;
803         dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
804
805         if (first_instance) {
806                 ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
807                 if (ret < 0) {
808                         SNDERR("unable to open slave");
809                         goto _err;
810                 }
811         
812                 if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
813                         SNDERR("dmix plugin can be only connected to hw plugin");
814                         ret = -EINVAL;
815                         goto _err;
816                 }
817                 
818                 ret = snd_pcm_direct_initialize_slave(dmix, spcm, params);
819                 if (ret < 0) {
820                         SNDERR("unable to initialize slave");
821                         goto _err;
822                 }
823
824                 dmix->spcm = spcm;
825
826                 dmix->server_free = dmix_server_free;
827                 
828                 ret = snd_pcm_direct_server_create(dmix);
829                 if (ret < 0) {
830                         SNDERR("unable to create server");
831                         goto _err;
832                 }
833
834                 dmix->shmptr->type = spcm->type;
835         } else {
836                 ret = snd_pcm_direct_client_connect(dmix);
837                 if (ret < 0) {
838                         SNDERR("unable to connect client");
839                         return ret;
840                 }
841                         
842                 ret = snd_pcm_hw_open_fd(&spcm, "dmix_client", dmix->hw_fd, 0, 0);
843                 if (ret < 0) {
844                         SNDERR("unable to open hardware");
845                         goto _err;
846                 }
847                 
848                 spcm->donot_close = 1;
849                 spcm->setup = 1;
850                 spcm->buffer_size = dmix->shmptr->s.buffer_size;
851                 spcm->sample_bits = dmix->shmptr->s.sample_bits;
852                 spcm->channels = dmix->shmptr->s.channels;
853                 spcm->format = dmix->shmptr->s.format;
854                 spcm->boundary = dmix->shmptr->s.boundary;
855                 spcm->info = dmix->shmptr->s.info;
856                 ret = snd_pcm_mmap(spcm);
857                 if (ret < 0) {
858                         SNDERR("unable to mmap channels");
859                         goto _err;
860                 }
861                 dmix->spcm = spcm;
862         }
863
864         ret = shm_sum_create_or_connect(dmix);
865         if (ret < 0) {
866                 SNDERR("unable to initialize sum ring buffer");
867                 goto _err;
868         }
869
870         ret = snd_pcm_direct_initialize_poll_fd(dmix);
871         if (ret < 0) {
872                 SNDERR("unable to initialize poll_fd");
873                 goto _err;
874         }
875
876         mix_select_callbacks(dmix);
877                 
878         pcm->poll_fd = dmix->poll_fd;
879         pcm->poll_events = POLLIN;      /* it's different than other plugins */
880                 
881         pcm->mmap_rw = 1;
882         snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0);
883         snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0);
884         
885         if (dmix->channels == UINT_MAX)
886                 dmix->channels = dmix->shmptr->s.channels;
887
888         snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
889
890         *pcmp = pcm;
891         return 0;
892         
893  _err:
894         if (dmix) {
895                 if (dmix->timer)
896                         snd_timer_close(dmix->timer);
897                 if (dmix->server)
898                         snd_pcm_direct_server_discard(dmix);
899                 if (dmix->client)
900                         snd_pcm_direct_client_discard(dmix);
901                 if (spcm)
902                         snd_pcm_close(spcm);
903                 if (dmix->u.dmix.shmid_sum >= 0)
904                         shm_sum_discard(dmix);
905                 if (dmix->shmid >= 0) {
906                         if (snd_pcm_direct_shm_discard(dmix) > 0) {
907                                 if (dmix->semid >= 0) {
908                                         if (snd_pcm_direct_semaphore_discard(dmix) < 0)
909                                                 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
910                                 }
911                         }
912                 }
913                 if (dmix->bindings)
914                         free(dmix->bindings);
915                 free(dmix);
916         }
917         if (pcm)
918                 snd_pcm_free(pcm);
919         return ret;
920 }
921
922 /*! \page pcm_plugins
923
924 \section pcm_plugins_dmix Plugin: dmix
925
926 This plugin provides direct mixing of multiple streams. The resolution
927 for 32-bit mixing is only 24-bit. The low significant byte is filled with
928 zeros. The extra 8 bits are used for the saturation.
929
930 \code
931 pcm.name {
932         type dmix               # Direct mix
933         ipc_key INT             # unique IPC key
934         ipc_key_add_uid BOOL    # add current uid to unique IPC key
935         ipc_perm INT            # IPC permissions (octal, default 0600)
936         slave STR
937         # or
938         slave {                 # Slave definition
939                 pcm STR         # slave PCM name
940                 # or
941                 pcm { }         # slave PCM definition
942                 format STR      # format definition
943                 rate INT        # rate definition
944                 channels INT
945                 period_time INT # in usec
946                 # or
947                 period_size INT # in bytes
948                 buffer_time INT # in usec
949                 # or
950                 buffer_size INT # in bytes
951                 periods INT     # when buffer_size or buffer_time is not specified
952         }
953         bindings {              # note: this is client independent!!!
954                 N INT           # maps slave channel to client channel N
955         }
956         slowptr BOOL            # slow but more precise pointer updates
957 }
958 \endcode
959
960 <code>ipc_key</code> specfies the unique IPC key in integer.
961 This number must be unique for each different dmix definition,
962 since the shared memory is created with this key number.
963 When <code>ipc_key_add_uid</code> is set true, the uid value is
964 added to the value set in <code>ipc_key</code>.  This will
965 avoid the confliction of the same IPC key with different users
966 concurrently.
967
968 Note that the dmix plugin itself supports only a single configuration.
969 That is, it supports only the fixed rate (default 48000), format
970 (\c S16), channels (2), and period_time (125000).
971 For using other configuration, you have to set the value explicitly
972 in the slave PCM definition.  The rate, format and channels can be
973 covered by an additional \ref pcm_plugins_dmix "plug plugin",
974 but there is only one base configuration, anyway.
975
976 An example configuration for setting 44100 Hz, \c S32_LE format
977 as the slave PCM of "hw:0" is like below:
978 \code
979 pcm.dmix_44 {
980         type dmix
981         ipc_key 321456  # any unique value
982         ipc_key_add_uid true
983         slave {
984                 pcm "hw:0"
985                 format S32_LE
986                 rate 44100
987         }
988 }
989 \endcode
990 You can hear 48000 Hz samples still using this dmix pcm via plug plugin
991 like:
992 \code
993 % aplay -Dplug:dmix_44 foo_48k.wav
994 \endcode
995
996 For using the dmix plugin for OSS emulation device, you have to set
997 the period and the buffer sizes in power of two.  For example,
998 \code
999 pcm.dmixoss {
1000         type dmix
1001         ipc_key 321456  # any unique value
1002         ipc_key_add_uid true
1003         slave {
1004                 pcm "hw:0"
1005                 period_time 0
1006                 period_size 1024  # must be power of 2
1007                 buffer_size 8192  # ditto
1008         }
1009 }
1010 \endcode
1011 <code>period_time 0</code> must be set, too, for resetting the
1012 default value.  In the case of soundcards with multi-channel IO,
1013 adding the bindings would help
1014 \code
1015 pcm.dmixoss {
1016         ...
1017         bindings {
1018                 0 0   # map from 0 to 0
1019                 1 1   # map from 1 to 1
1020         }
1021 }
1022 \endcode
1023 so that only the first two channels are used by dmix.
1024 Also, note that ICE1712 have the limited buffer size, 5513 frames
1025 (corresponding to 640 kB).  In this case, reduce the buffer_size
1026 to 4096.
1027
1028 \subsection pcm_plugins_dmix_funcref Function reference
1029
1030 <UL>
1031   <LI>snd_pcm_dmix_open()
1032   <LI>_snd_pcm_dmix_open()
1033 </UL>
1034
1035 */
1036
1037 /**
1038  * \brief Creates a new dmix PCM
1039  * \param pcmp Returns created PCM handle
1040  * \param name Name of PCM
1041  * \param root Root configuration node
1042  * \param conf Configuration node with dmix PCM description
1043  * \param stream PCM Stream
1044  * \param mode PCM Mode
1045  * \warning Using of this function might be dangerous in the sense
1046  *          of compatibility reasons. The prototype might be freely
1047  *          changed in future.
1048  */
1049 int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
1050                        snd_config_t *root, snd_config_t *conf,
1051                        snd_pcm_stream_t stream, int mode)
1052 {
1053         snd_config_iterator_t i, next;
1054         snd_config_t *slave = NULL, *bindings = NULL, *sconf;
1055         struct slave_params params;
1056         int bsize, psize, ipc_key_add_uid = 0, slowptr = 0;
1057         key_t ipc_key = 0;
1058         mode_t ipc_perm = 0600;
1059         int err;
1060         snd_config_for_each(i, next, conf) {
1061                 snd_config_t *n = snd_config_iterator_entry(i);
1062                 const char *id;
1063                 if (snd_config_get_id(n, &id) < 0)
1064                         continue;
1065                 if (snd_pcm_conf_generic_id(id))
1066                         continue;
1067                 if (strcmp(id, "ipc_key") == 0) {
1068                         long key;
1069                         err = snd_config_get_integer(n, &key);
1070                         if (err < 0) {
1071                                 SNDERR("The field ipc_key must be an integer type");
1072                                 return err;
1073                         }
1074                         ipc_key = key;
1075                         continue;
1076                 }
1077                 if (strcmp(id, "ipc_perm") == 0) {
1078                         char *perm;
1079                         char *endp;
1080                         err = snd_config_get_ascii(n, &perm);
1081                         if (err < 0) {
1082                                 SNDERR("The field ipc_perm must be a valid file permission");
1083                                 return err;
1084                         }
1085                         if (isdigit(*perm) == 0) {
1086                                 SNDERR("The field ipc_perm must be a valid file permission");
1087                                 return -EINVAL;
1088                         }
1089                         ipc_perm = strtol(perm, &endp, 8);
1090                         continue;
1091                 }
1092                 if (strcmp(id, "ipc_key_add_uid") == 0) {
1093                         if ((err = snd_config_get_bool(n)) < 0) {
1094                                 SNDERR("The field ipc_key_add_uid must be a boolean type");
1095                                 return err;
1096                         }
1097                         ipc_key_add_uid = err;
1098                         continue;
1099                 }
1100                 if (strcmp(id, "slave") == 0) {
1101                         slave = n;
1102                         continue;
1103                 }
1104                 if (strcmp(id, "bindings") == 0) {
1105                         bindings = n;
1106                         continue;
1107                 }
1108                 if (strcmp(id, "slowptr") == 0) {
1109                         err = snd_config_get_bool(n);
1110                         if (err < 0)
1111                                 return err;
1112                         slowptr = err;
1113                         continue;
1114                 }
1115                 SNDERR("Unknown field %s", id);
1116                 return -EINVAL;
1117         }
1118         if (!slave) {
1119                 SNDERR("slave is not defined");
1120                 return -EINVAL;
1121         }
1122         if (ipc_key_add_uid)
1123                 ipc_key += getuid();
1124         if (!ipc_key) {
1125                 SNDERR("Unique IPC key is not defined");
1126                 return -EINVAL;
1127         }
1128         /* the default settings, it might be invalid for some hardware */
1129         params.format = SND_PCM_FORMAT_S16;
1130         params.rate = 48000;
1131         params.channels = 2;
1132         params.period_time = -1;
1133         params.buffer_time = -1;
1134         bsize = psize = -1;
1135         params.periods = 3;
1136
1137         err = snd_pcm_slave_conf(root, slave, &sconf, 8,
1138                                  SND_PCM_HW_PARAM_FORMAT, 0, &params.format,
1139                                  SND_PCM_HW_PARAM_RATE, 0, &params.rate,
1140                                  SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
1141                                  SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
1142                                  SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
1143                                  SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
1144                                  SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
1145                                  SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
1146         if (err < 0)
1147                 return err;
1148
1149         /* set a reasonable default */  
1150         if (psize == -1 && params.period_time == -1)
1151                 params.period_time = 125000;    /* 0.125 seconds */
1152
1153         /* sorry, limited features */
1154         if (params.format != SND_PCM_FORMAT_S16 &&
1155             params.format != SND_PCM_FORMAT_S32) {
1156                 SNDERR("invalid format, specify s16 or s32");
1157                 snd_config_delete(sconf);
1158                 return -EINVAL;
1159         }
1160
1161         params.period_size = psize;
1162         params.buffer_size = bsize;
1163
1164         err = snd_pcm_dmix_open(pcmp, name, ipc_key, ipc_perm, &params, bindings, slowptr, root, sconf, stream, mode);
1165         if (err < 0)
1166                 snd_config_delete(sconf);
1167         return err;
1168 }
1169 #ifndef DOC_HIDDEN
1170 SND_DLSYM_BUILD_VERSION(_snd_pcm_dmix_open, SND_PCM_DLSYM_VERSION);
1171 #endif