Jack2  1.9.9
JackAlsaAdapter.h
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 
36  inline void* aligned_calloc ( size_t nmemb, size_t size ) { return ( void* ) calloc ( nmemb, size ); }
37 
38 #define max(x,y) (((x)>(y)) ? (x) : (y))
39 #define 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 
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:
59  AudioParam() :
60  fCardName ( "hw:0" ),
61  fFrequency ( 44100 ),
62  fBuffering ( 512 ),
63  fSoftInputs ( 2 ),
64  fSoftOutputs ( 2 )
65  {}
66 
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 
75  AudioParam& cardName ( const char* n )
76  {
77  fCardName = n;
78  return *this;
79  }
80 
81  AudioParam& frequency ( int f )
82  {
83  fFrequency = f;
84  return *this;
85  }
86 
87  AudioParam& buffering ( int fpb )
88  {
89  fBuffering = fpb;
90  return *this;
91  }
92 
93  void setInputs ( int inputs )
94  {
95  fSoftInputs = inputs;
96  }
97 
98  AudioParam& inputs ( int n )
99  {
100  fSoftInputs = n;
101  return *this;
102  }
103 
104  void setOutputs ( int outputs )
105  {
106  fSoftOutputs = outputs;
107  }
108 
109  AudioParam& outputs ( int n )
110  {
111  fSoftOutputs = n;
112  return *this;
113  }
114  };
115 
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 
155  const char* cardName()
156  {
157  return fCardName;
158  }
159 
160  int frequency()
161  {
162  return fFrequency;
163  }
164 
165  int buffering()
166  {
167  return fBuffering;
168  }
169 
170  jack_default_audio_sample_t** inputSoftChannels()
171  {
172  return fInputSoftChannels;
173  }
174 
175  jack_default_audio_sample_t** outputSoftChannels()
176  {
177  return fOutputSoftChannels;
178  }
179 
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 
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 
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 = max ( fSoftInputs, fCardInputs );
263  assert ( fSoftInputs < 256 );
264  fSoftOutputs = 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 
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 
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 
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 
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 
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, "unknow access mode" );
425  break;
426  }
427  return 0;
428  }
429 
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(max(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(max(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(max(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(max(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, "unknow access mode" );
511  break;
512  }
513  return 0;
514  }
515 
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 
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 
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 
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 
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 );
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
Audio adapter using ALSA API.
The base class for runnable objects, that have an Init and Execute method to be called in a threa...
Definition: JackThread.h:34
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:99
Base class for audio adapters.
Darwin threads. Real-time threads are actually &quot;time constraint&quot; threads.