00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "driver_interface.h"
00022 #include "JackThreadedDriver.h"
00023 #include "JackDriverLoader.h"
00024 #include "JackOSSDriver.h"
00025 #include "JackEngineControl.h"
00026 #include "JackGraphManager.h"
00027 #include "JackError.h"
00028 #include "JackTime.h"
00029 #include "JackShmMem.h"
00030 #include "memops.h"
00031
00032 #include <sys/ioctl.h>
00033 #include <sys/soundcard.h>
00034 #include <fcntl.h>
00035 #include <iostream>
00036 #include <assert.h>
00037 #include <stdio.h>
00038
00039 using namespace std;
00040
00041 namespace Jack
00042 {
00043
00044 #ifdef JACK_MONITOR
00045
00046 #define CYCLE_POINTS 500000
00047
00048 struct OSSCycle {
00049 jack_time_t fBeforeRead;
00050 jack_time_t fAfterRead;
00051 jack_time_t fAfterReadConvert;
00052 jack_time_t fBeforeWrite;
00053 jack_time_t fAfterWrite;
00054 jack_time_t fBeforeWriteConvert;
00055 };
00056
00057 struct OSSCycleTable {
00058 jack_time_t fBeforeFirstWrite;
00059 jack_time_t fAfterFirstWrite;
00060 OSSCycle fTable[CYCLE_POINTS];
00061 };
00062
00063 OSSCycleTable gCycleTable;
00064 int gCycleCount = 0;
00065
00066 #endif
00067
00068 inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; }
00069
00070 static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
00071 {
00072 switch (bits) {
00073
00074 case 16: {
00075 signed short *s16src = (signed short*)src;
00076 s16src += channel;
00077 sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
00078 break;
00079 }
00080 case 24: {
00081 signed int *s32src = (signed int*)src;
00082 s32src += channel;
00083 sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
00084 break;
00085 }
00086 case 32: {
00087 signed int *s32src = (signed int*)src;
00088 s32src += channel;
00089 sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
00090 break;
00091 }
00092 }
00093 }
00094
00095 static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
00096 {
00097 switch (bits) {
00098
00099 case 16: {
00100 signed short *s16dst = (signed short*)dst;
00101 s16dst += channel;
00102 sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL);
00103 break;
00104 }
00105 case 24: {
00106 signed int *s32dst = (signed int*)dst;
00107 s32dst += channel;
00108 sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
00109 break;
00110 }
00111 case 32: {
00112 signed int *s32dst = (signed int*)dst;
00113 s32dst += channel;
00114 sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
00115 break;
00116 }
00117 }
00118 }
00119
00120 void JackOSSDriver::SetSampleFormat()
00121 {
00122 switch (fBits) {
00123
00124 case 24:
00125 fSampleFormat = AFMT_S24_NE;
00126 fSampleSize = sizeof(int);
00127 break;
00128 case 32:
00129 fSampleFormat = AFMT_S32_NE;
00130 fSampleSize = sizeof(int);
00131 break;
00132 case 16:
00133 default:
00134 fSampleFormat = AFMT_S16_NE;
00135 fSampleSize = sizeof(short);
00136 break;
00137 }
00138 }
00139
00140 void JackOSSDriver::DisplayDeviceInfo()
00141 {
00142 audio_buf_info info;
00143 oss_audioinfo ai_in, ai_out;
00144 memset(&info, 0, sizeof(audio_buf_info));
00145 int cap = 0;
00146
00147
00148 jack_info("Audio Interface Description :");
00149 jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
00150
00151 if (fRWMode & kWrite) {
00152
00153 oss_sysinfo si;
00154 if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
00155 jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00156 } else {
00157 jack_info("OSS product %s", si.product);
00158 jack_info("OSS version %s", si.version);
00159 jack_info("OSS version num %d", si.versionnum);
00160 jack_info("OSS numaudios %d", si.numaudios);
00161 jack_info("OSS numaudioengines %d", si.numaudioengines);
00162 jack_info("OSS numcards %d", si.numcards);
00163 }
00164
00165 jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
00166 jack_info("Output block size = %d", fOutputBufferSize);
00167
00168 if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
00169 jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00170 } else {
00171 jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
00172 info.fragments, info.fragstotal, info.fragsize, info.bytes);
00173 }
00174
00175 if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
00176 jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00177 } else {
00178 if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
00179 if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
00180 if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
00181 if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
00182 if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
00183 if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
00184 if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
00185 if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
00186 }
00187 }
00188
00189 if (fRWMode & kRead) {
00190
00191 oss_sysinfo si;
00192 if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
00193 jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00194 } else {
00195 jack_info("OSS product %s", si.product);
00196 jack_info("OSS version %s", si.version);
00197 jack_info("OSS version num %d", si.versionnum);
00198 jack_info("OSS numaudios %d", si.numaudios);
00199 jack_info("OSS numaudioengines %d", si.numaudioengines);
00200 jack_info("OSS numcards %d", si.numcards);
00201 }
00202
00203 jack_info("Input capabilities - %d channels : ", fCaptureChannels);
00204 jack_info("Input block size = %d", fInputBufferSize);
00205
00206 if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
00207 jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00208 } else {
00209 jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
00210 info.fragments, info.fragstotal, info.fragsize, info.bytes);
00211 }
00212
00213 if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
00214 jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00215 } else {
00216 if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
00217 if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
00218 if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
00219 if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
00220 if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
00221 if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
00222 if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
00223 if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
00224 }
00225 }
00226
00227 if (ai_in.rate_source != ai_out.rate_source) {
00228 jack_info("Warning : input and output are not necessarily driven by the same clock!");
00229 }
00230 }
00231
00232 int JackOSSDriver::OpenInput()
00233 {
00234 int flags = 0;
00235 int gFragFormat;
00236 int cur_capture_channels;
00237 int cur_sample_format;
00238 jack_nframes_t cur_sample_rate;
00239
00240 if (fCaptureChannels == 0) fCaptureChannels = 2;
00241
00242 if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
00243 jack_error("JackOSSDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00244 return -1;
00245 }
00246
00247 jack_log("JackOSSDriver::OpenInput input fInFD = %d", fInFD);
00248
00249 if (fExcl) {
00250 if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
00251 jack_error("JackOSSDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00252 goto error;
00253 }
00254 }
00255
00256 gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
00257 if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
00258 jack_error("JackOSSDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00259 goto error;
00260 }
00261
00262 cur_sample_format = fSampleFormat;
00263 if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
00264 jack_error("JackOSSDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00265 goto error;
00266 }
00267 if (cur_sample_format != fSampleFormat) {
00268 jack_info("JackOSSDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
00269 }
00270
00271 cur_capture_channels = fCaptureChannels;
00272 if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
00273 jack_error("JackOSSDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00274 goto error;
00275 }
00276 if (cur_capture_channels != fCaptureChannels) {
00277 jack_info("JackOSSDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
00278 }
00279
00280 cur_sample_rate = fEngineControl->fSampleRate;
00281 if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
00282 jack_error("JackOSSDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00283 goto error;
00284 }
00285 if (cur_sample_rate != fEngineControl->fSampleRate) {
00286 jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
00287 }
00288
00289 fInputBufferSize = 0;
00290 if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
00291 jack_error("JackOSSDriver::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00292 goto error;
00293 }
00294
00295 if (fInputBufferSize != fEngineControl->fBufferSize * fSampleSize * fCaptureChannels) {
00296 if (fIgnoreHW) {
00297 int new_buffer_size = fInputBufferSize / (fSampleSize * fCaptureChannels);
00298 jack_info("JackOSSDriver::OpenInput driver forced buffer size %ld", new_buffer_size);
00299 JackAudioDriver::SetBufferSize(new_buffer_size);
00300 } else {
00301 jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained");
00302 goto error;
00303 }
00304 }
00305
00306 fInputBuffer = (void*)calloc(fInputBufferSize, 1);
00307 assert(fInputBuffer);
00308 return 0;
00309
00310 error:
00311 ::close(fInFD);
00312 return -1;
00313 }
00314
00315 int JackOSSDriver::OpenOutput()
00316 {
00317 int flags = 0;
00318 int gFragFormat;
00319 int cur_sample_format;
00320 int cur_playback_channels;
00321 jack_nframes_t cur_sample_rate;
00322
00323 if (fPlaybackChannels == 0) fPlaybackChannels = 2;
00324
00325 if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
00326 jack_error("JackOSSDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00327 return -1;
00328 }
00329
00330 jack_log("JackOSSDriver::OpenOutput output fOutFD = %d", fOutFD);
00331
00332 if (fExcl) {
00333 if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
00334 jack_error("JackOSSDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00335 goto error;
00336 }
00337 }
00338
00339 gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
00340 if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
00341 jack_error("JackOSSDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00342 goto error;
00343 }
00344
00345 cur_sample_format = fSampleFormat;
00346 if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
00347 jack_error("JackOSSDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00348 goto error;
00349 }
00350 if (cur_sample_format != fSampleFormat) {
00351 jack_info("JackOSSDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
00352 }
00353
00354 cur_playback_channels = fPlaybackChannels;
00355 if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
00356 jack_error("JackOSSDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00357 goto error;
00358 }
00359 if (cur_playback_channels != fPlaybackChannels) {
00360 jack_info("JackOSSDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
00361 }
00362
00363 cur_sample_rate = fEngineControl->fSampleRate;
00364 if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
00365 jack_error("JackOSSDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00366 goto error;
00367 }
00368 if (cur_sample_rate != fEngineControl->fSampleRate) {
00369 jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
00370 }
00371
00372 fOutputBufferSize = 0;
00373 if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
00374 jack_error("JackOSSDriver::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00375 goto error;
00376 }
00377
00378 if (fOutputBufferSize != fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels) {
00379 if (fIgnoreHW) {
00380 int new_buffer_size = fOutputBufferSize / (fSampleSize * fPlaybackChannels);
00381 jack_info("JackOSSDriver::OpenOutput driver forced buffer size %ld", new_buffer_size);
00382 JackAudioDriver::SetBufferSize(new_buffer_size);
00383 } else {
00384 jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained");
00385 goto error;
00386 }
00387 }
00388
00389 fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
00390 fFirstCycle = true;
00391 assert(fOutputBuffer);
00392 return 0;
00393
00394 error:
00395 ::close(fOutFD);
00396 return -1;
00397 }
00398
00399 int JackOSSDriver::Open(jack_nframes_t nframes,
00400 int user_nperiods,
00401 jack_nframes_t samplerate,
00402 bool capturing,
00403 bool playing,
00404 int inchannels,
00405 int outchannels,
00406 bool excl,
00407 bool monitor,
00408 const char* capture_driver_uid,
00409 const char* playback_driver_uid,
00410 jack_nframes_t capture_latency,
00411 jack_nframes_t playback_latency,
00412 int bits,
00413 bool ignorehwbuf)
00414 {
00415
00416 if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
00417 capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
00418 return -1;
00419 } else {
00420
00421 if (!fEngineControl->fSyncMode) {
00422 jack_error("Cannot run in asynchronous mode, use the -S parameter for jackd");
00423 return -1;
00424 }
00425
00426 fRWMode |= ((capturing) ? kRead : 0);
00427 fRWMode |= ((playing) ? kWrite : 0);
00428 fBits = bits;
00429 fIgnoreHW = ignorehwbuf;
00430 fNperiods = user_nperiods;
00431 fExcl = excl;
00432
00433 #ifdef JACK_MONITOR
00434
00435 memset(&gCycleTable, 0, sizeof(gCycleTable));
00436 #endif
00437
00438 if (OpenAux() < 0) {
00439 Close();
00440 return -1;
00441 } else {
00442 return 0;
00443 }
00444 }
00445 }
00446
00447 int JackOSSDriver::Close()
00448 {
00449 #ifdef JACK_MONITOR
00450 FILE* file = fopen("OSSProfiling.log", "w");
00451
00452 if (file) {
00453 jack_info("Writing OSS driver timing data....");
00454 for (int i = 1; i < gCycleCount; i++) {
00455 int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
00456 int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
00457 int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
00458 int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
00459 fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
00460 }
00461 fclose(file);
00462 } else {
00463 jack_error("JackOSSDriver::Close : cannot open OSSProfiling.log file");
00464 }
00465
00466 file = fopen("TimingOSS.plot", "w");
00467
00468 if (file == NULL) {
00469 jack_error("JackOSSDriver::Close cannot open TimingOSS.plot file");
00470 } else {
00471
00472 fprintf(file, "set grid\n");
00473 fprintf(file, "set title \"OSS audio driver timing\"\n");
00474 fprintf(file, "set xlabel \"audio cycles\"\n");
00475 fprintf(file, "set ylabel \"usec\"\n");
00476 fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
00477 \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
00478 \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
00479 \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
00480
00481 fprintf(file, "set output 'TimingOSS.pdf\n");
00482 fprintf(file, "set terminal pdf\n");
00483
00484 fprintf(file, "set grid\n");
00485 fprintf(file, "set title \"OSS audio driver timing\"\n");
00486 fprintf(file, "set xlabel \"audio cycles\"\n");
00487 fprintf(file, "set ylabel \"usec\"\n");
00488 fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
00489 \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
00490 \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
00491 \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
00492
00493 fclose(file);
00494 }
00495 #endif
00496 int res = JackAudioDriver::Close();
00497 CloseAux();
00498 return res;
00499 }
00500
00501
00502 int JackOSSDriver::OpenAux()
00503 {
00504 SetSampleFormat();
00505
00506 if ((fRWMode & kRead) && (OpenInput() < 0)) {
00507 return -1;
00508 }
00509
00510 if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
00511 return -1;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 DisplayDeviceInfo();
00526 return 0;
00527 }
00528
00529 void JackOSSDriver::CloseAux()
00530 {
00531 if (fRWMode & kRead && fInFD > 0) {
00532 close(fInFD);
00533 fInFD = -1;
00534 }
00535
00536 if (fRWMode & kWrite && fOutFD > 0) {
00537 close(fOutFD);
00538 fOutFD = -1;
00539 }
00540
00541 if (fInputBuffer)
00542 free(fInputBuffer);
00543 fInputBuffer = NULL;
00544
00545 if (fOutputBuffer)
00546 free(fOutputBuffer);
00547 fOutputBuffer = NULL;
00548 }
00549
00550 int JackOSSDriver::Read()
00551 {
00552 if (fInFD < 0) {
00553
00554 JackDriver::CycleTakeBeginTime();
00555 return 0;
00556 }
00557
00558 ssize_t count;
00559
00560 #ifdef JACK_MONITOR
00561 gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds();
00562 #endif
00563
00564 audio_errinfo ei_in;
00565 count = ::read(fInFD, fInputBuffer, fInputBufferSize);
00566
00567 #ifdef JACK_MONITOR
00568 if (count > 0 && count != (int)fInputBufferSize)
00569 jack_log("JackOSSDriver::Read count = %ld", count / (fSampleSize * fCaptureChannels));
00570 gCycleTable.fTable[gCycleCount].fAfterRead = GetMicroSeconds();
00571 #endif
00572
00573
00574 if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
00575
00576 if (ei_in.rec_overruns > 0 ) {
00577 jack_error("JackOSSDriver::Read overruns");
00578 jack_time_t cur_time = GetMicroSeconds();
00579 NotifyXRun(cur_time, float(cur_time - fBeginDateUst));
00580 }
00581
00582 if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
00583 jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
00584 }
00585 }
00586
00587 if (count < 0) {
00588 jack_log("JackOSSDriver::Read error = %s", strerror(errno));
00589 return -1;
00590 } else if (count < (int)fInputBufferSize) {
00591 jack_error("JackOSSDriver::Read error bytes read = %ld", count);
00592 return -1;
00593 } else {
00594
00595
00596 JackDriver::CycleTakeBeginTime();
00597 for (int i = 0; i < fCaptureChannels; i++) {
00598 if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
00599 CopyAndConvertIn(GetInputBuffer(i), fInputBuffer, fEngineControl->fBufferSize, i, fCaptureChannels, fBits);
00600 }
00601 }
00602
00603 #ifdef JACK_MONITOR
00604 gCycleTable.fTable[gCycleCount].fAfterReadConvert = GetMicroSeconds();
00605 #endif
00606
00607 return 0;
00608 }
00609 }
00610
00611 int JackOSSDriver::Write()
00612 {
00613 if (fOutFD < 0) {
00614
00615 JackDriver::CycleTakeEndTime();
00616 return 0;
00617 }
00618
00619 ssize_t count;
00620 audio_errinfo ei_out;
00621
00622
00623 if (fFirstCycle) {
00624
00625 fFirstCycle = false;
00626 memset(fOutputBuffer, 0, fOutputBufferSize);
00627
00628
00629 for (int i = 0; i < fNperiods; i++) {
00630 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
00631 if (count < (int)fOutputBufferSize) {
00632 jack_error("JackOSSDriver::Write error bytes written = %ld", count);
00633 return -1;
00634 }
00635 }
00636
00637 int delay;
00638 if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
00639 jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00640 return -1;
00641 }
00642
00643 delay /= fSampleSize * fPlaybackChannels;
00644 jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
00645 }
00646
00647 #ifdef JACK_MONITOR
00648 gCycleTable.fTable[gCycleCount].fBeforeWriteConvert = GetMicroSeconds();
00649 #endif
00650
00651 memset(fOutputBuffer, 0, fOutputBufferSize);
00652 for (int i = 0; i < fPlaybackChannels; i++) {
00653 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00654 CopyAndConvertOut(fOutputBuffer, GetOutputBuffer(i), fEngineControl->fBufferSize, i, fPlaybackChannels, fBits);
00655 }
00656 }
00657
00658 #ifdef JACK_MONITOR
00659 gCycleTable.fTable[gCycleCount].fBeforeWrite = GetMicroSeconds();
00660 #endif
00661
00662
00663 JackDriver::CycleTakeEndTime();
00664 count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
00665
00666 #ifdef JACK_MONITOR
00667 if (count > 0 && count != (int)fOutputBufferSize)
00668 jack_log("JackOSSDriver::Write count = %ld", count / (fSampleSize * fPlaybackChannels));
00669 gCycleTable.fTable[gCycleCount].fAfterWrite = GetMicroSeconds();
00670 gCycleCount = (gCycleCount == CYCLE_POINTS - 1) ? gCycleCount: gCycleCount + 1;
00671 #endif
00672
00673
00674 if (ioctl(fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) {
00675
00676 if (ei_out.play_underruns > 0) {
00677 jack_error("JackOSSDriver::Write underruns");
00678 jack_time_t cur_time = GetMicroSeconds();
00679 NotifyXRun(cur_time, float(cur_time - fBeginDateUst));
00680 }
00681
00682 if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
00683 jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
00684 }
00685 }
00686
00687 if (count < 0) {
00688 jack_log("JackOSSDriver::Write error = %s", strerror(errno));
00689 return -1;
00690 } else if (count < (int)fOutputBufferSize) {
00691 jack_error("JackOSSDriver::Write error bytes written = %ld", count);
00692 return -1;
00693 } else {
00694 return 0;
00695 }
00696 }
00697
00698 int JackOSSDriver::SetBufferSize(jack_nframes_t buffer_size)
00699 {
00700 CloseAux();
00701 JackAudioDriver::SetBufferSize(buffer_size);
00702 return OpenAux();
00703 }
00704
00705 int JackOSSDriver::ProcessSync()
00706 {
00707
00708 if (Read() < 0) {
00709 jack_error("ProcessSync: read error, skip cycle");
00710 return 0;
00711 }
00712
00713 if (fIsMaster) {
00714 ProcessGraphSync();
00715 } else {
00716 ResumeRefNum();
00717 }
00718
00719
00720 if (Write() < 0) {
00721 jack_error("JackAudioDriver::ProcessSync: write error, skip cycle");
00722 return 0;
00723 }
00724
00725 return 0;
00726 }
00727
00728 }
00729
00730 #ifdef __cplusplus
00731 extern "C"
00732 {
00733 #endif
00734
00735 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
00736 {
00737 jack_driver_desc_t * desc;
00738 jack_driver_desc_filler_t filler;
00739 jack_driver_param_value_t value;
00740
00741 desc = jack_driver_descriptor_construct("oss", JackDriverMaster, "OSS API based audio backend", &filler);
00742
00743 value.ui = OSS_DRIVER_DEF_FS;
00744 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00745
00746 value.ui = OSS_DRIVER_DEF_BLKSIZE;
00747 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
00748
00749 value.ui = OSS_DRIVER_DEF_NPERIODS;
00750 jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
00751
00752 value.i = OSS_DRIVER_DEF_BITS;
00753 jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
00754
00755 value.ui = OSS_DRIVER_DEF_INS;
00756 jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
00757
00758 value.ui = OSS_DRIVER_DEF_OUTS;
00759 jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
00760
00761 value.i = false;
00762 jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
00763
00764 strcpy(value.str, OSS_DRIVER_DEF_DEV);
00765 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
00766 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
00767 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
00768
00769 value.i = false;
00770 jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
00771
00772 value.ui = 0;
00773 jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
00774 jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
00775
00776 return desc;
00777 }
00778
00779 EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
00780 {
00781 int bits = OSS_DRIVER_DEF_BITS;
00782 jack_nframes_t srate = OSS_DRIVER_DEF_FS;
00783 jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE;
00784 const char* capture_pcm_name = OSS_DRIVER_DEF_DEV;
00785 const char* playback_pcm_name = OSS_DRIVER_DEF_DEV;
00786 bool capture = false;
00787 bool playback = false;
00788 int chan_in = 0;
00789 int chan_out = 0;
00790 bool monitor = false;
00791 bool excl = false;
00792 unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
00793 const JSList *node;
00794 const jack_driver_param_t *param;
00795 bool ignorehwbuf = false;
00796 jack_nframes_t systemic_input_latency = 0;
00797 jack_nframes_t systemic_output_latency = 0;
00798
00799 for (node = params; node; node = jack_slist_next(node)) {
00800
00801 param = (const jack_driver_param_t *)node->data;
00802
00803 switch (param->character) {
00804
00805 case 'r':
00806 srate = param->value.ui;
00807 break;
00808
00809 case 'p':
00810 frames_per_interrupt = (unsigned int)param->value.ui;
00811 break;
00812
00813 case 'n':
00814 nperiods = (unsigned int)param->value.ui;
00815 break;
00816
00817 case 'w':
00818 bits = param->value.i;
00819 break;
00820
00821 case 'i':
00822 chan_in = (int)param->value.ui;
00823 break;
00824
00825 case 'o':
00826 chan_out = (int)param->value.ui;
00827 break;
00828
00829 case 'C':
00830 capture = true;
00831 if (strcmp(param->value.str, "none") != 0) {
00832 capture_pcm_name = param->value.str;
00833 }
00834 break;
00835
00836 case 'P':
00837 playback = true;
00838 if (strcmp(param->value.str, "none") != 0) {
00839 playback_pcm_name = param->value.str;
00840 }
00841 break;
00842
00843 case 'd':
00844 playback_pcm_name = param->value.str;
00845 capture_pcm_name = param->value.str;
00846 break;
00847
00848 case 'b':
00849 ignorehwbuf = true;
00850 break;
00851
00852 case 'e':
00853 excl = true;
00854 break;
00855
00856 case 'I':
00857 systemic_input_latency = param->value.ui;
00858 break;
00859
00860 case 'O':
00861 systemic_output_latency = param->value.ui;
00862 break;
00863 }
00864 }
00865
00866
00867 if (!capture && !playback) {
00868 capture = true;
00869 playback = true;
00870 }
00871
00872 Jack::JackOSSDriver* oss_driver = new Jack::JackOSSDriver("system", "oss", engine, table);
00873 Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(oss_driver);
00874
00875
00876 if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
00877 excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) {
00878 return threaded_driver;
00879 } else {
00880 delete threaded_driver;
00881 return NULL;
00882 }
00883 }
00884
00885 #ifdef __cplusplus
00886 }
00887 #endif