Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2008 Grame & RTL 2008 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 00018 */ 00019 00020 #include "JackOSSAdapter.h" 00021 #include "JackServerGlobals.h" 00022 #include "JackEngineControl.h" 00023 #include "memops.h" 00024 00025 #include <sys/ioctl.h> 00026 #include <sys/soundcard.h> 00027 #include <fcntl.h> 00028 #include <iostream> 00029 #include <assert.h> 00030 00031 namespace Jack 00032 { 00033 00034 inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; } 00035 00036 static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits) 00037 { 00038 switch (bits) { 00039 00040 case 16: { 00041 signed short *s16src = (signed short*)src; 00042 s16src += channel; 00043 sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1); 00044 break; 00045 } 00046 case 24: { 00047 signed int *s32src = (signed int*)src; 00048 s32src += channel; 00049 sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2); 00050 break; 00051 } 00052 case 32: { 00053 signed int *s32src = (signed int*)src; 00054 s32src += channel; 00055 sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2); 00056 break; 00057 } 00058 } 00059 } 00060 00061 static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits) 00062 { 00063 switch (bits) { 00064 00065 case 16: { 00066 signed short *s16dst = (signed short*)dst; 00067 s16dst += channel; 00068 sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now... 00069 break; 00070 } 00071 case 24: { 00072 signed int *s32dst = (signed int*)dst; 00073 s32dst += channel; 00074 sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now... 00075 break; 00076 } 00077 case 32: { 00078 signed int *s32dst = (signed int*)dst; 00079 s32dst += channel; 00080 sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); 00081 break; 00082 } 00083 } 00084 } 00085 00086 void JackOSSAdapter::SetSampleFormat() 00087 { 00088 switch (fBits) { 00089 00090 case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */ 00091 fSampleFormat = AFMT_S24_NE; 00092 fSampleSize = sizeof(int); 00093 break; 00094 case 32: /* native-endian 32-bit integer */ 00095 fSampleFormat = AFMT_S32_NE; 00096 fSampleSize = sizeof(int); 00097 break; 00098 case 16: /* native-endian 16-bit integer */ 00099 default: 00100 fSampleFormat = AFMT_S16_NE; 00101 fSampleSize = sizeof(short); 00102 break; 00103 } 00104 } 00105 00106 JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) 00107 :JackAudioAdapterInterface(buffer_size, sample_rate) 00108 ,fThread(this), 00109 fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS), 00110 fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false), 00111 fInputBufferSize(0), fOutputBufferSize(0), 00112 fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true) 00113 { 00114 const JSList* node; 00115 const jack_driver_param_t* param; 00116 00117 fCaptureChannels = 2; 00118 fPlaybackChannels = 2; 00119 00120 strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV); 00121 strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV); 00122 00123 for (node = params; node; node = jack_slist_next(node)) { 00124 param = (const jack_driver_param_t*) node->data; 00125 00126 switch (param->character) { 00127 00128 case 'r': 00129 SetAdaptedSampleRate(param->value.ui); 00130 break; 00131 00132 case 'p': 00133 SetAdaptedBufferSize(param->value.ui); 00134 break; 00135 00136 case 'n': 00137 fNperiods = param->value.ui; 00138 break; 00139 00140 case 'w': 00141 fBits = param->value.i; 00142 break; 00143 00144 case 'i': 00145 fCaptureChannels = param->value.ui; 00146 break; 00147 00148 case 'o': 00149 fPlaybackChannels = param->value.ui; 00150 break; 00151 00152 case 'e': 00153 fExcl = true; 00154 break; 00155 00156 case 'C': 00157 fRWMode |= kRead; 00158 if (strcmp(param->value.str, "none") != 0) { 00159 strcpy(fCaptureDriverName, param->value.str); 00160 } 00161 break; 00162 00163 case 'P': 00164 fRWMode |= kWrite; 00165 if (strcmp(param->value.str, "none") != 0) { 00166 strcpy(fPlaybackDriverName, param->value.str); 00167 } 00168 break; 00169 00170 case 'd': 00171 fRWMode |= kRead; 00172 fRWMode |= kWrite; 00173 strcpy(fCaptureDriverName, param->value.str); 00174 strcpy(fPlaybackDriverName, param->value.str); 00175 break; 00176 00177 case 'b': 00178 fIgnoreHW = true; 00179 break; 00180 00181 case 'q': 00182 fQuality = param->value.ui; 00183 break; 00184 00185 case 'g': 00186 fRingbufferCurSize = param->value.ui; 00187 fAdaptative = false; 00188 break; 00189 00190 } 00191 } 00192 00193 fRWMode |= kRead; 00194 fRWMode |= kWrite; 00195 } 00196 00197 void JackOSSAdapter::DisplayDeviceInfo() 00198 { 00199 audio_buf_info info; 00200 oss_audioinfo ai_in, ai_out; 00201 memset(&info, 0, sizeof(audio_buf_info)); 00202 int cap = 0; 00203 00204 // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html 00205 00206 jack_info("Audio Interface Description :"); 00207 jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode); 00208 00209 if (fRWMode & kWrite) { 00210 00211 oss_sysinfo si; 00212 if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) { 00213 jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00214 } else { 00215 jack_info("OSS product %s", si.product); 00216 jack_info("OSS version %s", si.version); 00217 jack_info("OSS version num %d", si.versionnum); 00218 jack_info("OSS numaudios %d", si.numaudios); 00219 jack_info("OSS numaudioengines %d", si.numaudioengines); 00220 jack_info("OSS numcards %d", si.numcards); 00221 } 00222 00223 jack_info("Output capabilities - %d channels : ", fPlaybackChannels); 00224 jack_info("Output block size = %d", fOutputBufferSize); 00225 00226 if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) { 00227 jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00228 } else { 00229 jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", 00230 info.fragments, info.fragstotal, info.fragsize, info.bytes); 00231 } 00232 00233 if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { 00234 jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00235 } else { 00236 if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); 00237 if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); 00238 if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); 00239 if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); 00240 if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); 00241 if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); 00242 if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); 00243 if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); 00244 } 00245 } 00246 00247 if (fRWMode & kRead) { 00248 00249 oss_sysinfo si; 00250 if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) { 00251 jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00252 } else { 00253 jack_info("OSS product %s", si.product); 00254 jack_info("OSS version %s", si.version); 00255 jack_info("OSS version num %d", si.versionnum); 00256 jack_info("OSS numaudios %d", si.numaudios); 00257 jack_info("OSS numaudioengines %d", si.numaudioengines); 00258 jack_info("OSS numcards %d", si.numcards); 00259 } 00260 00261 jack_info("Input capabilities - %d channels : ", fCaptureChannels); 00262 jack_info("Input block size = %d", fInputBufferSize); 00263 00264 if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) { 00265 jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00266 } else { 00267 jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", 00268 info.fragments, info.fragstotal, info.fragsize, info.bytes); 00269 } 00270 00271 if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { 00272 jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00273 } else { 00274 if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); 00275 if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); 00276 if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); 00277 if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); 00278 if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); 00279 if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); 00280 if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); 00281 if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); 00282 } 00283 } 00284 00285 if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) { 00286 jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name); 00287 } 00288 00289 if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) { 00290 jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name); 00291 } 00292 00293 if (ai_in.rate_source != ai_out.rate_source) { 00294 jack_info("Warning : input and output are not necessarily driven by the same clock!"); 00295 } 00296 } 00297 00298 int JackOSSAdapter::OpenInput() 00299 { 00300 int flags = 0; 00301 int gFragFormat; 00302 int cur_sample_format, cur_capture_channels; 00303 jack_nframes_t cur_sample_rate; 00304 00305 if (fCaptureChannels == 0) fCaptureChannels = 2; 00306 00307 if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) { 00308 jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00309 return -1; 00310 } 00311 00312 if (fExcl) { 00313 if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { 00314 jack_error("JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00315 goto error; 00316 } 00317 } 00318 00319 gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels); 00320 if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { 00321 jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00322 goto error; 00323 } 00324 00325 cur_sample_format = fSampleFormat; 00326 if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { 00327 jack_error("JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00328 goto error; 00329 } 00330 if (cur_sample_format != fSampleFormat) { 00331 jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat); 00332 } 00333 00334 cur_capture_channels = fCaptureChannels; 00335 if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) { 00336 jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00337 goto error; 00338 } 00339 if (cur_capture_channels != fCaptureChannels) { 00340 jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels); 00341 } 00342 00343 cur_sample_rate = fAdaptedSampleRate; 00344 if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) { 00345 jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00346 goto error; 00347 } 00348 if (cur_sample_rate != fAdaptedSampleRate) { 00349 jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate); 00350 } 00351 00352 fInputBufferSize = 0; 00353 if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) { 00354 jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00355 goto error; 00356 } 00357 00358 if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) { 00359 if (fIgnoreHW) { 00360 jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize); 00361 } else { 00362 jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained"); 00363 goto error; 00364 } 00365 } 00366 00367 fInputBuffer = (void*)calloc(fInputBufferSize, 1); 00368 assert(fInputBuffer); 00369 00370 fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*)); 00371 assert(fInputSampleBuffer); 00372 00373 for (int i = 0; i < fCaptureChannels; i++) { 00374 fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); 00375 assert(fInputSampleBuffer[i]); 00376 } 00377 return 0; 00378 00379 error: 00380 ::close(fInFD); 00381 return -1; 00382 } 00383 00384 int JackOSSAdapter::OpenOutput() 00385 { 00386 int flags = 0; 00387 int gFragFormat; 00388 int cur_sample_format, cur_playback_channels; 00389 jack_nframes_t cur_sample_rate; 00390 00391 if (fPlaybackChannels == 0) fPlaybackChannels = 2; 00392 00393 if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) { 00394 jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00395 return -1; 00396 } 00397 00398 if (fExcl) { 00399 if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { 00400 jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00401 goto error; 00402 } 00403 } 00404 00405 gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels); 00406 if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { 00407 jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00408 goto error; 00409 } 00410 00411 cur_sample_format = fSampleFormat; 00412 if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { 00413 jack_error("JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00414 goto error; 00415 } 00416 if (cur_sample_format != fSampleFormat) { 00417 jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat); 00418 } 00419 00420 cur_playback_channels = fPlaybackChannels; 00421 if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) { 00422 jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00423 goto error; 00424 } 00425 if (cur_playback_channels != fPlaybackChannels) { 00426 jack_info("JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels); 00427 } 00428 00429 cur_sample_rate = fAdaptedSampleRate; 00430 if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) { 00431 jack_error("JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00432 goto error; 00433 } 00434 if (cur_sample_rate != fAdaptedSampleRate) { 00435 jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate); 00436 } 00437 00438 fOutputBufferSize = 0; 00439 if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) { 00440 jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00441 goto error; 00442 } 00443 00444 if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) { 00445 if (fIgnoreHW) { 00446 jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize); 00447 } else { 00448 jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained"); 00449 goto error; 00450 } 00451 } 00452 00453 fOutputBuffer = (void*)calloc(fOutputBufferSize, 1); 00454 assert(fOutputBuffer); 00455 00456 fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*)); 00457 assert(fOutputSampleBuffer); 00458 00459 for (int i = 0; i < fPlaybackChannels; i++) { 00460 fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); 00461 assert(fOutputSampleBuffer[i]); 00462 } 00463 00464 fFirstCycle = true; 00465 return 0; 00466 00467 error: 00468 ::close(fOutFD); 00469 return -1; 00470 } 00471 00472 int JackOSSAdapter::Open() 00473 { 00474 SetSampleFormat(); 00475 00476 if ((fRWMode & kRead) && (OpenInput() < 0)) { 00477 return -1; 00478 } 00479 00480 if ((fRWMode & kWrite) && (OpenOutput() < 0)) { 00481 return -1; 00482 } 00483 00484 // In duplex mode, check that input and output use the same buffer size 00485 if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { 00486 jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!"); 00487 goto error; 00488 } 00489 00490 DisplayDeviceInfo(); 00491 00492 //start adapter thread 00493 if (fThread.StartSync() < 0) { 00494 jack_error ( "Cannot start audioadapter thread" ); 00495 return -1; 00496 } 00497 00498 //turn the thread realtime 00499 fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority); 00500 return 0; 00501 00502 error: 00503 CloseAux(); 00504 return -1; 00505 } 00506 00507 00508 int JackOSSAdapter::Close() 00509 { 00510 #ifdef JACK_MONITOR 00511 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00512 #endif 00513 fThread.Stop(); 00514 CloseAux(); 00515 return 0; 00516 } 00517 00518 void JackOSSAdapter::CloseAux() 00519 { 00520 if (fRWMode & kRead) { 00521 close(fInFD); 00522 fInFD = -1; 00523 } 00524 00525 if (fRWMode & kWrite) { 00526 close(fOutFD); 00527 fOutFD = -1; 00528 } 00529 00530 free(fInputBuffer); 00531 fInputBuffer = NULL; 00532 00533 free(fOutputBuffer); 00534 fOutputBuffer = NULL; 00535 00536 for (int i = 0; i < fCaptureChannels; i++) { 00537 free(fInputSampleBuffer[i]); 00538 } 00539 free(fInputSampleBuffer); 00540 00541 for (int i = 0; i < fPlaybackChannels; i++) { 00542 free(fOutputSampleBuffer[i]); 00543 } 00544 free(fOutputSampleBuffer); 00545 } 00546 00547 int JackOSSAdapter::Read() 00548 { 00549 ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize); 00550 00551 if (count < fInputBufferSize) { 00552 jack_error("JackOSSAdapter::Read error bytes read = %ld", count); 00553 return -1; 00554 } else { 00555 for (int i = 0; i < fCaptureChannels; i++) { 00556 CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits); 00557 } 00558 return 0; 00559 } 00560 } 00561 00562 int JackOSSAdapter::Write() 00563 { 00564 ssize_t count; 00565 00566 // Maybe necessay to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html 00567 if (fFirstCycle) { 00568 00569 fFirstCycle = false; 00570 memset(fOutputBuffer, 0, fOutputBufferSize); 00571 00572 // Prefill ouput buffer 00573 for (int i = 0; i < fNperiods; i++) { 00574 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); 00575 if (count < fOutputBufferSize) { 00576 jack_error("JackOSSDriver::Write error bytes written = %ld", count); 00577 return -1; 00578 } 00579 } 00580 00581 int delay; 00582 if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) { 00583 jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno); 00584 return -1; 00585 } 00586 00587 delay /= fSampleSize * fPlaybackChannels; 00588 jack_info("JackOSSDriver::Write output latency frames = %ld", delay); 00589 } 00590 00591 for (int i = 0; i < fPlaybackChannels; i++) { 00592 CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits); 00593 } 00594 00595 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); 00596 00597 if (count < fOutputBufferSize) { 00598 jack_error("JackOSSAdapter::Write error bytes written = %ld", count); 00599 return -1; 00600 } else { 00601 return 0; 00602 } 00603 } 00604 00605 bool JackOSSAdapter::Execute() 00606 { 00607 //read data from audio interface 00608 if (Read() < 0) 00609 return false; 00610 00611 PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize); 00612 00613 //write data to audio interface 00614 if (Write() < 0) 00615 return false; 00616 00617 return true; 00618 } 00619 00620 int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size) 00621 { 00622 JackAudioAdapterInterface::SetBufferSize(buffer_size); 00623 Close(); 00624 return Open(); 00625 } 00626 00627 } // namespace 00628 00629 #ifdef __cplusplus 00630 extern "C" 00631 { 00632 #endif 00633 00634 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00635 { 00636 jack_driver_desc_t * desc; 00637 jack_driver_desc_filler_t filler; 00638 jack_driver_param_value_t value; 00639 00640 desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); 00641 00642 value.ui = OSS_DRIVER_DEF_FS; 00643 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); 00644 00645 value.ui = OSS_DRIVER_DEF_BLKSIZE; 00646 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); 00647 00648 value.ui = OSS_DRIVER_DEF_NPERIODS; 00649 jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL); 00650 00651 value.i = OSS_DRIVER_DEF_BITS; 00652 jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL); 00653 00654 value.ui = OSS_DRIVER_DEF_INS; 00655 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL); 00656 00657 value.ui = OSS_DRIVER_DEF_OUTS; 00658 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL); 00659 00660 value.i = false; 00661 jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL); 00662 00663 strcpy(value.str, OSS_DRIVER_DEF_DEV); 00664 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL); 00665 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL); 00666 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL); 00667 00668 value.i = true; 00669 jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL); 00670 00671 value.ui = 0; 00672 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); 00673 00674 value.i = 32768; 00675 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)"); 00676 00677 return desc; 00678 } 00679 00680 #ifdef __cplusplus 00681 } 00682 #endif 00683