amend ab3889ff: portaudio backend uses a vector for connections
[ardour.git] / libs / backends / alsa / zita-alsa-pcmi.cc
1 // ----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 //
18 // ----------------------------------------------------------------------------
19
20 #if defined(__NetBSD__)
21 #include <sys/endian.h>
22 #else
23 #include <endian.h>
24 #endif
25 #include <sys/time.h>
26 #include "zita-alsa-pcmi.h"
27
28
29 // Public members ----------------------------------------------------------------------
30
31
32 int zita_alsa_pcmi_major_version (void)
33 {
34         return ZITA_ALSA_PCMI_MAJOR_VERSION;
35 }
36
37
38 int zita_alsa_pcmi_minor_version (void)
39 {
40         return ZITA_ALSA_PCMI_MINOR_VERSION;
41 }
42
43
44 Alsa_pcmi::Alsa_pcmi (
45                 const char        *play_name,
46                 const char        *capt_name,
47                 const char        *ctrl_name,
48                 unsigned int       fsamp,
49                 unsigned int       fsize,
50                 unsigned int       play_nfrag,
51                 unsigned int       capt_nfrag,
52                 unsigned int       debug)
53         : _fsamp (fsamp)
54         , _fsize (fsize)
55         , _play_nfrag (play_nfrag)
56         , _capt_nfrag (capt_nfrag)
57         , _debug (debug)
58         , _state (-1)
59         , _play_handle (0)
60         , _capt_handle (0)
61         , _ctrl_handle (0)
62         , _play_hwpar (0)
63         , _play_swpar (0)
64         , _capt_hwpar (0)
65         , _capt_swpar (0)
66         , _play_nchan (0)
67         , _capt_nchan (0)
68         , _play_xrun (0)
69         , _capt_xrun (0)
70         , _synced (false)
71         , _play_npfd (0)
72         , _capt_npfd (0)
73 {
74         const char *p;
75
76         p = getenv ("ZITA_ALSA_PCMI_DEBUG");
77         if (p && *p) _debug = atoi (p);
78         initialise (play_name, capt_name, ctrl_name);
79 }
80
81
82 Alsa_pcmi::~Alsa_pcmi (void)
83 {
84         if (_play_handle) snd_pcm_close (_play_handle);
85         if (_capt_handle) snd_pcm_close (_capt_handle);
86         if (_ctrl_handle) snd_ctl_close (_ctrl_handle);
87
88         snd_pcm_sw_params_free (_capt_swpar);
89         snd_pcm_hw_params_free (_capt_hwpar);
90         snd_pcm_sw_params_free (_play_swpar);
91         snd_pcm_hw_params_free (_play_hwpar);
92 }
93
94
95 int Alsa_pcmi::pcm_start (void)
96 {
97         unsigned int i, j, n;
98         int          err;
99
100         if (_play_handle)
101         {
102                 n = snd_pcm_avail_update (_play_handle);
103                 if (n != _fsize * _play_nfrag)
104                 {
105                         if (_debug & DEBUG_STAT) fprintf  (stderr, "Alsa_pcmi: full buffer not available at start.\n");
106                         return -1;
107                 }
108                 for (i = 0; i < _play_nfrag; i++)
109                 {
110                         play_init (_fsize);
111                         for (j = 0; j < _play_nchan; j++) clear_chan (j, _fsize);
112                         play_done (_fsize);
113                 }
114                 if ((err = snd_pcm_start (_play_handle)) < 0)
115                 {
116                         if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_start(play): %s.\n", snd_strerror (err));
117                         return -1;
118                 }
119         }
120         if (_capt_handle && !_synced && ((err = snd_pcm_start (_capt_handle)) < 0))
121         {
122                 if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_start(capt): %s.\n", snd_strerror (err));
123                 return -1;
124         }
125
126         return 0;
127 }
128
129
130 int Alsa_pcmi::pcm_stop (void)
131 {
132         int err;
133
134         if (_play_handle && ((err = snd_pcm_drop (_play_handle)) < 0))
135         {
136                 if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_drop(play): %s.\n", snd_strerror (err));
137                 return -1;
138         }
139         if (_capt_handle && !_synced && ((err = snd_pcm_drop (_capt_handle)) < 0))
140         {
141                 if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_drop(capt): %s.\n", snd_strerror (err));
142                 return -1;
143         }
144
145         return 0;
146 }
147
148
149 snd_pcm_sframes_t Alsa_pcmi::pcm_wait (void)
150 {
151         bool              need_capt;
152         bool              need_play;
153         snd_pcm_sframes_t capt_av;
154         snd_pcm_sframes_t play_av;
155         unsigned short    rev;
156         int               i, r, n1, n2;
157
158         _state = 0;
159         need_capt = _capt_handle ? true : false;
160         need_play = _play_handle ? true : false;
161
162         while (need_play || need_capt)
163         {
164                 n1 = 0;
165                 if (need_play)
166                 {
167                         snd_pcm_poll_descriptors (_play_handle, _poll_fd, _play_npfd);
168                         n1 += _play_npfd;
169                 }
170                 n2 = n1;
171                 if (need_capt)
172                 {
173                         snd_pcm_poll_descriptors (_capt_handle, _poll_fd + n1, _capt_npfd);
174                         n2 += _capt_npfd;
175                 }
176                 for (i = 0; i < n2; i++) _poll_fd [i].events |= POLLERR;
177
178                 timespec timeout;
179                 timeout.tv_sec = 1;
180                 timeout.tv_nsec = 0;
181 #if defined(__NetBSD__)
182                 r = pollts (_poll_fd, n2, &timeout, NULL);
183 #else
184                 r = ppoll (_poll_fd, n2, &timeout, NULL);
185 #endif
186
187
188                 if (r < 0)
189                 {
190                         if (errno == EINTR) return 0;
191                         if (_debug & DEBUG_WAIT) fprintf (stderr, "Alsa_pcmi: poll(): %s\n.", strerror (errno));
192                         _state = -1;
193                         return 0;
194                 }
195                 if (r == 0)
196                 {
197                         if (_debug & DEBUG_WAIT) fprintf (stderr, "Alsa_pcmi: poll timed out.\n");
198                         _state = -1;
199                         return 0;
200                 }
201
202                 if (need_play)
203                 {
204                         snd_pcm_poll_descriptors_revents (_play_handle, _poll_fd, n1, &rev);
205                         if (rev & POLLERR)
206                         {
207                                 if (_debug & DEBUG_WAIT) fprintf (stderr, "Alsa_pcmi: error on playback pollfd.\n");
208                                 _state = 1;
209                                 recover ();
210                                 return 0;
211                         }
212                         if (rev & POLLOUT) need_play = false;
213                 }
214                 if (need_capt)
215                 {
216                         snd_pcm_poll_descriptors_revents (_capt_handle, _poll_fd + n1, n2 - n1, &rev);
217                         if (rev & POLLERR)
218                         {
219                                 if (_debug & DEBUG_WAIT) fprintf (stderr, "Alsa_pcmi: error on capture pollfd.\n");
220                                 _state = 1;
221                                 recover ();
222                                 return 0;
223                         }
224                         if (rev & POLLIN) need_capt = false;
225                 }
226         }
227
228         play_av = 999999999;
229         if (_play_handle && (play_av = snd_pcm_avail_update (_play_handle)) < 0)
230         {
231                 _state = -1;
232                 recover ();
233                 return 0;
234         }
235         capt_av = 999999999;
236         if (_capt_handle && (capt_av = snd_pcm_avail_update (_capt_handle)) < 0)
237         {
238                 _state = -1;
239                 recover ();
240                 return 0;
241         }
242
243         return (capt_av < play_av) ? capt_av : play_av;
244 }
245
246
247 int Alsa_pcmi::pcm_idle (int len)
248 {
249         unsigned int       i;
250         snd_pcm_uframes_t  n, k;
251
252         if (_capt_handle)
253         {
254                 n = len;
255                 while (n)
256                 {
257                         k = capt_init (n);
258                         capt_done (k);
259                         n -= k;
260                 }
261         }
262         if (_play_handle)
263         {
264                 n = len;
265                 while (n)
266                 {
267                         k = play_init (n);
268                         for (i = 0; i < _play_nchan; i++) clear_chan (i, k);
269                         play_done (k);
270                         n -= k;
271                 }
272         }
273         return 0;
274 }
275
276
277 int Alsa_pcmi::play_init (snd_pcm_uframes_t len)
278 {
279         unsigned int                   i;
280         const snd_pcm_channel_area_t   *a;
281         int                            err;
282
283         if (!_play_handle) {
284                 return 0;
285         }
286         if ((err = snd_pcm_mmap_begin (_play_handle, &a, &_play_offs, &len)) < 0)
287         {
288                 if (_debug & DEBUG_DATA) fprintf (stderr, "Alsa_pcmi: snd_pcm_mmap_begin(play): %s.\n", snd_strerror (err));
289                 return -1;
290         }
291         _play_step = (a->step) >> 3;
292         for (i = 0; i < _play_nchan; i++, a++)
293         {
294                 _play_ptr [i] = (char *) a->addr + ((a->first + a->step * _play_offs) >> 3);
295         }
296
297         return len;
298 }
299
300
301 int Alsa_pcmi::capt_init (snd_pcm_uframes_t len)
302 {
303         unsigned int                  i;
304         const snd_pcm_channel_area_t  *a;
305         int                           err;
306
307         if (!_capt_handle) {
308                 return 0;
309         }
310
311         if ((err = snd_pcm_mmap_begin (_capt_handle, &a, &_capt_offs, &len)) < 0)
312         {
313                 if (_debug & DEBUG_DATA) fprintf (stderr, "Alsa_pcmi: snd_pcm_mmap_begin(capt): %s.\n", snd_strerror (err));
314                 return -1;
315         }
316         _capt_step = (a->step) >> 3;
317         for (i = 0; i < _capt_nchan; i++, a++)
318         {
319                 _capt_ptr [i] = (char *) a->addr + ((a->first + a->step * _capt_offs) >> 3);
320         }
321
322         return len;
323 }
324
325
326 void Alsa_pcmi::clear_chan (int chan, int len)
327 {
328         _play_ptr [chan] = (this->*Alsa_pcmi::_clear_func)(_play_ptr [chan], len);
329 }
330
331
332 void Alsa_pcmi::play_chan (int chan, const float *src, int len, int step)
333 {
334         _play_ptr [chan] = (this->*Alsa_pcmi::_play_func)(src, _play_ptr [chan], len, step);
335 }
336
337
338 void Alsa_pcmi::capt_chan  (int chan, float *dst, int len, int step)
339 {
340         _capt_ptr [chan] = (this->*Alsa_pcmi::_capt_func)(_capt_ptr [chan], dst, len, step);
341 }
342
343
344 int Alsa_pcmi::play_done (int len)
345 {
346         if (!_play_handle) return 0;
347         return snd_pcm_mmap_commit (_play_handle, _play_offs, len);
348 }
349
350
351 int Alsa_pcmi::capt_done (int len)
352 {
353         if (!_capt_handle) return 0;
354         return snd_pcm_mmap_commit (_capt_handle, _capt_offs, len);
355 }
356
357
358 void Alsa_pcmi::printinfo (void)
359 {
360         fprintf (stdout, "playback :");
361         if (_play_handle)
362         {
363                 fprintf (stdout, "\n  nchan  : %d\n", _play_nchan);
364                 fprintf (stdout, "  fsamp  : %d\n", _fsamp);
365                 fprintf (stdout, "  fsize  : %ld\n", _fsize);
366                 fprintf (stdout, "  nfrag  : %d\n", _play_nfrag);
367                 fprintf (stdout, "  format : %s\n", snd_pcm_format_name (_play_format));
368         }
369         else fprintf (stdout, " not enabled\n");
370         fprintf (stdout, "capture  :");
371         if (_capt_handle)
372         {
373                 fprintf (stdout, "\n  nchan  : %d\n", _capt_nchan);
374                 fprintf (stdout, "  fsamp  : %d\n", _fsamp);
375                 fprintf (stdout, "  fsize  : %ld\n", _fsize);
376                 fprintf (stdout, "  nfrag  : %d\n", _capt_nfrag);
377                 fprintf (stdout, "  format : %s\n", snd_pcm_format_name (_capt_format));
378                 if (_play_handle) fprintf (stdout, "%s\n", _synced ? "synced" : "not synced");
379         }
380         else fprintf (stdout, " not enabled\n");
381 }
382
383
384 // Private members ---------------------------------------------------------------------
385
386
387 void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const char *ctrl_name)
388 {
389         unsigned int          fsamp;
390         snd_pcm_uframes_t     fsize;
391         unsigned int          nfrag;
392         int                   err;
393         int                   dir;
394         snd_ctl_card_info_t  *card;
395
396         if (play_name)
397         {
398                 if (snd_pcm_open (&_play_handle, play_name, SND_PCM_STREAM_PLAYBACK, 0) < 0)
399                 {
400                         _play_handle = 0;
401                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: Cannot open PCM device %s for playback.\n",
402                                         play_name);
403                 }
404         }
405
406         if (capt_name)
407         {
408                 if (snd_pcm_open (&_capt_handle, capt_name, SND_PCM_STREAM_CAPTURE, 0) < 0)
409                 {
410                         _capt_handle = 0;
411                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: Cannot open PCM device %s for capture.\n",
412                                         capt_name);
413                 }
414         }
415
416         if (! _play_handle && ! _capt_handle) return;
417
418         if (ctrl_name)
419         {
420                 snd_ctl_card_info_alloca (&card);
421
422                 if ((err = snd_ctl_open (&_ctrl_handle, ctrl_name, 0)) < 0)
423                 {
424                         if (_debug & DEBUG_INIT) fprintf  (stderr, "Alse_driver: ctl_open(): %s\n",
425                                         snd_strerror (err));
426                         return;
427                 }
428                 if ((err = snd_ctl_card_info (_ctrl_handle, card)) < 0)
429                 {
430                         if (_debug & DEBUG_INIT) fprintf  (stderr, "Alsa_pcmi: ctl_card_info(): %s\n",
431                                         snd_strerror (err));
432                         return;
433                 }
434         }
435
436         _state = -2;
437         if (_play_handle)
438         {
439                 if (snd_pcm_hw_params_malloc (&_play_hwpar) < 0)
440                 {
441                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate playback hw params\n");
442                         return;
443                 }
444                 if (snd_pcm_sw_params_malloc (&_play_swpar) < 0)
445                 {
446                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate playback sw params\n");
447                         return;
448                 }
449                 if (set_hwpar (_play_handle, _play_hwpar, "playback", _play_nfrag, &_play_nchan) < 0) return;
450                 if (set_swpar (_play_handle, _play_swpar, "playback") < 0) return;
451         }
452
453         if (_capt_handle)
454         {
455                 if (snd_pcm_hw_params_malloc (&_capt_hwpar) < 0)
456                 {
457                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate capture hw params\n");
458                         return;
459                 }
460                 if (snd_pcm_sw_params_malloc (&_capt_swpar) < 0)
461                 {
462                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate capture sw params\n");
463                         return;
464                 }
465                 if (set_hwpar (_capt_handle, _capt_hwpar, "capture", _capt_nfrag, &_capt_nchan) < 0) return;
466                 if (set_swpar (_capt_handle, _capt_swpar, "capture") < 0) return;
467         }
468
469         if (_play_handle)
470         {
471                 if (snd_pcm_hw_params_get_rate (_play_hwpar, &fsamp, &dir) || (fsamp != _fsamp) || dir)
472                 {
473                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested sample rate for playback.\n");
474                         _state = -3;
475                         return;
476                 }
477                 if (snd_pcm_hw_params_get_period_size (_play_hwpar, &fsize, &dir) || (fsize != _fsize) || dir)
478                 {
479                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested period size for playback.\n");
480                         _state = -4;
481                         return;
482                 }
483                 if (snd_pcm_hw_params_get_periods (_play_hwpar, &nfrag, &dir) || (nfrag != _play_nfrag) || dir)
484                 {
485                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested number of periods for playback.\n");
486                         _state = -5;
487                         return;
488                 }
489
490                 snd_pcm_hw_params_get_format (_play_hwpar, &_play_format);
491                 snd_pcm_hw_params_get_access (_play_hwpar, &_play_access);
492
493 #if __BYTE_ORDER == __LITTLE_ENDIAN
494                 switch (_play_format)
495                 {
496                         case SND_PCM_FORMAT_FLOAT_LE:
497                                 _clear_func = &Alsa_pcmi::clear_32;
498                                 _play_func  = &Alsa_pcmi::play_float;
499                                 break;
500
501                         case SND_PCM_FORMAT_S32_LE:
502                                 _clear_func = &Alsa_pcmi::clear_32;
503                                 _play_func  = &Alsa_pcmi::play_32;
504                                 break;
505
506                         case SND_PCM_FORMAT_S32_BE:
507                                 _clear_func = &Alsa_pcmi::clear_32;
508                                 _play_func  = &Alsa_pcmi::play_32swap;
509                                 break;
510
511                         case SND_PCM_FORMAT_S24_3LE:
512                                 _clear_func = &Alsa_pcmi::clear_24;
513                                 _play_func  = &Alsa_pcmi::play_24;
514                                 break;
515
516                         case SND_PCM_FORMAT_S24_3BE:
517                                 _clear_func = &Alsa_pcmi::clear_24;
518                                 _play_func  = &Alsa_pcmi::play_24swap;
519                                 break;
520
521                         case SND_PCM_FORMAT_S16_LE:
522                                 _clear_func = &Alsa_pcmi::clear_16;
523                                 _play_func  = &Alsa_pcmi::play_16;
524                                 break;
525
526                         case SND_PCM_FORMAT_S16_BE:
527                                 _clear_func = &Alsa_pcmi::clear_16;
528                                 _play_func  = &Alsa_pcmi::play_16swap;
529                                 break;
530
531                         default:
532                                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't handle playback sample format.\n");
533                                 _state = -6;
534                                 return;
535                 }
536 #elif __BYTE_ORDER == __BIG_ENDIAN
537                 switch (_play_format)
538                 {
539                         case SND_PCM_FORMAT_S32_LE:
540                                 _clear_func = &Alsa_pcmi::clear_32;
541                                 _play_func  = &Alsa_pcmi::play_32swap;
542                                 break;
543
544                         case SND_PCM_FORMAT_S32_BE:
545                                 _clear_func = &Alsa_pcmi::clear_32;
546                                 _play_func  = &Alsa_pcmi::play_32;
547                                 break;
548
549                         case SND_PCM_FORMAT_S24_3LE:
550                                 _clear_func = &Alsa_pcmi::clear_24;
551                                 _play_func  = &Alsa_pcmi::play_24swap;
552                                 break;
553
554                         case SND_PCM_FORMAT_S24_3BE:
555                                 _clear_func = &Alsa_pcmi::clear_24;
556                                 _play_func  = &Alsa_pcmi::play_24;
557                                 break;
558
559                         case SND_PCM_FORMAT_S16_LE:
560                                 _clear_func = &Alsa_pcmi::clear_16;
561                                 _play_func  = &Alsa_pcmi::play_16swap;
562                                 break;
563
564                         case SND_PCM_FORMAT_S16_BE:
565                                 _clear_func = &Alsa_pcmi::clear_16;
566                                 _play_func  = &Alsa_pcmi::play_16;
567                                 break;
568
569                         default:
570                                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't handle playback sample format.\n");
571                                 _state = -6;
572                                 return;
573                 }
574 #else
575 #error "System byte order is undefined or not supported"
576 #endif
577
578                 _play_npfd = snd_pcm_poll_descriptors_count (_play_handle);
579         }
580
581         if (_capt_handle)
582         {
583                 if (snd_pcm_hw_params_get_rate (_capt_hwpar, &fsamp, &dir) || (fsamp != _fsamp) || dir)
584                 {
585                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested sample rate for capture.\n");
586                         _state = -3;
587                         return;
588                 }
589                 if (snd_pcm_hw_params_get_period_size (_capt_hwpar, &fsize, &dir) || (fsize != _fsize) || dir)
590                 {
591                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested period size for capture.\n");
592                         _state = -4;
593                         return;
594                 }
595                 if (snd_pcm_hw_params_get_periods (_capt_hwpar, &nfrag, &dir) || (nfrag != _capt_nfrag) || dir)
596                 {
597                         if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested number of periods for capture.\n");
598                         _state = -5;
599                         return;
600                 }
601
602                 if (_play_handle) _synced = ! snd_pcm_link (_play_handle, _capt_handle);
603
604                 snd_pcm_hw_params_get_format (_capt_hwpar, &_capt_format);
605                 snd_pcm_hw_params_get_access (_capt_hwpar, &_capt_access);
606
607 #if __BYTE_ORDER == __LITTLE_ENDIAN
608                 switch (_capt_format)
609                 {
610                         case SND_PCM_FORMAT_FLOAT_LE:
611                                 _capt_func  = &Alsa_pcmi::capt_float;
612                                 break;
613
614                         case SND_PCM_FORMAT_S32_LE:
615                                 _capt_func  = &Alsa_pcmi::capt_32;
616                                 break;
617
618                         case SND_PCM_FORMAT_S32_BE:
619                                 _capt_func  = &Alsa_pcmi::capt_32swap;
620                                 break;
621
622                         case SND_PCM_FORMAT_S24_3LE:
623                                 _capt_func  = &Alsa_pcmi::capt_24;
624                                 break;
625
626                         case SND_PCM_FORMAT_S24_3BE:
627                                 _capt_func  = &Alsa_pcmi::capt_24swap;
628                                 break;
629
630                         case SND_PCM_FORMAT_S16_LE:
631                                 _capt_func  = &Alsa_pcmi::capt_16;
632                                 break;
633
634                         case SND_PCM_FORMAT_S16_BE:
635                                 _capt_func  = &Alsa_pcmi::capt_16swap;
636                                 break;
637
638                         default:
639                                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't handle capture sample format.\n");
640                                 _state = -6;
641                                 return;
642                 }
643 #elif __BYTE_ORDER == __BIG_ENDIAN
644                 switch (_capt_format)
645                 {
646                         case SND_PCM_FORMAT_S32_LE:
647                                 _capt_func  = &Alsa_pcmi::capt_32swap;
648                                 break;
649
650                         case SND_PCM_FORMAT_S32_BE:
651                                 _capt_func  = &Alsa_pcmi::capt_32;
652                                 break;
653
654                         case SND_PCM_FORMAT_S24_3LE:
655                                 _capt_func  = &Alsa_pcmi::capt_24swap;
656                                 break;
657
658                         case SND_PCM_FORMAT_S24_3BE:
659                                 _capt_func  = &Alsa_pcmi::capt_24;
660                                 break;
661
662                         case SND_PCM_FORMAT_S16_LE:
663                                 _capt_func  = &Alsa_pcmi::capt_16swap;
664                                 break;
665
666                         case SND_PCM_FORMAT_S16_BE:
667                                 _capt_func  = &Alsa_pcmi::capt_16;
668                                 break;
669
670                         default:
671                                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't handle capture sample format.\n");
672                                 _state = -6;
673                                 return;
674                 }
675 #else
676 #error "System byte order is undefined or not supported"
677 #endif
678
679                 _capt_npfd = snd_pcm_poll_descriptors_count (_capt_handle);
680         }
681
682         if (_play_npfd + _capt_npfd > MAXPFD)
683         {
684                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: interface requires more than %d pollfd\n", MAXPFD);
685                 return;
686         }
687
688         _state = 0;
689 }
690
691
692 int Alsa_pcmi::set_hwpar (snd_pcm_t *handle,  snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int nfrag, unsigned int *nchan)
693 {
694         bool err;
695
696         if (snd_pcm_hw_params_any (handle, hwpar) < 0)
697         {
698                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: no %s hw configurations available.\n",
699                                 sname);
700                 return -1;
701         }
702         if (snd_pcm_hw_params_set_periods_integer (handle, hwpar) < 0)
703         {
704                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s period size to integral value.\n",
705                                 sname);
706                 return -1;
707         }
708         if (   (snd_pcm_hw_params_set_access (handle, hwpar, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0)
709                         && (snd_pcm_hw_params_set_access (handle, hwpar, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0)
710                         && (snd_pcm_hw_params_set_access (handle, hwpar, SND_PCM_ACCESS_MMAP_COMPLEX) < 0))
711         {
712                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: the %s interface doesn't support mmap-based access.\n",
713                                 sname);
714                 return -1;
715         }
716         if (_debug & FORCE_16B)
717         {
718                 err =    (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S16_LE) < 0)
719                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S16_BE) < 0);
720         }
721         else
722         {
723                 err =    (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_FLOAT_LE) < 0)
724                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S32_LE) < 0)
725                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S32_BE) < 0)
726                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S24_3LE) < 0)
727                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S24_3BE) < 0)
728                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S16_LE) < 0)
729                         && (snd_pcm_hw_params_set_format (handle, hwpar, SND_PCM_FORMAT_S16_BE) < 0);
730         }
731         if (err)
732         {
733                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: no supported sample format on %s interface.\n.",
734                                 sname);
735                 return -1;
736         }
737         if (snd_pcm_hw_params_set_rate (handle, hwpar, _fsamp, 0) < 0)
738         {
739                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s sample rate to %u.\n",
740                                 sname, _fsamp);
741                 return -3;
742         }
743         snd_pcm_hw_params_get_channels_max (hwpar, nchan);
744         if (*nchan > 1024)
745         {
746                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: detected more than 1024 %s channels, reset to 2.\n",
747                                 sname);
748                 *nchan = 2;
749         }
750         if (_debug & FORCE_2CH)
751         {
752                 *nchan = 2;
753         }
754         if (*nchan > MAXCHAN)
755         {
756                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: number of %s channels reduced to %d.\n",
757                                 sname, MAXCHAN);
758                 *nchan = MAXCHAN;
759         }
760
761         if (snd_pcm_hw_params_set_channels (handle, hwpar, *nchan) < 0)
762         {
763                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s channel count to %u.\n",
764                                 sname, *nchan);
765                 return -1;
766         }
767         if (snd_pcm_hw_params_set_period_size (handle, hwpar, _fsize, 0) < 0)
768         {
769                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s period size to %lu.\n",
770                                 sname, _fsize);
771                 return -4;
772         }
773         if (snd_pcm_hw_params_set_periods (handle, hwpar, nfrag, 0) < 0)
774         {
775                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s periods to %u.\n",
776                                 sname, nfrag);
777                 return -5;
778         }
779         if (snd_pcm_hw_params_set_buffer_size (handle, hwpar, _fsize * nfrag) < 0)
780         {
781                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s buffer length to %lu.\n",
782                                 sname, _fsize * nfrag);
783                 return -4;
784         }
785         if (snd_pcm_hw_params (handle, hwpar) < 0)
786         {
787                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s hardware parameters.\n",
788                                 sname);
789                 return -1;
790         }
791
792         return 0;
793 }
794
795
796 int Alsa_pcmi::set_swpar (snd_pcm_t *handle, snd_pcm_sw_params_t *swpar, const char *sname)
797 {
798         int err;
799
800         snd_pcm_sw_params_current (handle, swpar);
801
802         if ((err = snd_pcm_sw_params_set_tstamp_mode (handle, swpar, SND_PCM_TSTAMP_MMAP)) < 0)
803         {
804                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s timestamp mode to %u.\n",
805                                 sname, SND_PCM_TSTAMP_MMAP);
806                 return -1;
807         }
808         if ((err = snd_pcm_sw_params_set_avail_min (handle, swpar, _fsize)) < 0)
809         {
810                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s avail_min to %lu.\n",
811                                 sname, _fsize);
812                 return -1;
813         }
814         if ((err = snd_pcm_sw_params (handle, swpar)) < 0)
815         {
816                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s software parameters.\n",
817                                 sname);
818                 return -1;
819         }
820
821         return 0;
822 }
823
824
825 int Alsa_pcmi::recover (void)
826 {
827         int                err;
828         snd_pcm_status_t   *stat;
829
830         snd_pcm_status_alloca (&stat);
831
832         if (_play_handle)
833         {
834                 if ((err = snd_pcm_status (_play_handle, stat)) < 0)
835                 {
836                         if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_status(play): %s\n",
837                                         snd_strerror (err));
838                 }
839                 _play_xrun = xruncheck (stat);
840         }
841         if (_capt_handle)
842         {
843                 if ((err = snd_pcm_status (_capt_handle, stat)) < 0)
844                 {
845                         if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_status(capt): %s\n",
846                                         snd_strerror (err));
847                 }
848                 _capt_xrun = xruncheck (stat);
849         }
850
851         if (pcm_stop ()) return -1;
852         if (_play_handle && ((err = snd_pcm_prepare (_play_handle)) < 0))
853         {
854                 if (_debug & DEBUG_STAT) fprintf (stderr, "Alsa_pcmi: pcm_prepare(play): %s\n",
855                                 snd_strerror (err));
856                 return -1;
857         }
858         if (_capt_handle && !_synced && ((err = snd_pcm_prepare (_capt_handle)) < 0))
859         {
860                 if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: pcm_prepare(capt): %s\n",
861                                 snd_strerror (err));
862                 return -1;
863         }
864         if (pcm_start ()) return -1;
865
866         return 0;
867 }
868
869
870 float Alsa_pcmi::xruncheck (snd_pcm_status_t *stat)
871 {
872         struct timeval   tupd, trig;
873         int              ds, du;
874
875         if (snd_pcm_status_get_state (stat) == SND_PCM_STATE_XRUN)
876         {
877                 snd_pcm_status_get_tstamp (stat, &tupd);
878                 snd_pcm_status_get_trigger_tstamp (stat, &trig);
879                 ds = tupd.tv_sec - trig.tv_sec;
880                 du = tupd.tv_usec - trig.tv_usec;
881                 if (du < 0)
882                 {
883                         du += 1000000;
884                         ds -= 1;
885                 }
886                 return ds + 1e-6f * du;
887         }
888         return 0.0f;
889 }
890
891
892 char *Alsa_pcmi::clear_16 (char *dst, int nfrm)
893 {
894         while (nfrm--)
895         {
896                 *((short int *) dst) = 0;
897                 dst += _play_step;
898         }
899         return dst;
900 }
901
902 char *Alsa_pcmi::clear_24 (char *dst, int nfrm)
903 {
904         while (nfrm--)
905         {
906                 dst [0] = 0;
907                 dst [1] = 0;
908                 dst [2] = 0;
909                 dst += _play_step;
910         }
911         return dst;
912 }
913
914 char *Alsa_pcmi::clear_32 (char *dst, int nfrm)
915 {
916         while (nfrm--)
917         {
918                 *((int *) dst) = 0;
919                 dst += _play_step;
920         }
921         return dst;
922 }
923
924
925 char *Alsa_pcmi::play_16 (const float *src, char *dst, int nfrm, int step)
926 {
927         float     s;
928         short int d;
929
930         while (nfrm--)
931         {
932                 s = *src;
933                 if      (s >  1) d = 0x7fff;
934                 else if (s < -1) d = 0x8001;
935                 else d = (short int)((float) 0x7fff * s);
936                 *((short int *) dst) = d;
937                 dst += _play_step;
938                 src += step;
939         }
940         return dst;
941 }
942
943 char *Alsa_pcmi::play_16swap (const float *src, char *dst, int nfrm, int step)
944 {
945         float     s;
946         short int d;
947
948         while (nfrm--)
949         {
950                 s = *src;
951                 if      (s >  1) d = 0x7fff;
952                 else if (s < -1) d = 0x8001;
953                 else d = (short int)((float) 0x7fff * s);
954                 dst [0] = d >> 8;
955                 dst [1] = d;
956                 dst += _play_step;
957                 src += step;
958         }
959         return dst;
960 }
961
962 char *Alsa_pcmi::play_24 (const float *src, char *dst, int nfrm, int step)
963 {
964         float   s;
965         int     d;
966
967         while (nfrm--)
968         {
969                 s = *src;
970                 if      (s >  1) d = 0x007fffff;
971                 else if (s < -1) d = 0x00800001;
972                 else d = (int)((float) 0x007fffff * s);
973                 dst [0] = d;
974                 dst [1] = d >> 8;
975                 dst [2] = d >> 16;
976                 dst += _play_step;
977                 src += step;
978         }
979         return dst;
980 }
981
982 char *Alsa_pcmi::play_24swap (const float *src, char *dst, int nfrm, int step)
983 {
984         float   s;
985         int     d;
986
987         while (nfrm--)
988         {
989                 s = *src;
990                 if      (s >  1) d = 0x007fffff;
991                 else if (s < -1) d = 0x00800001;
992                 else d = (int)((float) 0x007fffff * s);
993                 dst [0] = d >> 16;
994                 dst [1] = d >> 8;
995                 dst [2] = d;
996                 dst += _play_step;
997                 src += step;
998         }
999         return dst;
1000 }
1001
1002 char *Alsa_pcmi::play_32 (const float *src, char *dst, int nfrm, int step)
1003 {
1004         float   s;
1005         int     d;
1006
1007         while (nfrm--)
1008         {
1009                 s = *src;
1010                 if      (s >  1) d = 0x007fffff;
1011                 else if (s < -1) d = 0x00800001;
1012                 else d = (int)((float) 0x007fffff * s);
1013                 *((int *) dst) = d << 8;
1014                 dst += _play_step;
1015                 src += step;
1016         }
1017         return dst;
1018 }
1019
1020 char *Alsa_pcmi::play_32swap (const float *src, char *dst, int nfrm, int step)
1021 {
1022         float   s;
1023         int     d;
1024
1025         while (nfrm--)
1026         {
1027                 s = *src;
1028                 if      (s >  1) d = 0x007fffff;
1029                 else if (s < -1) d = 0x00800001;
1030                 else d = (int)((float) 0x007fffff * s);
1031                 dst [0] = d >> 16;
1032                 dst [1] = d >> 8;
1033                 dst [2] = d;
1034                 dst [3] = 0;
1035                 dst += _play_step;
1036                 src += step;
1037         }
1038         return dst;
1039 }
1040
1041 char *Alsa_pcmi::play_float (const float *src, char *dst, int nfrm, int step)
1042 {
1043         while (nfrm--)
1044         {
1045                 *((float *) dst) = *src;
1046                 dst += _play_step;
1047                 src += step;
1048         }
1049         return dst;
1050 }
1051
1052
1053 const char *Alsa_pcmi::capt_16 (const char *src, float *dst, int nfrm, int step)
1054 {
1055         while (nfrm--)
1056         {
1057                 const short int s = *((short int const *) src);
1058                 const float d = (float) s / (float) 0x7fff;
1059                 *dst = d;
1060                 dst += step;
1061                 src += _capt_step;
1062         }
1063         return src;
1064 }
1065
1066 const char *Alsa_pcmi::capt_16swap (const char *src, float *dst, int nfrm, int step)
1067 {
1068         float     d;
1069         short int s;
1070
1071         while (nfrm--)
1072         {
1073                 s =  (src [0] & 0xFF) << 8;
1074                 s += (src [1] & 0xFF);
1075                 d = (float) s / (float) 0x7fff;
1076                 *dst = d;
1077                 dst += step;
1078                 src += _capt_step;
1079         }
1080         return src;
1081 }
1082
1083 const char *Alsa_pcmi::capt_24 (const char *src, float *dst, int nfrm, int step)
1084 {
1085         float   d;
1086         int     s;
1087
1088         while (nfrm--)
1089         {
1090                 s  = (src [0] & 0xFF);
1091                 s += (src [1] & 0xFF) << 8;
1092                 s += (src [2] & 0xFF) << 16;
1093                 if (s & 0x00800000) s-= 0x01000000;
1094                 d = (float) s / (float) 0x007fffff;
1095                 *dst = d;
1096                 dst += step;
1097                 src += _capt_step;
1098         }
1099         return src;
1100 }
1101
1102 const char *Alsa_pcmi::capt_24swap (const char *src, float *dst, int nfrm, int step)
1103 {
1104         float   d;
1105         int     s;
1106
1107         while (nfrm--)
1108         {
1109                 s  = (src [0] & 0xFF) << 16;
1110                 s += (src [1] & 0xFF) << 8;
1111                 s += (src [2] & 0xFF);
1112                 if (s & 0x00800000) s-= 0x01000000;
1113                 d = (float) s / (float) 0x007fffff;
1114                 *dst = d;
1115                 dst += step;
1116                 src += _capt_step;
1117         }
1118         return src;
1119 }
1120
1121 const char *Alsa_pcmi::capt_32 (const char *src, float *dst, int nfrm, int step)
1122 {
1123         while (nfrm--)
1124         {
1125                 const int s = *((int const *) src);
1126                 const float d = (float) s / (float) 0x7fffff00;
1127                 *dst = d;
1128                 dst += step;
1129                 src += _capt_step;
1130         }
1131         return src;
1132 }
1133
1134 const char *Alsa_pcmi::capt_32swap (const char *src, float *dst, int nfrm, int step)
1135 {
1136         float   d;
1137         int     s;
1138
1139         while (nfrm--)
1140         {
1141                 s  = (src [0] & 0xFF) << 24;
1142                 s += (src [1] & 0xFF) << 16;
1143                 s += (src [2] & 0xFF) << 8;
1144                 d = (float) s / (float) 0x7fffff00;
1145                 *dst = d;
1146                 dst += step;
1147                 src += _capt_step;
1148         }
1149         return src;
1150 }
1151
1152 const char *Alsa_pcmi::capt_float (const char *src, float *dst, int nfrm, int step)
1153 {
1154         while (nfrm--)
1155         {
1156                 *dst = *((float const *) src);
1157                 dst += step;
1158                 src += _capt_step;
1159         }
1160         return src;
1161 }