1 /*
2 Copyright (C) 2008 Grame
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifndef __JackAlsaAdapter__
21 #define __JackAlsaAdapter__
22 
23 #include <math.h>
24 #include <limits.h>
25 #include <assert.h>
26 #include <alsa/asoundlib.h>
27 #include "JackAudioAdapterInterface.h"
28 #include "JackPlatformPlug.h"
29 #include "JackError.h"
30 #include "jack.h"
31 #include "jslist.h"
32 
33 namespace Jack
34 {
35 
aligned_calloc(size_t nmemb,size_t size)36     inline void* aligned_calloc ( size_t nmemb, size_t size ) { return ( void* ) calloc ( nmemb, size ); }
37 
38 #define jack_max(x,y) (((x)>(y)) ? (x) : (y))
39 #define jack_min(x,y) (((x)<(y)) ? (x) : (y))
40 
41 #define check_error(err) if (err) { jack_error("%s:%d, alsa error %d : %s", __FILE__, __LINE__, err, snd_strerror(err)); return err; }
42 #define check_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); return err; }
43 #define display_error_msg(err,msg) if (err) { jack_error("%s:%d, %s : %s(%d)", __FILE__, __LINE__, msg, snd_strerror(err), err); }
44 
45     /**
46      * A convenient class to pass parameters to AudioInterface
47      */
48     class AudioParam
49     {
50         public:
51             const char*     fCardName;
52             unsigned int    fFrequency;
53             int             fBuffering;
54 
55             unsigned int    fSoftInputs;
56             unsigned int    fSoftOutputs;
57 
58         public:
AudioParam()59             AudioParam() :
60                     fCardName ( "hw:0" ),
61                     fFrequency ( 44100 ),
62                     fBuffering ( 512 ),
63                     fSoftInputs ( 2 ),
64                     fSoftOutputs ( 2 )
65             {}
66 
AudioParam(jack_nframes_t buffer_size,jack_nframes_t sample_rate)67             AudioParam ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
68                     fCardName ( "hw:0" ),
69                     fFrequency ( sample_rate ),
70                     fBuffering ( buffer_size ),
71                     fSoftInputs ( 2 ),
72                     fSoftOutputs ( 2 )
73             {}
74 
cardName(const char * n)75             AudioParam& cardName ( const char* n )
76             {
77                 fCardName = n;
78                 return *this;
79             }
80 
frequency(int f)81             AudioParam& frequency ( int f )
82             {
83                 fFrequency = f;
84                 return *this;
85             }
86 
buffering(int fpb)87             AudioParam& buffering ( int fpb )
88             {
89                 fBuffering = fpb;
90                 return *this;
91             }
92 
setInputs(int inputs)93             void setInputs ( int inputs )
94             {
95                 fSoftInputs = inputs;
96             }
97 
inputs(int n)98             AudioParam& inputs ( int n )
99             {
100                 fSoftInputs = n;
101                 return *this;
102             }
103 
setOutputs(int outputs)104             void setOutputs ( int outputs )
105             {
106                 fSoftOutputs = outputs;
107             }
108 
outputs(int n)109             AudioParam& outputs ( int n )
110             {
111                 fSoftOutputs = n;
112                 return *this;
113             }
114     };
115 
116     /**
117      * An ALSA audio interface
118      */
119     class AudioInterface : public AudioParam
120     {
121         public:
122             //device info
123             snd_pcm_t*  fOutputDevice;
124             snd_pcm_t*  fInputDevice;
125             snd_pcm_hw_params_t* fInputParams;
126             snd_pcm_hw_params_t* fOutputParams;
127 
128             //samples info
129             snd_pcm_format_t fSampleFormat;
130             snd_pcm_access_t fSampleAccess;
131 
132             //channels
133             const char*  fCaptureName;
134             const char*  fPlaybackName;
135             unsigned int fCardInputs;
136             unsigned int fCardOutputs;
137 
138             //stream parameters
139             unsigned int fPeriod;
140 
141             //interleaved mode audiocard buffers
142             void* fInputCardBuffer;
143             void* fOutputCardBuffer;
144 
145             //non-interleaved mode audiocard buffers
146             void* fInputCardChannels[256];
147             void* fOutputCardChannels[256];
148 
149             //non-interleaved mod, floating point software buffers
150             jack_default_audio_sample_t* fInputSoftChannels[256];
151             jack_default_audio_sample_t* fOutputSoftChannels[256];
152 
153             //public methods ---------------------------------------------------------
154 
cardName()155             const char* cardName()
156             {
157                 return fCardName;
158             }
159 
frequency()160             int frequency()
161             {
162                 return fFrequency;
163             }
164 
buffering()165             int buffering()
166             {
167                 return fBuffering;
168             }
169 
inputSoftChannels()170             jack_default_audio_sample_t** inputSoftChannels()
171             {
172                 return fInputSoftChannels;
173             }
174 
outputSoftChannels()175             jack_default_audio_sample_t** outputSoftChannels()
176             {
177                 return fOutputSoftChannels;
178             }
179 
AudioParam(ap)180             AudioInterface ( const AudioParam& ap = AudioParam() ) : AudioParam ( ap )
181             {
182                 fInputDevice    = 0;
183                 fOutputDevice   = 0;
184                 fInputParams    = 0;
185                 fOutputParams   = 0;
186                 fPeriod = 2;
187                 fCaptureName    = NULL;
188                 fPlaybackName   = NULL;
189 
190                 fInputCardBuffer = 0;
191                 fOutputCardBuffer = 0;
192 
193                 for ( int i = 0; i < 256; i++ )
194                 {
195                     fInputCardChannels[i] = 0;
196                     fOutputCardChannels[i] = 0;
197                     fInputSoftChannels[i] = 0;
198                     fOutputSoftChannels[i] = 0;
199                 }
200             }
201 
AudioInterface(jack_nframes_t buffer_size,jack_nframes_t sample_rate)202             AudioInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ) :
203                     AudioParam ( buffer_size, sample_rate )
204             {
205                 fInputCardBuffer = 0;
206                 fOutputCardBuffer = 0;
207                 fCaptureName    = NULL;
208                 fPlaybackName   = NULL;
209 
210                 for ( int i = 0; i < 256; i++ )
211                 {
212                     fInputCardChannels[i] = 0;
213                     fOutputCardChannels[i] = 0;
214                     fInputSoftChannels[i] = 0;
215                     fOutputSoftChannels[i] = 0;
216                 }
217             }
218 
219             /**
220              * Open the audio interface
221              */
open()222             int open()
223             {
224                 //open input/output streams
225                 check_error ( snd_pcm_open ( &fInputDevice,  (fCaptureName == NULL) ? fCardName : fCaptureName, SND_PCM_STREAM_CAPTURE, 0 ) );
226                 check_error ( snd_pcm_open ( &fOutputDevice, (fPlaybackName == NULL) ? fCardName : fPlaybackName, SND_PCM_STREAM_PLAYBACK, 0 ) );
227 
228                 //get hardware input parameters
229                 check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) );
230                 setAudioParams ( fInputDevice, fInputParams );
231 
232                 //get hardware output parameters
233                 check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) )
234                 setAudioParams ( fOutputDevice, fOutputParams );
235 
236                 // set the number of physical input and output channels close to what we need
237                 fCardInputs 	= fSoftInputs;
238                 fCardOutputs 	= fSoftOutputs;
239 
240                 snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs);
241                 snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs);
242 
243                 //set input/output param
244                 check_error ( snd_pcm_hw_params ( fInputDevice,  fInputParams ) );
245                 check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) );
246 
247                 //set hardware buffers
248                 if ( fSampleAccess == SND_PCM_ACCESS_RW_INTERLEAVED )
249                 {
250                     fInputCardBuffer = aligned_calloc ( interleavedBufferSize ( fInputParams ), 1 );
251                     fOutputCardBuffer = aligned_calloc ( interleavedBufferSize ( fOutputParams ), 1 );
252                 }
253                 else
254                 {
255                     for ( unsigned int i = 0; i < fCardInputs; i++ )
256                         fInputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fInputParams ), 1 );
257                     for ( unsigned int i = 0; i < fCardOutputs; i++ )
258                         fOutputCardChannels[i] = aligned_calloc ( noninterleavedBufferSize ( fOutputParams ), 1 );
259                 }
260 
261                 //set floating point buffers needed by the dsp code
262                 fSoftInputs = jack_max ( fSoftInputs, fCardInputs );
263                 assert ( fSoftInputs < 256 );
264                 fSoftOutputs = jack_max ( fSoftOutputs, fCardOutputs );
265                 assert ( fSoftOutputs < 256 );
266 
267                 for ( unsigned int i = 0; i < fSoftInputs; i++ )
268                 {
269                     fInputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering, sizeof ( jack_default_audio_sample_t ) );
270                     for ( int j = 0; j < fBuffering; j++ )
271                         fInputSoftChannels[i][j] = 0.0;
272                 }
273 
274                 for ( unsigned int i = 0; i < fSoftOutputs; i++ )
275                 {
276                     fOutputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering, sizeof ( jack_default_audio_sample_t ) );
277                     for ( int j = 0; j < fBuffering; j++ )
278                         fOutputSoftChannels[i][j] = 0.0;
279                 }
280                 return 0;
281             }
282 
close()283             int close()
284             {
285                 snd_pcm_hw_params_free ( fInputParams );
286                 snd_pcm_hw_params_free ( fOutputParams );
287                 snd_pcm_close ( fInputDevice );
288                 snd_pcm_close ( fOutputDevice );
289 
290                 for ( unsigned int i = 0; i < fSoftInputs; i++ )
291                     if ( fInputSoftChannels[i] )
292                         free ( fInputSoftChannels[i] );
293 
294                 for ( unsigned int i = 0; i < fSoftOutputs; i++ )
295                     if ( fOutputSoftChannels[i] )
296                         free ( fOutputSoftChannels[i] );
297 
298                 for ( unsigned int i = 0; i < fCardInputs; i++ )
299                     if ( fInputCardChannels[i] )
300                         free ( fInputCardChannels[i] );
301 
302                 for ( unsigned int i = 0; i < fCardOutputs; i++ )
303                     if ( fOutputCardChannels[i] )
304                         free ( fOutputCardChannels[i] );
305 
306                 if ( fInputCardBuffer )
307                     free ( fInputCardBuffer );
308                 if ( fOutputCardBuffer )
309                     free ( fOutputCardBuffer );
310 
311                 return 0;
312             }
313 
setAudioParams(snd_pcm_t * stream,snd_pcm_hw_params_t * params)314             int setAudioParams ( snd_pcm_t* stream, snd_pcm_hw_params_t* params )
315             {
316                 //set params record with initial values
317                 check_error_msg ( snd_pcm_hw_params_any ( stream, params ), "unable to init parameters" )
318 
319                 //set alsa access mode (and fSampleAccess field) either to non interleaved or interleaved
320                 if ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_NONINTERLEAVED ) )
321                     check_error_msg ( snd_pcm_hw_params_set_access ( stream, params, SND_PCM_ACCESS_RW_INTERLEAVED ),
322                                       "unable to set access mode neither to non-interleaved or to interleaved" );
323                 snd_pcm_hw_params_get_access ( params, &fSampleAccess );
324 
325                 //search for 32-bits or 16-bits format
326                 if ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S32 ) )
327                     check_error_msg ( snd_pcm_hw_params_set_format ( stream, params, SND_PCM_FORMAT_S16 ),
328                                       "unable to set format to either 32-bits or 16-bits" );
329                 snd_pcm_hw_params_get_format ( params, &fSampleFormat );
330 
331                 //set sample frequency
332                 snd_pcm_hw_params_set_rate_near ( stream, params, &fFrequency, 0 );
333 
334                 //set period and period size (buffering)
335                 check_error_msg ( snd_pcm_hw_params_set_period_size ( stream, params, fBuffering, 0 ), "period size not available" );
336                 check_error_msg ( snd_pcm_hw_params_set_periods ( stream, params, fPeriod, 0 ), "number of periods not available" );
337 
338                 return 0;
339             }
340 
interleavedBufferSize(snd_pcm_hw_params_t * params)341             ssize_t interleavedBufferSize ( snd_pcm_hw_params_t* params )
342             {
343                 _snd_pcm_format format;
344                 unsigned int channels;
345                 snd_pcm_hw_params_get_format ( params, &format );
346                 snd_pcm_uframes_t psize;
347                 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
348                 snd_pcm_hw_params_get_channels ( params, &channels );
349                 ssize_t bsize = snd_pcm_format_size ( format, psize * channels );
350                 return bsize;
351             }
352 
noninterleavedBufferSize(snd_pcm_hw_params_t * params)353             ssize_t noninterleavedBufferSize ( snd_pcm_hw_params_t* params )
354             {
355                 _snd_pcm_format format;
356                 snd_pcm_hw_params_get_format ( params, &format );
357                 snd_pcm_uframes_t psize;
358                 snd_pcm_hw_params_get_period_size ( params, &psize, NULL );
359                 ssize_t bsize = snd_pcm_format_size ( format, psize );
360                 return bsize;
361             }
362 
363             /**
364              * Read audio samples from the audio card. Convert samples to floats and take
365              * care of interleaved buffers
366              */
read()367             int read()
368             {
369                 int count, s;
370                 unsigned int c;
371                 switch ( fSampleAccess )
372                 {
373                     case SND_PCM_ACCESS_RW_INTERLEAVED :
374                         count = snd_pcm_readi ( fInputDevice, fInputCardBuffer, fBuffering );
375                         if ( count < 0 )
376                         {
377                             display_error_msg ( count, "reading samples" );
378                             check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
379                         }
380                         if ( fSampleFormat == SND_PCM_FORMAT_S16 )
381                         {
382                             short* buffer16b = ( short* ) fInputCardBuffer;
383                             for ( s = 0; s < fBuffering; s++ )
384                                 for ( c = 0; c < fCardInputs; c++ )
385                                     fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer16b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX));
386                         }
387                         else   // SND_PCM_FORMAT_S32
388                         {
389                             int32_t* buffer32b = ( int32_t* ) fInputCardBuffer;
390                             for ( s = 0; s < fBuffering; s++ )
391                                 for ( c = 0; c < fCardInputs; c++ )
392                                     fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer32b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX));
393                         }
394                         break;
395                     case SND_PCM_ACCESS_RW_NONINTERLEAVED :
396                         count = snd_pcm_readn ( fInputDevice, fInputCardChannels, fBuffering );
397                         if ( count < 0 )
398                         {
399                             display_error_msg ( count, "reading samples" );
400                             check_error_msg ( snd_pcm_prepare ( fInputDevice ), "preparing input stream" );
401                         }
402                         if ( fSampleFormat == SND_PCM_FORMAT_S16 )
403                         {
404                             short* chan16b;
405                             for ( c = 0; c < fCardInputs; c++ )
406                             {
407                                 chan16b = ( short* ) fInputCardChannels[c];
408                                 for ( s = 0; s < fBuffering; s++ )
409                                     fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan16b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX));
410                             }
411                         }
412                         else   // SND_PCM_FORMAT_S32
413                         {
414                             int32_t* chan32b;
415                             for ( c = 0; c < fCardInputs; c++ )
416                             {
417                                 chan32b = ( int32_t* ) fInputCardChannels[c];
418                                 for ( s = 0; s < fBuffering; s++ )
419                                     fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan32b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX));
420                             }
421                         }
422                         break;
423                     default :
424                         check_error_msg ( -10000, "unknown access mode" );
425                         break;
426                 }
427                 return 0;
428             }
429 
430             /**
431              * write the output soft channels to the audio card. Convert sample
432              * format and interleaves buffers when needed
433              */
write()434             int write()
435             {
436                 int count, f;
437                 unsigned int c;
438             recovery:
439                 switch ( fSampleAccess )
440                 {
441                     case SND_PCM_ACCESS_RW_INTERLEAVED :
442                         if ( fSampleFormat == SND_PCM_FORMAT_S16 )
443                         {
444                             short* buffer16b = ( short* ) fOutputCardBuffer;
445                             for ( f = 0; f < fBuffering; f++ )
446                             {
447                                 for ( unsigned int c = 0; c < fCardOutputs; c++ )
448                                 {
449                                     jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
450                                     buffer16b[c + f * fCardOutputs] = short(jack_max(jack_min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX));
451                                 }
452                             }
453                         }
454                         else   // SND_PCM_FORMAT_S32
455                         {
456                             int32_t* buffer32b = ( int32_t* ) fOutputCardBuffer;
457                             for ( f = 0; f < fBuffering; f++ )
458                             {
459                                 for ( unsigned int c = 0; c < fCardOutputs; c++ )
460                                 {
461                                     jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
462                                     buffer32b[c + f * fCardOutputs] = int32_t(jack_max(jack_min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX));
463                                 }
464                             }
465                         }
466                         count = snd_pcm_writei ( fOutputDevice, fOutputCardBuffer, fBuffering );
467                         if ( count < 0 )
468                         {
469                             display_error_msg ( count, "w3" );
470                             int err = snd_pcm_prepare ( fOutputDevice );
471                             check_error_msg ( err, "preparing output stream" );
472                             goto recovery;
473                         }
474                         break;
475                     case SND_PCM_ACCESS_RW_NONINTERLEAVED :
476                         if ( fSampleFormat == SND_PCM_FORMAT_S16 )
477                         {
478                             for ( c = 0; c < fCardOutputs; c++ )
479                             {
480                                 short* chan16b = ( short* ) fOutputCardChannels[c];
481                                 for ( f = 0; f < fBuffering; f++ )
482                                 {
483                                     jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
484                                     chan16b[f] = short(jack_max(jack_min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX));
485                                 }
486                             }
487                         }
488                         else
489                         {
490                             for ( c = 0; c < fCardOutputs; c++ )
491                             {
492                                 int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c];
493                                 for ( f = 0; f < fBuffering; f++ )
494                                 {
495                                     jack_default_audio_sample_t x = fOutputSoftChannels[c][f];
496                                     chan32b[f] = int32_t(jack_max(jack_min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX));
497                                 }
498                             }
499                         }
500                         count = snd_pcm_writen ( fOutputDevice, fOutputCardChannels, fBuffering );
501                         if ( count<0 )
502                         {
503                             display_error_msg ( count, "w3" );
504                             int err = snd_pcm_prepare ( fOutputDevice );
505                             check_error_msg ( err, "preparing output stream" );
506                             goto recovery;
507                         }
508                         break;
509                     default :
510                         check_error_msg ( -10000, "unknown access mode" );
511                         break;
512                 }
513                 return 0;
514             }
515 
516             /**
517              *  print short information on the audio device
518              */
shortinfo()519             int shortinfo()
520             {
521                 int err;
522                 snd_ctl_card_info_t* card_info;
523                 snd_ctl_t* ctl_handle;
524                 err = snd_ctl_open ( &ctl_handle, fCardName, 0 );   check_error ( err );
525                 snd_ctl_card_info_alloca ( &card_info );
526                 err = snd_ctl_card_info ( ctl_handle, card_info );  check_error ( err );
527                 jack_info ( "%s|%d|%d|%d|%d|%s",
528                             snd_ctl_card_info_get_driver ( card_info ),
529                             fCardInputs, fCardOutputs,
530                             fFrequency, fBuffering,
531                             snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ) );
532                 snd_ctl_close(ctl_handle);
533             }
534 
535             /**
536              *  print more detailed information on the audio device
537              */
longinfo()538             int longinfo()
539             {
540                 snd_ctl_card_info_t* card_info;
541                 snd_ctl_t* ctl_handle;
542 
543                 //display info
544                 jack_info ( "Audio Interface Description :" );
545                 jack_info ( "Sampling Frequency : %d, Sample Format : %s, buffering : %d, nperiod : %d",
546                             fFrequency, snd_pcm_format_name ( ( _snd_pcm_format ) fSampleFormat ), fBuffering, fPeriod );
547                 jack_info ( "Software inputs : %2d, Software outputs : %2d", fSoftInputs, fSoftOutputs );
548                 jack_info ( "Hardware inputs : %2d, Hardware outputs : %2d", fCardInputs, fCardOutputs );
549 
550                 //get audio card info and display
551                 check_error ( snd_ctl_open ( &ctl_handle, fCardName, 0 ) );
552                 snd_ctl_card_info_alloca ( &card_info );
553                 check_error ( snd_ctl_card_info ( ctl_handle, card_info ) );
554                 printCardInfo ( card_info );
555 
556                 //display input/output streams info
557                 if ( fSoftInputs > 0 )
558                     printHWParams ( fInputParams );
559                 if ( fSoftOutputs > 0 )
560                     printHWParams ( fOutputParams );
561                 snd_ctl_close(ctl_handle);
562                 return 0;
563             }
564 
printCardInfo(snd_ctl_card_info_t * ci)565             void printCardInfo ( snd_ctl_card_info_t* ci )
566             {
567                 jack_info ( "Card info (address : %p)", ci );
568                 jack_info ( "\tID         = %s", snd_ctl_card_info_get_id ( ci ) );
569                 jack_info ( "\tDriver     = %s", snd_ctl_card_info_get_driver ( ci ) );
570                 jack_info ( "\tName       = %s", snd_ctl_card_info_get_name ( ci ) );
571                 jack_info ( "\tLongName   = %s", snd_ctl_card_info_get_longname ( ci ) );
572                 jack_info ( "\tMixerName  = %s", snd_ctl_card_info_get_mixername ( ci ) );
573                 jack_info ( "\tComponents = %s", snd_ctl_card_info_get_components ( ci ) );
574                 jack_info ( "--------------" );
575             }
576 
printHWParams(snd_pcm_hw_params_t * params)577             void printHWParams ( snd_pcm_hw_params_t* params )
578             {
579                 jack_info ( "HW Params info (address : %p)\n", params );
580 #if 0
581                 jack_info ( "\tChannels    = %d", snd_pcm_hw_params_get_channels ( params, NULL ) );
582                 jack_info ( "\tFormat      = %s", snd_pcm_format_name ( ( _snd_pcm_format ) snd_pcm_hw_params_get_format ( params, NULL ) ) );
583                 jack_info ( "\tAccess      = %s", snd_pcm_access_name ( ( _snd_pcm_access ) snd_pcm_hw_params_get_access ( params, NULL ) ) );
584                 jack_info ( "\tRate        = %d", snd_pcm_hw_params_get_rate ( params, NULL, NULL ) );
585                 jack_info ( "\tPeriods     = %d", snd_pcm_hw_params_get_periods ( params, NULL, NULL ) );
586                 jack_info ( "\tPeriod size = %d", ( int ) snd_pcm_hw_params_get_period_size ( params, NULL, NULL ) );
587                 jack_info ( "\tPeriod time = %d", snd_pcm_hw_params_get_period_time ( params, NULL, NULL ) );
588                 jack_info ( "\tBuffer size = %d", ( int ) snd_pcm_hw_params_get_buffer_size ( params, NULL ) );
589                 jack_info ( "\tBuffer time = %d", snd_pcm_hw_params_get_buffer_time ( params, NULL, NULL ) );
590 #endif
591                 jack_info ( "--------------" );
592             }
593     };
594 
595     /*!
596     \brief Audio adapter using ALSA API.
597     */
598 
599     class JackAlsaAdapter : public JackAudioAdapterInterface, public JackRunnableInterface
600     {
601 
602         private:
603             JackThread fThread;
604             AudioInterface fAudioInterface;
605 
606         public:
607             JackAlsaAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
~JackAlsaAdapter()608             ~JackAlsaAdapter()
609             {}
610 
611             virtual int Open();
612             virtual int Close();
613 
614             virtual int SetSampleRate ( jack_nframes_t sample_rate );
615             virtual int SetBufferSize ( jack_nframes_t buffer_size );
616 
617             virtual bool Init();
618             virtual bool Execute();
619 
620     };
621 
622 }
623 
624 #ifdef __cplusplus
625 extern "C"
626 {
627 #endif
628 
629 #include "JackCompilerDeps.h"
630 #include "driver_interface.h"
631 
632 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor();
633 
634 #ifdef __cplusplus
635 }
636 #endif
637 
638 #endif
639