20 #include "JackOSSAdapter.h"
21 #include "JackServerGlobals.h"
22 #include "JackEngineControl.h"
25 #include <sys/ioctl.h>
26 #include <sys/soundcard.h>
34 inline int int2pow2(
int x) {
int r = 0;
while ((1 << r) < x) r++;
return r; }
36 static inline void CopyAndConvertIn(jack_sample_t *dst,
void *src,
size_t nframes,
int channel,
int chcount,
int bits)
41 signed short *s16src = (
signed short*)src;
43 sample_move_dS_s16(dst, (
char*)s16src, nframes, chcount<<1);
47 signed int *s32src = (
signed int*)src;
49 sample_move_dS_s24(dst, (
char*)s32src, nframes, chcount<<2);
53 signed int *s32src = (
signed int*)src;
55 sample_move_dS_s32u24(dst, (
char*)s32src, nframes, chcount<<2);
61 static inline void CopyAndConvertOut(
void *dst, jack_sample_t *src,
size_t nframes,
int channel,
int chcount,
int bits)
66 signed short *s16dst = (
signed short*)dst;
68 sample_move_d16_sS((
char*)s16dst, src, nframes, chcount<<1, NULL);
72 signed int *s32dst = (
signed int*)dst;
74 sample_move_d24_sS((
char*)s32dst, src, nframes, chcount<<2, NULL);
78 signed int *s32dst = (
signed int*)dst;
80 sample_move_d32u24_sS((
char*)s32dst, src, nframes, chcount<<2, NULL);
86 void JackOSSAdapter::SetSampleFormat()
91 fSampleFormat = AFMT_S24_NE;
92 fSampleSize =
sizeof(int);
95 fSampleFormat = AFMT_S32_NE;
96 fSampleSize =
sizeof(int);
100 fSampleFormat = AFMT_S16_NE;
101 fSampleSize =
sizeof(short);
106 JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate,
const JSList* params)
107 :JackAudioAdapterInterface(buffer_size, sample_rate)
109 fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS),
110 fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false),
111 fInputBufferSize(0), fOutputBufferSize(0),
112 fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true)
117 fCaptureChannels = 2;
118 fPlaybackChannels = 2;
120 strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV);
121 strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV);
123 for (node = params; node; node = jack_slist_next(node)) {
126 switch (param->character) {
129 SetAdaptedSampleRate(param->value.ui);
133 SetAdaptedBufferSize(param->value.ui);
137 fNperiods = param->value.ui;
141 fBits = param->value.i;
145 fCaptureChannels = param->value.ui;
149 fPlaybackChannels = param->value.ui;
158 if (strcmp(param->value.str,
"none") != 0) {
159 strcpy(fCaptureDriverName, param->value.str);
165 if (strcmp(param->value.str,
"none") != 0) {
166 strcpy(fPlaybackDriverName, param->value.str);
173 strcpy(fCaptureDriverName, param->value.str);
174 strcpy(fPlaybackDriverName, param->value.str);
182 fQuality = param->value.ui;
186 fRingbufferCurSize = param->value.ui;
197 void JackOSSAdapter::DisplayDeviceInfo()
200 oss_audioinfo ai_in, ai_out;
201 memset(&info, 0,
sizeof(audio_buf_info));
206 jack_info(
"Audio Interface Description :");
207 jack_info(
"Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode);
209 if (fRWMode & kWrite) {
212 if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
213 jack_error(
"JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
217 jack_info(
"OSS version num %d", si.versionnum);
218 jack_info(
"OSS numaudios %d", si.numaudios);
219 jack_info(
"OSS numaudioengines %d", si.numaudioengines);
220 jack_info(
"OSS numcards %d", si.numcards);
223 jack_info(
"Output capabilities - %d channels : ", fPlaybackChannels);
224 jack_info(
"Output block size = %d", fOutputBufferSize);
226 if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
227 jack_error(
"JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
229 jack_info(
"output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
230 info.fragments, info.fragstotal, info.fragsize, info.bytes);
233 if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
234 jack_error(
"JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
236 if (cap & DSP_CAP_DUPLEX)
jack_info(
" DSP_CAP_DUPLEX");
237 if (cap & DSP_CAP_REALTIME)
jack_info(
" DSP_CAP_REALTIME");
238 if (cap & DSP_CAP_BATCH)
jack_info(
" DSP_CAP_BATCH");
239 if (cap & DSP_CAP_COPROC)
jack_info(
" DSP_CAP_COPROC");
240 if (cap & DSP_CAP_TRIGGER)
jack_info(
" DSP_CAP_TRIGGER");
241 if (cap & DSP_CAP_MMAP)
jack_info(
" DSP_CAP_MMAP");
242 if (cap & DSP_CAP_MULTI)
jack_info(
" DSP_CAP_MULTI");
243 if (cap & DSP_CAP_BIND)
jack_info(
" DSP_CAP_BIND");
247 if (fRWMode & kRead) {
250 if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
251 jack_error(
"JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
255 jack_info(
"OSS version num %d", si.versionnum);
256 jack_info(
"OSS numaudios %d", si.numaudios);
257 jack_info(
"OSS numaudioengines %d", si.numaudioengines);
258 jack_info(
"OSS numcards %d", si.numcards);
261 jack_info(
"Input capabilities - %d channels : ", fCaptureChannels);
262 jack_info(
"Input block size = %d", fInputBufferSize);
264 if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
265 jack_error(
"JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
267 jack_info(
"input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
268 info.fragments, info.fragstotal, info.fragsize, info.bytes);
271 if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
272 jack_error(
"JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
274 if (cap & DSP_CAP_DUPLEX)
jack_info(
" DSP_CAP_DUPLEX");
275 if (cap & DSP_CAP_REALTIME)
jack_info(
" DSP_CAP_REALTIME");
276 if (cap & DSP_CAP_BATCH)
jack_info(
" DSP_CAP_BATCH");
277 if (cap & DSP_CAP_COPROC)
jack_info(
" DSP_CAP_COPROC");
278 if (cap & DSP_CAP_TRIGGER)
jack_info(
" DSP_CAP_TRIGGER");
279 if (cap & DSP_CAP_MMAP)
jack_info(
" DSP_CAP_MMAP");
280 if (cap & DSP_CAP_MULTI)
jack_info(
" DSP_CAP_MULTI");
281 if (cap & DSP_CAP_BIND)
jack_info(
" DSP_CAP_BIND");
285 if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) {
286 jack_info(
"Using audio engine %d = %s for input", ai_in.dev, ai_in.name);
289 if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) {
290 jack_info(
"Using audio engine %d = %s for output", ai_out.dev, ai_out.name);
293 if (ai_in.rate_source != ai_out.rate_source) {
294 jack_info(
"Warning : input and output are not necessarily driven by the same clock!");
298 int JackOSSAdapter::OpenInput()
302 int cur_sample_format, cur_capture_channels;
303 jack_nframes_t cur_sample_rate;
305 if (fCaptureChannels == 0) fCaptureChannels = 2;
307 if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
308 jack_error(
"JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
313 if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
314 jack_error(
"JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
319 gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
320 if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
321 jack_error(
"JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
325 cur_sample_format = fSampleFormat;
326 if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
327 jack_error(
"JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
330 if (cur_sample_format != fSampleFormat) {
331 jack_info(
"JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat);
334 cur_capture_channels = fCaptureChannels;
335 if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
336 jack_error(
"JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
339 if (cur_capture_channels != fCaptureChannels) {
340 jack_info(
"JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
343 cur_sample_rate = fAdaptedSampleRate;
344 if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
345 jack_error(
"JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
348 if (cur_sample_rate != fAdaptedSampleRate) {
349 jack_info(
"JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
352 fInputBufferSize = 0;
353 if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
354 jack_error(
"JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
358 if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) {
360 jack_info(
"JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize);
362 jack_error(
"JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
367 fInputBuffer = (
void*)calloc(fInputBufferSize, 1);
368 assert(fInputBuffer);
370 fInputSampleBuffer = (
float**)malloc(fCaptureChannels *
sizeof(
float*));
371 assert(fInputSampleBuffer);
373 for (
int i = 0; i < fCaptureChannels; i++) {
374 fInputSampleBuffer[i] = (
float*)malloc(fAdaptedBufferSize *
sizeof(
float));
375 assert(fInputSampleBuffer[i]);
384 int JackOSSAdapter::OpenOutput()
388 int cur_sample_format, cur_playback_channels;
389 jack_nframes_t cur_sample_rate;
391 if (fPlaybackChannels == 0) fPlaybackChannels = 2;
393 if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
394 jack_error(
"JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
399 if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
400 jack_error(
"JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
405 gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
406 if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
407 jack_error(
"JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
411 cur_sample_format = fSampleFormat;
412 if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
413 jack_error(
"JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
416 if (cur_sample_format != fSampleFormat) {
417 jack_info(
"JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat);
420 cur_playback_channels = fPlaybackChannels;
421 if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
422 jack_error(
"JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
425 if (cur_playback_channels != fPlaybackChannels) {
426 jack_info(
"JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
429 cur_sample_rate = fAdaptedSampleRate;
430 if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
431 jack_error(
"JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
434 if (cur_sample_rate != fAdaptedSampleRate) {
435 jack_info(
"JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
438 fOutputBufferSize = 0;
439 if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
440 jack_error(
"JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
444 if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) {
446 jack_info(
"JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize);
448 jack_error(
"JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
453 fOutputBuffer = (
void*)calloc(fOutputBufferSize, 1);
454 assert(fOutputBuffer);
456 fOutputSampleBuffer = (
float**)malloc(fPlaybackChannels *
sizeof(
float*));
457 assert(fOutputSampleBuffer);
459 for (
int i = 0; i < fPlaybackChannels; i++) {
460 fOutputSampleBuffer[i] = (
float*)malloc(fAdaptedBufferSize *
sizeof(
float));
461 assert(fOutputSampleBuffer[i]);
472 int JackOSSAdapter::Open()
476 if ((fRWMode & kRead) && (OpenInput() < 0)) {
480 if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
485 if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
486 jack_error(
"JackOSSAdapter::OpenAux input and output buffer size are not the same!!");
493 if (fThread.StartSync() < 0) {
494 jack_error (
"Cannot start audioadapter thread" );
499 fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority);
508 int JackOSSAdapter::Close()
511 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
518 void JackOSSAdapter::CloseAux()
520 if (fRWMode & kRead) {
525 if (fRWMode & kWrite) {
534 fOutputBuffer = NULL;
536 for (
int i = 0; i < fCaptureChannels; i++) {
537 free(fInputSampleBuffer[i]);
539 free(fInputSampleBuffer);
541 for (
int i = 0; i < fPlaybackChannels; i++) {
542 free(fOutputSampleBuffer[i]);
544 free(fOutputSampleBuffer);
547 int JackOSSAdapter::Read()
549 ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
551 if (count < fInputBufferSize) {
552 jack_error(
"JackOSSAdapter::Read error bytes read = %ld", count);
555 for (
int i = 0; i < fCaptureChannels; i++) {
556 CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
562 int JackOSSAdapter::Write()
570 memset(fOutputBuffer, 0, fOutputBufferSize);
573 for (
int i = 0; i < fNperiods; i++) {
574 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
575 if (count < fOutputBufferSize) {
576 jack_error(
"JackOSSDriver::Write error bytes written = %ld", count);
582 if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
583 jack_error(
"JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
587 delay /= fSampleSize * fPlaybackChannels;
588 jack_info(
"JackOSSDriver::Write output latency frames = %ld", delay);
591 for (
int i = 0; i < fPlaybackChannels; i++) {
592 CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits);
595 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
597 if (count < fOutputBufferSize) {
598 jack_error(
"JackOSSAdapter::Write error bytes written = %ld", count);
605 bool JackOSSAdapter::Execute()
611 PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize);
620 int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size)
622 JackAudioAdapterInterface::SetBufferSize(buffer_size);
640 desc = jack_driver_descriptor_construct(
"audioadapter", JackDriverNone,
"netjack audio <==> net backend adapter", &filler);
642 value.ui = OSS_DRIVER_DEF_FS;
643 jack_driver_descriptor_add_parameter(desc, &filler,
"rate",
'r', JackDriverParamUInt, &value, NULL,
"Sample rate", NULL);
645 value.ui = OSS_DRIVER_DEF_BLKSIZE;
646 jack_driver_descriptor_add_parameter(desc, &filler,
"period",
'p', JackDriverParamUInt, &value, NULL,
"Frames per period", NULL);
648 value.ui = OSS_DRIVER_DEF_NPERIODS;
649 jack_driver_descriptor_add_parameter(desc, &filler,
"nperiods",
'n', JackDriverParamUInt, &value, NULL,
"Number of periods to prefill output buffer", NULL);
651 value.i = OSS_DRIVER_DEF_BITS;
652 jack_driver_descriptor_add_parameter(desc, &filler,
"wordlength",
'w', JackDriverParamInt, &value, NULL,
"Word length", NULL);
654 value.ui = OSS_DRIVER_DEF_INS;
655 jack_driver_descriptor_add_parameter(desc, &filler,
"in-channels",
'i', JackDriverParamUInt, &value, NULL,
"Capture channels", NULL);
657 value.ui = OSS_DRIVER_DEF_OUTS;
658 jack_driver_descriptor_add_parameter(desc, &filler,
"out-channels",
'o', JackDriverParamUInt, &value, NULL,
"Playback channels", NULL);
661 jack_driver_descriptor_add_parameter(desc, &filler,
"excl",
'e', JackDriverParamBool, &value, NULL,
"Exclusif (O_EXCL) access mode", NULL);
663 strcpy(value.str, OSS_DRIVER_DEF_DEV);
664 jack_driver_descriptor_add_parameter(desc, &filler,
"capture",
'C', JackDriverParamString, &value, NULL,
"Input device", NULL);
665 jack_driver_descriptor_add_parameter(desc, &filler,
"playback",
'P', JackDriverParamString, &value, NULL,
"Output device", NULL);
666 jack_driver_descriptor_add_parameter(desc, &filler,
"device",
'd', JackDriverParamString, &value, NULL,
"OSS device name", NULL);
669 jack_driver_descriptor_add_parameter(desc, &filler,
"ignorehwbuf",
'b', JackDriverParamBool, &value, NULL,
"Ignore hardware period size", NULL);
672 jack_driver_descriptor_add_parameter(desc, &filler,
"quality",
'q', JackDriverParamInt, &value, NULL,
"Resample algorithm quality (0 - 4)", NULL);
675 jack_driver_descriptor_add_parameter(desc, &filler,
"ring-buffer",
'g', JackDriverParamInt, &value, NULL,
"Fixed ringbuffer size",
"Fixed ringbuffer size (if not set => automatic adaptative)");
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)