20 #include "driver_interface.h"
21 #include "JackThreadedDriver.h"
22 #include "JackDriverLoader.h"
23 #include "JackBoomerDriver.h"
24 #include "JackEngineControl.h"
25 #include "JackGraphManager.h"
26 #include "JackError.h"
28 #include "JackShmMem.h"
29 #include "JackGlobals.h"
32 #include <sys/ioctl.h>
33 #include <sys/soundcard.h>
46 #define CYCLE_POINTS 500000
49 jack_time_t fBeforeRead;
50 jack_time_t fAfterRead;
51 jack_time_t fAfterReadConvert;
52 jack_time_t fBeforeWrite;
53 jack_time_t fAfterWrite;
54 jack_time_t fBeforeWriteConvert;
57 struct OSSCycleTable {
58 jack_time_t fBeforeFirstWrite;
59 jack_time_t fAfterFirstWrite;
60 OSSCycle fTable[CYCLE_POINTS];
63 OSSCycleTable gCycleTable;
64 int gCycleReadCount = 0;
65 int gCycleWriteCount = 0;
69 inline int int2pow2(
int x) {
int r = 0;
while ((1 << r) < x) r++;
return r; }
71 static inline void CopyAndConvertIn(jack_sample_t *dst,
void *src,
size_t nframes,
int channel,
int byte_skip,
int bits)
76 signed short *s16src = (
signed short*)src;
78 sample_move_dS_s16(dst, (
char*)s16src, nframes, byte_skip);
82 signed int *s32src = (
signed int*)src;
84 sample_move_dS_s24(dst, (
char*)s32src, nframes, byte_skip);
88 signed int *s32src = (
signed int*)src;
90 sample_move_dS_s32u24(dst, (
char*)s32src, nframes, byte_skip);
96 static inline void CopyAndConvertOut(
void *dst, jack_sample_t *src,
size_t nframes,
int channel,
int byte_skip,
int bits)
101 signed short *s16dst = (
signed short*)dst;
103 sample_move_d16_sS((
char*)s16dst, src, nframes, byte_skip, NULL);
107 signed int *s32dst = (
signed int*)dst;
109 sample_move_d24_sS((
char*)s32dst, src, nframes, byte_skip, NULL);
113 signed int *s32dst = (
signed int*)dst;
115 sample_move_d32u24_sS((
char*)s32dst, src, nframes, byte_skip, NULL);
121 void JackBoomerDriver::SetSampleFormat()
126 fSampleFormat = AFMT_S24_NE;
130 fSampleFormat = AFMT_S32_NE;
135 fSampleFormat = AFMT_S16_NE;
141 void JackBoomerDriver::DisplayDeviceInfo()
144 oss_audioinfo ai_in, ai_out;
145 memset(&info, 0,
sizeof(audio_buf_info));
149 jack_info(
"Audio Interface Description :");
150 jack_info(
"Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
152 if (fRWMode & kWrite) {
155 if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
156 jack_error(
"JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
160 jack_info(
"OSS version num %d", si.versionnum);
161 jack_info(
"OSS numaudios %d", si.numaudios);
162 jack_info(
"OSS numaudioengines %d", si.numaudioengines);
163 jack_info(
"OSS numcards %d", si.numcards);
166 jack_info(
"Output capabilities - %d channels : ", fPlaybackChannels);
167 jack_info(
"Output block size = %d", fOutputBufferSize);
169 if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
170 jack_error(
"JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
172 jack_info(
"output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
173 info.fragments, info.fragstotal, info.fragsize, info.bytes);
174 fFragmentSize = info.fragsize;
177 if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
178 jack_error(
"JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
180 if (cap & DSP_CAP_DUPLEX)
jack_info(
" DSP_CAP_DUPLEX");
181 if (cap & DSP_CAP_REALTIME)
jack_info(
" DSP_CAP_REALTIME");
182 if (cap & DSP_CAP_BATCH)
jack_info(
" DSP_CAP_BATCH");
183 if (cap & DSP_CAP_COPROC)
jack_info(
" DSP_CAP_COPROC");
184 if (cap & DSP_CAP_TRIGGER)
jack_info(
" DSP_CAP_TRIGGER");
185 if (cap & DSP_CAP_MMAP)
jack_info(
" DSP_CAP_MMAP");
186 if (cap & DSP_CAP_MULTI)
jack_info(
" DSP_CAP_MULTI");
187 if (cap & DSP_CAP_BIND)
jack_info(
" DSP_CAP_BIND");
191 if (fRWMode & kRead) {
194 if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
195 jack_error(
"JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
199 jack_info(
"OSS version num %d", si.versionnum);
200 jack_info(
"OSS numaudios %d", si.numaudios);
201 jack_info(
"OSS numaudioengines %d", si.numaudioengines);
202 jack_info(
"OSS numcards %d", si.numcards);
205 jack_info(
"Input capabilities - %d channels : ", fCaptureChannels);
206 jack_info(
"Input block size = %d", fInputBufferSize);
208 if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
209 jack_error(
"JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
211 jack_info(
"input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
212 info.fragments, info.fragstotal, info.fragsize, info.bytes);
215 if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
216 jack_error(
"JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
218 if (cap & DSP_CAP_DUPLEX)
jack_info(
" DSP_CAP_DUPLEX");
219 if (cap & DSP_CAP_REALTIME)
jack_info(
" DSP_CAP_REALTIME");
220 if (cap & DSP_CAP_BATCH)
jack_info(
" DSP_CAP_BATCH");
221 if (cap & DSP_CAP_COPROC)
jack_info(
" DSP_CAP_COPROC");
222 if (cap & DSP_CAP_TRIGGER)
jack_info(
" DSP_CAP_TRIGGER");
223 if (cap & DSP_CAP_MMAP)
jack_info(
" DSP_CAP_MMAP");
224 if (cap & DSP_CAP_MULTI)
jack_info(
" DSP_CAP_MULTI");
225 if (cap & DSP_CAP_BIND)
jack_info(
" DSP_CAP_BIND");
229 if (ai_in.rate_source != ai_out.rate_source) {
230 jack_info(
"Warning : input and output are not necessarily driven by the same clock!");
234 JackBoomerDriver::JackBoomerDriver(
const char* name,
const char* alias, JackLockedEngine* engine, JackSynchro* table)
235 : JackAudioDriver(name, alias, engine, table),
236 fInFD(-1), fOutFD(-1), fBits(0),
237 fSampleFormat(0), fNperiods(0), fSampleSize(0), fFragmentSize(0),
238 fRWMode(0), fExcl(false), fSyncIO(false),
239 fInputBufferSize(0), fOutputBufferSize(0),
240 fInputBuffer(NULL), fOutputBuffer(NULL),
241 fInputThread(&fInputHandler), fOutputThread(&fOutputHandler),
242 fInputHandler(this), fOutputHandler(this)
244 sem_init(&fReadSema, 0, 0);
245 sem_init(&fWriteSema, 0, 0);
248 JackBoomerDriver::~JackBoomerDriver()
250 sem_destroy(&fReadSema);
251 sem_destroy(&fWriteSema);
254 int JackBoomerDriver::OpenInput()
258 int cur_capture_channels;
259 int cur_sample_format;
260 jack_nframes_t cur_sample_rate;
262 if (fCaptureChannels == 0)
263 fCaptureChannels = 2;
265 if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
266 jack_error(
"JackBoomerDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
270 jack_log(
"JackBoomerDriver::OpenInput input fInFD = %d", fInFD);
273 if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
274 jack_error(
"JackBoomerDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
279 gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
280 if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
281 jack_error(
"JackBoomerDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
285 cur_sample_format = fSampleFormat;
286 if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
287 jack_error(
"JackBoomerDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
290 if (cur_sample_format != fSampleFormat) {
291 jack_info(
"JackBoomerDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
294 cur_capture_channels = fCaptureChannels;
295 if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
296 jack_error(
"JackBoomerDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
299 if (cur_capture_channels != fCaptureChannels) {
300 jack_info(
"JackBoomerDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
303 cur_sample_rate = fEngineControl->fSampleRate;
304 if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
305 jack_error(
"JackBoomerDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
308 if (cur_sample_rate != fEngineControl->fSampleRate) {
309 jack_info(
"JackBoomerDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
313 fInputBufferSize = fEngineControl->fBufferSize * fSampleSize * fCaptureChannels;
315 fInputBuffer = (
void*)calloc(fInputBufferSize, 1);
316 assert(fInputBuffer);
324 int JackBoomerDriver::OpenOutput()
328 int cur_sample_format;
329 int cur_playback_channels;
330 jack_nframes_t cur_sample_rate;
332 if (fPlaybackChannels == 0)
333 fPlaybackChannels = 2;
335 if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
336 jack_error(
"JackBoomerDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
340 jack_log(
"JackBoomerDriver::OpenOutput output fOutFD = %d", fOutFD);
343 if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
344 jack_error(
"JackBoomerDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
349 gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
350 if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
351 jack_error(
"JackBoomerDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
355 cur_sample_format = fSampleFormat;
356 if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
357 jack_error(
"JackBoomerDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
360 if (cur_sample_format != fSampleFormat) {
361 jack_info(
"JackBoomerDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
364 cur_playback_channels = fPlaybackChannels;
365 if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
366 jack_error(
"JackBoomerDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
369 if (cur_playback_channels != fPlaybackChannels) {
370 jack_info(
"JackBoomerDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
373 cur_sample_rate = fEngineControl->fSampleRate;
374 if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
375 jack_error(
"JackBoomerDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
378 if (cur_sample_rate != fEngineControl->fSampleRate) {
379 jack_info(
"JackBoomerDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
383 fOutputBufferSize = fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels;
385 fOutputBuffer = (
void*)calloc(fOutputBufferSize, 1);
386 assert(fOutputBuffer);
394 int JackBoomerDriver::Open(jack_nframes_t nframes,
396 jack_nframes_t samplerate,
403 const char* capture_driver_uid,
404 const char* playback_driver_uid,
405 jack_nframes_t capture_latency,
406 jack_nframes_t playback_latency,
407 int bits,
bool syncio)
410 if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
411 capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
415 if (!fEngineControl->fSyncMode) {
416 jack_error(
"Cannot run in asynchronous mode, use the -S parameter for jackd");
420 fRWMode |= ((capturing) ? kRead : 0);
421 fRWMode |= ((playing) ? kWrite : 0);
424 fNperiods = (user_nperiods == 0) ? 1 : user_nperiods ;
429 memset(&gCycleTable, 0,
sizeof(gCycleTable));
441 int JackBoomerDriver::Close()
444 FILE* file = fopen(
"OSSProfiling.log",
"w");
447 jack_info(
"Writing OSS driver timing data....");
448 for (
int i = 1; i < std::min(gCycleReadCount, gCycleWriteCount); i++) {
449 int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
450 int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
451 int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
452 int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
453 fprintf(file,
"%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
457 jack_error(
"JackBoomerDriver::Close : cannot open OSSProfiling.log file");
460 file = fopen(
"TimingOSS.plot",
"w");
463 jack_error(
"JackBoomerDriver::Close cannot open TimingOSS.plot file");
466 fprintf(file,
"set grid\n");
467 fprintf(file,
"set title \"OSS audio driver timing\"\n");
468 fprintf(file,
"set xlabel \"audio cycles\"\n");
469 fprintf(file,
"set ylabel \"usec\"\n");
470 fprintf(file,
"plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
471 \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
472 \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
473 \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
475 fprintf(file,
"set output 'TimingOSS.pdf\n");
476 fprintf(file,
"set terminal pdf\n");
478 fprintf(file,
"set grid\n");
479 fprintf(file,
"set title \"OSS audio driver timing\"\n");
480 fprintf(file,
"set xlabel \"audio cycles\"\n");
481 fprintf(file,
"set ylabel \"usec\"\n");
482 fprintf(file,
"plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
483 \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
484 \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
485 \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
490 int res = JackAudioDriver::Close();
495 int JackBoomerDriver::OpenAux()
499 if ((fRWMode & kRead) && (OpenInput() < 0)) {
503 if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
511 void JackBoomerDriver::CloseAux()
513 if (fRWMode & kRead && fInFD >= 0) {
518 if (fRWMode & kWrite && fOutFD >= 0) {
529 fOutputBuffer = NULL;
532 int JackBoomerDriver::Start()
534 jack_log(
"JackBoomerDriver::Start");
535 JackAudioDriver::Start();
538 if (fInFD >= 0 && fOutFD >= 0 && fSyncIO) {
540 jack_log(
"JackBoomerDriver::Start sync input/output");
547 group.mode = PCM_ENABLE_INPUT;
548 if (ioctl(fInFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
549 jack_error(
"JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCGROUP : %s@%i, errno = %d", __FILE__, __LINE__, errno);
551 group.mode = PCM_ENABLE_OUTPUT;
552 if (ioctl(fOutFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
553 jack_error(
"JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCGROUP : %s@%i, errno = %d", __FILE__, __LINE__, errno);
556 char* silence_buf = (
char*)malloc(fFragmentSize);
557 memset(silence_buf, 0, fFragmentSize);
559 jack_log (
"JackBoomerDriver::Start prefill size = %d", fFragmentSize);
561 for (
int i = 0; i < 2; i++) {
562 ssize_t count = ::write(fOutFD, silence_buf, fFragmentSize);
563 if (count < (
int)fFragmentSize) {
564 jack_error(
"JackBoomerDriver::Start error bytes written = %ld", count);
573 if (ioctl(fInFD, SNDCTL_DSP_SYNCSTART, &
id) == -1)
574 jack_error(
"JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCSTART : %s@%i, errno = %d", __FILE__, __LINE__, errno);
576 }
else if (fOutFD >= 0) {
579 memset(fOutputBuffer, 0, fOutputBufferSize);
582 for (
int i = 0; i < fNperiods; i++) {
583 ssize_t count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
584 if (count < (
int)fOutputBufferSize) {
585 jack_error(
"JackBoomerDriver::Start error bytes written = %ld", count);
592 if (fInputThread.StartSync() < 0) {
600 if (fOutputThread.StartSync() < 0) {
609 int JackBoomerDriver::Stop()
618 fOutputThread.Kill();
624 bool JackBoomerDriver::JackBoomerDriverInput::Init()
626 if (fDriver->IsRealTime()) {
627 jack_log(
"JackBoomerDriverInput::Init IsRealTime");
628 if (fDriver->fInputThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
631 set_threaded_log_function();
639 bool JackBoomerDriver::JackBoomerDriverInput::Execute()
643 gCycleTable.fTable[gCycleReadCount].fBeforeRead = GetMicroSeconds();
647 ssize_t count = ::read(fDriver->fInFD, fDriver->fInputBuffer, fDriver->fInputBufferSize);
650 if (count > 0 && count != (
int)fDriver->fInputBufferSize)
651 jack_log(
"JackBoomerDriverInput::Execute count = %ld", count / (fDriver->fSampleSize * fDriver->fCaptureChannels));
652 gCycleTable.fTable[gCycleReadCount].fAfterRead = GetMicroSeconds();
656 if (ioctl(fDriver->fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
658 if (ei_in.rec_overruns > 0 ) {
659 jack_error(
"JackBoomerDriverInput::Execute overruns");
660 jack_time_t cur_time = GetMicroSeconds();
661 fDriver->NotifyXRun(cur_time,
float(cur_time - fDriver->fBeginDateUst));
664 if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
665 jack_error(
"%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
670 jack_log(
"JackBoomerDriverInput::Execute error = %s", strerror(errno));
671 }
else if (count < (
int)fDriver->fInputBufferSize) {
672 jack_error(
"JackBoomerDriverInput::Execute error bytes read = %ld", count);
676 fDriver->CycleTakeBeginTime();
677 for (
int i = 0; i < fDriver->fCaptureChannels; i++) {
678 if (fDriver->fGraphManager->GetConnectionsNum(fDriver->fCapturePortList[i]) > 0) {
679 CopyAndConvertIn(fDriver->GetInputBuffer(i),
680 fDriver->fInputBuffer,
681 fDriver->fEngineControl->fBufferSize,
683 fDriver->fCaptureChannels * fDriver->fSampleSize,
689 gCycleTable.fTable[gCycleReadCount].fAfterReadConvert = GetMicroSeconds();
690 gCycleReadCount = (gCycleReadCount == CYCLE_POINTS - 1) ? gCycleReadCount: gCycleReadCount + 1;
695 if (fDriver->fInFD >= 0 && fDriver->fOutFD >= 0) {
696 fDriver->SynchronizeRead();
704 bool JackBoomerDriver::JackBoomerDriverOutput::Init()
706 if (fDriver->IsRealTime()) {
707 jack_log(
"JackBoomerDriverOutput::Init IsRealTime");
708 if (fDriver->fOutputThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
711 set_threaded_log_function();
716 if (ioctl(fDriver->fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
717 jack_error(
"JackBoomerDriverOutput::Init error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
720 delay /= fDriver->fSampleSize * fDriver->fPlaybackChannels;
721 jack_info(
"JackBoomerDriverOutput::Init output latency frames = %ld", delay);
727 bool JackBoomerDriver::JackBoomerDriverOutput::Execute()
729 memset(fDriver->fOutputBuffer, 0, fDriver->fOutputBufferSize);
732 gCycleTable.fTable[gCycleWriteCount].fBeforeWriteConvert = GetMicroSeconds();
735 for (
int i = 0; i < fDriver->fPlaybackChannels; i++) {
736 if (fDriver->fGraphManager->GetConnectionsNum(fDriver->fPlaybackPortList[i]) > 0) {
737 CopyAndConvertOut(fDriver->fOutputBuffer,
738 fDriver->GetOutputBuffer(i),
739 fDriver->fEngineControl->fBufferSize,
741 fDriver->fPlaybackChannels * fDriver->fSampleSize,
747 gCycleTable.fTable[gCycleWriteCount].fBeforeWrite = GetMicroSeconds();
750 ssize_t count = ::write(fDriver->fOutFD, fDriver->fOutputBuffer, fDriver->fOutputBufferSize);
753 if (count > 0 && count != (
int)fDriver->fOutputBufferSize)
754 jack_log(
"JackBoomerDriverOutput::Execute count = %ld", count / (fDriver->fSampleSize * fDriver->fPlaybackChannels));
755 gCycleTable.fTable[gCycleWriteCount].fAfterWrite = GetMicroSeconds();
756 gCycleWriteCount = (gCycleWriteCount == CYCLE_POINTS - 1) ? gCycleWriteCount: gCycleWriteCount + 1;
760 audio_errinfo ei_out;
761 if (ioctl(fDriver->fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) {
763 if (ei_out.play_underruns > 0) {
764 jack_error(
"JackBoomerDriverOutput::Execute underruns");
765 jack_time_t cur_time = GetMicroSeconds();
766 fDriver->NotifyXRun(cur_time,
float(cur_time - fDriver->fBeginDateUst));
769 if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
770 jack_error(
"%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
775 jack_log(
"JackBoomerDriverOutput::Execute error = %s", strerror(errno));
776 }
else if (count < (
int)fDriver->fOutputBufferSize) {
777 jack_error(
"JackBoomerDriverOutput::Execute error bytes written = %ld", count);
781 if (fDriver->fInFD >= 0 && fDriver->fOutFD >= 0) {
782 fDriver->SynchronizeWrite();
785 fDriver->CycleTakeBeginTime();
791 void JackBoomerDriver::SynchronizeRead()
793 sem_wait(&fWriteSema);
795 sem_post(&fReadSema);
798 void JackBoomerDriver::SynchronizeWrite()
800 sem_post(&fWriteSema);
801 sem_wait(&fReadSema);
804 int JackBoomerDriver::SetBufferSize(jack_nframes_t buffer_size)
807 JackAudioDriver::SetBufferSize(buffer_size);
824 desc = jack_driver_descriptor_construct(
"boomer", JackDriverMaster,
"Boomer/OSS API based audio backend", &filler);
826 value.ui = OSS_DRIVER_DEF_FS;
827 jack_driver_descriptor_add_parameter(desc, &filler,
"rate",
'r', JackDriverParamUInt, &value, NULL,
"Sample rate", NULL);
829 value.ui = OSS_DRIVER_DEF_BLKSIZE;
830 jack_driver_descriptor_add_parameter(desc, &filler,
"period",
'p', JackDriverParamUInt, &value, NULL,
"Frames per period", NULL);
832 value.ui = OSS_DRIVER_DEF_NPERIODS;
833 jack_driver_descriptor_add_parameter(desc, &filler,
"nperiods",
'n', JackDriverParamUInt, &value, NULL,
"Number of periods to prefill output buffer", NULL);
835 value.i = OSS_DRIVER_DEF_BITS;
836 jack_driver_descriptor_add_parameter(desc, &filler,
"wordlength",
'w', JackDriverParamInt, &value, NULL,
"Word length", NULL);
838 value.ui = OSS_DRIVER_DEF_INS;
839 jack_driver_descriptor_add_parameter(desc, &filler,
"inchannels",
'i', JackDriverParamUInt, &value, NULL,
"Capture channels", NULL);
841 value.ui = OSS_DRIVER_DEF_OUTS;
842 jack_driver_descriptor_add_parameter(desc, &filler,
"outchannels",
'o', JackDriverParamUInt, &value, NULL,
"Playback channels", NULL);
845 jack_driver_descriptor_add_parameter(desc, &filler,
"excl",
'e', JackDriverParamBool, &value, NULL,
"Exclusif (O_EXCL) access mode", NULL);
847 strcpy(value.str, OSS_DRIVER_DEF_DEV);
848 jack_driver_descriptor_add_parameter(desc, &filler,
"capture",
'C', JackDriverParamString, &value, NULL,
"Input device", NULL);
849 jack_driver_descriptor_add_parameter(desc, &filler,
"playback",
'P', JackDriverParamString, &value, NULL,
"Output device", NULL);
850 jack_driver_descriptor_add_parameter(desc, &filler,
"device",
'd', JackDriverParamString, &value, NULL,
"OSS device name", NULL);
853 jack_driver_descriptor_add_parameter(desc, &filler,
"input-latency",
'I', JackDriverParamUInt, &value, NULL,
"Extra input latency", NULL);
854 jack_driver_descriptor_add_parameter(desc, &filler,
"output-latency",
'O', JackDriverParamUInt, &value, NULL,
"Extra output latency", NULL);
857 jack_driver_descriptor_add_parameter(desc, &filler,
"sync-io",
'S', JackDriverParamBool, &value, NULL,
"In duplex mode, synchronize input and output", NULL);
864 int bits = OSS_DRIVER_DEF_BITS;
865 jack_nframes_t srate = OSS_DRIVER_DEF_FS;
866 jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE;
867 const char* capture_pcm_name = OSS_DRIVER_DEF_DEV;
868 const char* playback_pcm_name = OSS_DRIVER_DEF_DEV;
869 bool capture =
false;
870 bool playback =
false;
873 bool monitor =
false;
876 unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
879 jack_nframes_t systemic_input_latency = 0;
880 jack_nframes_t systemic_output_latency = 0;
882 for (node = params; node; node = jack_slist_next(node)) {
886 switch (param->character) {
889 srate = param->value.ui;
893 frames_per_interrupt = (
unsigned int)param->value.ui;
897 nperiods = (
unsigned int)param->value.ui;
901 bits = param->value.i;
905 chan_in = (int)param->value.ui;
909 chan_out = (
int)param->value.ui;
914 if (strcmp(param->value.str,
"none") != 0) {
915 capture_pcm_name = param->value.str;
921 if (strcmp(param->value.str,
"none") != 0) {
922 playback_pcm_name = param->value.str;
927 playback_pcm_name = param->value.str;
928 capture_pcm_name = param->value.str;
936 systemic_input_latency = param->value.ui;
940 systemic_output_latency = param->value.ui;
950 if (!capture && !playback) {
958 if (boomer_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out, excl,
959 monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, syncio) == 0) {
960 return boomer_driver;
962 delete boomer_driver;
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
The base interface for drivers clients.
SERVER_EXPORT void jack_log(const char *fmt,...)