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 "JackServer.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 for ( node
= params
; node
; node
= jack_slist_next ( node
) )
44 param
= ( const jack_driver_param_t
* ) node
->data
;
46 switch ( param
->character
)
49 fCaptureChannels
= param
->value
.ui
;
52 fPlaybackChannels
= param
->value
.ui
;
61 fAudioInterface
.fPeriod
= param
->value
.ui
;
64 fAudioInterface
.fCardName
= strdup ( param
->value
.str
);
67 SetAdaptedSampleRate ( param
->value
.ui
);
70 SetAdaptedBufferSize ( param
->value
.ui
);
75 fAudioInterface
.setInputs ( fCaptureChannels
);
76 fAudioInterface
.setOutputs ( fPlaybackChannels
);
79 int JackAlsaAdapter::Open()
81 //open audio interface
82 if ( fAudioInterface
.open() )
85 //start adapter thread
86 if ( fThread
.StartSync() < 0 )
88 jack_error ( "Cannot start audioadapter thread" );
93 fAudioInterface
.longinfo();
95 //turn the thread realtime
96 fThread
.AcquireRealTime ( JackServer::fInstance
->GetEngineControl()->fPriority
);
101 int JackAlsaAdapter::Close()
106 switch ( fThread
.GetStatus() )
109 // Kill the thread in Init phase
110 case JackThread::kStarting
:
111 case JackThread::kIniting
:
112 if ( fThread
.Kill() < 0 )
114 jack_error ( "Cannot kill thread" );
119 // Stop when the thread cycle is finished
120 case JackThread::kRunning
:
121 if ( fThread
.Stop() < 0 )
123 jack_error ( "Cannot stop thread" );
131 return fAudioInterface
.close();
134 bool JackAlsaAdapter::Init()
136 //fill the hardware buffers
137 for ( unsigned int i
= 0; i
< fAudioInterface
.fPeriod
; i
++ )
138 fAudioInterface
.write();
142 bool JackAlsaAdapter::Execute()
144 //read data from audio interface
145 if ( fAudioInterface
.read() < 0 )
148 bool failure
= false;
150 //compute resampling factor
151 jack_nframes_t time1
, time2
;
152 ResampleFactor ( time1
, time2
);
155 for ( int i
= 0; i
< fCaptureChannels
; i
++ )
157 fCaptureRingBuffer
[i
]->SetRatio ( time1
, time2
);
158 if ( fCaptureRingBuffer
[i
]->WriteResample ( fAudioInterface
.fInputSoftChannels
[i
], fAdaptedBufferSize
) < fAdaptedBufferSize
)
162 for ( int i
= 0; i
< fPlaybackChannels
; i
++ )
164 fPlaybackRingBuffer
[i
]->SetRatio ( time2
, time1
);
165 if ( fPlaybackRingBuffer
[i
]->ReadResample ( fAudioInterface
.fOutputSoftChannels
[i
], fAdaptedBufferSize
) < fAdaptedBufferSize
)
170 fTable
.Write ( time1
, time2
, double ( time1
) / double ( time2
), double ( time2
) / double ( time1
),
171 fCaptureRingBuffer
[0]->ReadSpace(), fPlaybackRingBuffer
[0]->WriteSpace() );
174 //write data to audio interface
175 if ( fAudioInterface
.write() < 0 )
178 //reset all ringbuffers in case of failure
181 jack_error ( "JackAlsaAdapter::Execute ringbuffer failure... reset" );
188 int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate
)
190 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate
);
195 int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size
)
197 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size
);
209 SERVER_EXPORT jack_driver_desc_t
* jack_get_descriptor()
211 jack_driver_desc_t
*desc
;
212 jack_driver_param_desc_t
* params
;
215 desc
= (jack_driver_desc_t
*)calloc(1, sizeof(jack_driver_desc_t
));
217 strcpy(desc
->name
, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
218 strcpy(desc
->desc
, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
221 params
= (jack_driver_param_desc_t
*)calloc(desc
->nparams
, sizeof(jack_driver_param_desc_t
));
224 strcpy ( params
[i
].name
, "capture" );
225 params
[i
].character
= 'C';
226 params
[i
].type
= JackDriverParamString
;
227 strcpy ( params
[i
].value
.str
, "none" );
228 strcpy ( params
[i
].short_desc
,
229 "Provide capture ports. Optionally set device" );
230 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
233 strcpy ( params
[i
].name
, "playback" );
234 params
[i
].character
= 'P';
235 params
[i
].type
= JackDriverParamString
;
236 strcpy ( params
[i
].value
.str
, "none" );
237 strcpy ( params
[i
].short_desc
,
238 "Provide playback ports. Optionally set device" );
239 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
242 strcpy ( params
[i
].name
, "device" );
243 params
[i
].character
= 'd';
244 params
[i
].type
= JackDriverParamString
;
245 strcpy ( params
[i
].value
.str
, "hw:0" );
246 strcpy ( params
[i
].short_desc
, "ALSA device name" );
247 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
250 strcpy ( params
[i
].name
, "rate" );
251 params
[i
].character
= 'r';
252 params
[i
].type
= JackDriverParamUInt
;
253 params
[i
].value
.ui
= 48000U;
254 strcpy ( params
[i
].short_desc
, "Sample rate" );
255 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
258 strcpy ( params
[i
].name
, "periodsize" );
259 params
[i
].character
= 'p';
260 params
[i
].type
= JackDriverParamUInt
;
261 params
[i
].value
.ui
= 512U;
262 strcpy ( params
[i
].short_desc
, "Period size" );
263 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
266 strcpy ( params
[i
].name
, "nperiods" );
267 params
[i
].character
= 'n';
268 params
[i
].type
= JackDriverParamUInt
;
269 params
[i
].value
.ui
= 2U;
270 strcpy ( params
[i
].short_desc
, "Number of periods of playback latency" );
271 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
274 strcpy ( params
[i
].name
, "duplex" );
275 params
[i
].character
= 'D';
276 params
[i
].type
= JackDriverParamBool
;
277 params
[i
].value
.i
= 1;
278 strcpy ( params
[i
].short_desc
,
279 "Provide both capture and playback ports" );
280 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
283 strcpy ( params
[i
].name
, "inchannels" );
284 params
[i
].character
= 'i';
285 params
[i
].type
= JackDriverParamUInt
;
286 params
[i
].value
.i
= 0;
287 strcpy ( params
[i
].short_desc
,
288 "Number of capture channels (defaults to hardware max)" );
289 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
292 strcpy ( params
[i
].name
, "outchannels" );
293 params
[i
].character
= 'o';
294 params
[i
].type
= JackDriverParamUInt
;
295 params
[i
].value
.i
= 0;
296 strcpy ( params
[i
].short_desc
,
297 "Number of playback channels (defaults to hardware max)" );
298 strcpy ( params
[i
].long_desc
, params
[i
].short_desc
);
300 desc
->params
= params
;