2 Copyright (C) 2008 Grame
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.
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.
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.
20 #if defined(HAVE_CONFIG_H)
24 #include "JackAlsaAdapter.h"
25 #include "JackServerGlobals.h"
26 #include "JackEngineControl.h"
31 JackAlsaAdapter::JackAlsaAdapter ( jack_nframes_t buffer_size
, jack_nframes_t sample_rate
, const JSList
* params
) :
32 JackAudioAdapterInterface ( buffer_size
, sample_rate
),
34 fAudioInterface ( buffer_size
, sample_rate
)
37 const jack_driver_param_t
* param
;
40 fPlaybackChannels
= 2;
42 fAudioInterface
.fPeriod
= 2;
44 for ( node
= params
; node
; node
= jack_slist_next ( node
) )
46 param
= ( const jack_driver_param_t
* ) node
->data
;
48 switch ( param
->character
)
51 fCaptureChannels
= param
->value
.ui
;
54 fPlaybackChannels
= param
->value
.ui
;
63 fAudioInterface
.fPeriod
= param
->value
.ui
;
66 fAudioInterface
.fCardName
= strdup ( param
->value
.str
);
69 fAudioInterface
.fFrequency
= param
->value
.ui
;
70 SetAdaptedSampleRate ( param
->value
.ui
);
73 fAudioInterface
.fBuffering
= param
->value
.ui
;
74 SetAdaptedBufferSize ( param
->value
.ui
);
77 fQuality
= param
->value
.ui
;
80 fRingbufferCurSize
= param
->value
.ui
;
86 fAudioInterface
.setInputs ( fCaptureChannels
);
87 fAudioInterface
.setOutputs ( fPlaybackChannels
);
90 int JackAlsaAdapter::Open()
92 //open audio interface
93 if ( fAudioInterface
.open() )
96 //start adapter thread
97 if ( fThread
.StartSync() < 0 )
99 jack_error ( "Cannot start audioadapter thread" );
104 fAudioInterface
.longinfo();
106 //turn the thread realtime
107 fThread
.AcquireRealTime ( JackServerGlobals::fInstance
->GetEngineControl()->fClientPriority
);
111 int JackAlsaAdapter::Close()
114 fTable
.Save(fHostBufferSize
, fHostSampleRate
, fAdaptedSampleRate
, fAdaptedBufferSize
);
116 switch ( fThread
.GetStatus() )
119 // Kill the thread in Init phase
120 case JackThread::kStarting
:
121 case JackThread::kIniting
:
122 if ( fThread
.Kill() < 0 )
124 jack_error ( "Cannot kill thread" );
129 // Stop when the thread cycle is finished
130 case JackThread::kRunning
:
131 if ( fThread
.Stop() < 0 )
133 jack_error ( "Cannot stop thread" );
141 return fAudioInterface
.close();
144 bool JackAlsaAdapter::Init()
146 //fill the hardware buffers
147 for ( unsigned int i
= 0; i
< fAudioInterface
.fPeriod
; i
++ )
148 fAudioInterface
.write();
152 bool JackAlsaAdapter::Execute()
154 //read data from audio interface
155 if (fAudioInterface
.read() < 0)
158 PushAndPull(fAudioInterface
.fInputSoftChannels
, fAudioInterface
.fOutputSoftChannels
, fAdaptedBufferSize
);
160 //write data to audio interface
161 if (fAudioInterface
.write() < 0)
167 int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate
)
169 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate
);
174 int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size
)
176 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size
);
188 SERVER_EXPORT jack_driver_desc_t
* jack_get_descriptor()
190 jack_driver_desc_t
*desc
;
192 desc
= ( jack_driver_desc_t
* ) calloc ( 1, sizeof ( jack_driver_desc_t
) );
194 strcpy ( desc
->name
, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
195 strcpy ( desc
->desc
, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
198 desc
->params
= ( jack_driver_param_desc_t
* ) calloc ( desc
->nparams
, sizeof ( jack_driver_param_desc_t
) );
201 strcpy ( desc
->params
[i
].name
, "capture" );
202 desc
->params
[i
].character
= 'C';
203 desc
->params
[i
].type
= JackDriverParamString
;
204 strcpy ( desc
->params
[i
].value
.str
, "none" );
205 strcpy ( desc
->params
[i
].short_desc
,
206 "Provide capture ports. Optionally set device" );
207 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
210 strcpy ( desc
->params
[i
].name
, "playback" );
211 desc
->params
[i
].character
= 'P';
212 desc
->params
[i
].type
= JackDriverParamString
;
213 strcpy ( desc
->params
[i
].value
.str
, "none" );
214 strcpy ( desc
->params
[i
].short_desc
,
215 "Provide playback ports. Optionally set device" );
216 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
219 strcpy ( desc
->params
[i
].name
, "device" );
220 desc
->params
[i
].character
= 'd';
221 desc
->params
[i
].type
= JackDriverParamString
;
222 strcpy ( desc
->params
[i
].value
.str
, "hw:0" );
223 strcpy ( desc
->params
[i
].short_desc
, "ALSA device name" );
224 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
227 strcpy ( desc
->params
[i
].name
, "rate" );
228 desc
->params
[i
].character
= 'r';
229 desc
->params
[i
].type
= JackDriverParamUInt
;
230 desc
->params
[i
].value
.ui
= 48000U;
231 strcpy ( desc
->params
[i
].short_desc
, "Sample rate" );
232 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
235 strcpy ( desc
->params
[i
].name
, "periodsize" );
236 desc
->params
[i
].character
= 'p';
237 desc
->params
[i
].type
= JackDriverParamUInt
;
238 desc
->params
[i
].value
.ui
= 512U;
239 strcpy ( desc
->params
[i
].short_desc
, "Period size" );
240 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
243 strcpy ( desc
->params
[i
].name
, "nperiods" );
244 desc
->params
[i
].character
= 'n';
245 desc
->params
[i
].type
= JackDriverParamUInt
;
246 desc
->params
[i
].value
.ui
= 2U;
247 strcpy ( desc
->params
[i
].short_desc
, "Number of periods of playback latency" );
248 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
251 strcpy ( desc
->params
[i
].name
, "duplex" );
252 desc
->params
[i
].character
= 'D';
253 desc
->params
[i
].type
= JackDriverParamBool
;
254 desc
->params
[i
].value
.i
= true;
255 strcpy ( desc
->params
[i
].short_desc
,
256 "Provide both capture and playback ports" );
257 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
260 strcpy ( desc
->params
[i
].name
, "inchannels" );
261 desc
->params
[i
].character
= 'i';
262 desc
->params
[i
].type
= JackDriverParamUInt
;
263 desc
->params
[i
].value
.i
= 0;
264 strcpy ( desc
->params
[i
].short_desc
,
265 "Number of capture channels (defaults to hardware max)" );
266 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
269 strcpy ( desc
->params
[i
].name
, "outchannels" );
270 desc
->params
[i
].character
= 'o';
271 desc
->params
[i
].type
= JackDriverParamUInt
;
272 desc
->params
[i
].value
.i
= 0;
273 strcpy ( desc
->params
[i
].short_desc
,
274 "Number of playback channels (defaults to hardware max)" );
275 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
278 strcpy(desc
->params
[i
].name
, "quality");
279 desc
->params
[i
].character
= 'q';
280 desc
->params
[i
].type
= JackDriverParamInt
;
281 desc
->params
[i
].value
.ui
= 0;
282 strcpy(desc
->params
[i
].short_desc
, "Resample algorithm quality (0 - 4)");
283 strcpy(desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
286 strcpy(desc
->params
[i
].name
, "ring-buffer");
287 desc
->params
[i
].character
= 'g';
288 desc
->params
[i
].type
= JackDriverParamInt
;
289 desc
->params
[i
].value
.ui
= 32768;
290 strcpy(desc
->params
[i
].short_desc
, "Fixed ringbuffer size");
291 strcpy(desc
->params
[i
].long_desc
, "Fixed ringbuffer size (if not set => automatic adaptative)");