jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1428 lines
54KB

  1. /*
  2. Copyright (C) 2003-2007 Jussi Laako <jussi@sonarnerd.net>
  3. Copyright (C) 2008 Grame & RTL 2008
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "driver_interface.h"
  17. #include "JackThreadedDriver.h"
  18. #include "JackDriverLoader.h"
  19. #include "JackOSSDriver.h"
  20. #include "JackEngineControl.h"
  21. #include "JackGraphManager.h"
  22. #include "JackError.h"
  23. #include "JackTime.h"
  24. #include "JackShmMem.h"
  25. #include "memops.h"
  26. #include <sys/ioctl.h>
  27. #include <sys/soundcard.h>
  28. #include <fcntl.h>
  29. #include <iostream>
  30. #include <assert.h>
  31. #include <stdio.h>
  32. using namespace std;
  33. namespace
  34. {
  35. inline jack_nframes_t TimeToFrames(jack_time_t time, jack_nframes_t sample_rate) {
  36. return ((time * sample_rate) + 500000ULL) / 1000000ULL;
  37. }
  38. inline long long TimeToOffset(jack_time_t time1, jack_time_t time2, jack_nframes_t sample_rate)
  39. {
  40. if (time2 > time1) {
  41. return TimeToFrames(time2 - time1, sample_rate);
  42. } else {
  43. return 0LL - TimeToFrames(time1 - time2, sample_rate);
  44. }
  45. }
  46. inline jack_time_t FramesToTime(jack_nframes_t frames, jack_nframes_t sample_rate) {
  47. return ((frames * 1000000ULL) + (sample_rate / 2ULL)) / sample_rate;
  48. }
  49. inline jack_nframes_t RoundUp(jack_nframes_t frames, jack_nframes_t block) {
  50. if (block > 0) {
  51. frames += (block - 1);
  52. frames -= (frames % block);
  53. }
  54. return frames;
  55. }
  56. inline jack_time_t RoundDown(jack_time_t time, jack_time_t interval) {
  57. if (interval > 0) {
  58. time -= (time % interval);
  59. }
  60. return time;
  61. }
  62. int GetSampleFormat(int bits)
  63. {
  64. switch(bits) {
  65. // Native-endian signed 32 bit samples.
  66. case 32:
  67. return AFMT_S32_NE;
  68. // Native-endian signed 24 bit (packed) samples.
  69. case 24:
  70. return AFMT_S24_NE;
  71. // Native-endian signed 16 bit samples, used by default.
  72. case 16:
  73. default:
  74. return AFMT_S16_NE;
  75. }
  76. }
  77. unsigned int GetSampleSize(int format)
  78. {
  79. switch(format) {
  80. // Native-endian signed 32 bit samples.
  81. case AFMT_S32_NE:
  82. return 4;
  83. // Native-endian signed 24 bit (packed) samples.
  84. case AFMT_S24_NE:
  85. return 3;
  86. // Native-endian signed 16 bit samples.
  87. case AFMT_S16_NE:
  88. return 2;
  89. // Unsupported sample format.
  90. default:
  91. return 0;
  92. }
  93. }
  94. inline int UpToPower2(int x)
  95. {
  96. int r = 0;
  97. while ((1 << r) < x)
  98. r++;
  99. return r;
  100. }
  101. }
  102. namespace Jack
  103. {
  104. #ifdef JACK_MONITOR
  105. #define CYCLE_POINTS 500000
  106. struct OSSCycle {
  107. jack_time_t fBeforeRead;
  108. jack_time_t fAfterRead;
  109. jack_time_t fAfterReadConvert;
  110. jack_time_t fBeforeWrite;
  111. jack_time_t fAfterWrite;
  112. jack_time_t fBeforeWriteConvert;
  113. };
  114. struct OSSCycleTable {
  115. jack_time_t fBeforeFirstWrite;
  116. jack_time_t fAfterFirstWrite;
  117. OSSCycle fTable[CYCLE_POINTS];
  118. };
  119. OSSCycleTable gCycleTable;
  120. int gCycleCount = 0;
  121. #endif
  122. static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
  123. {
  124. switch (bits) {
  125. case 16: {
  126. signed short *s16src = (signed short*)src;
  127. s16src += channel;
  128. sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
  129. break;
  130. }
  131. case 24: {
  132. char *s24src = (char*)src;
  133. s24src += channel * 3;
  134. sample_move_dS_s24(dst, s24src, nframes, chcount*3);
  135. break;
  136. }
  137. case 32: {
  138. signed int *s32src = (signed int*)src;
  139. s32src += channel;
  140. sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
  141. break;
  142. }
  143. }
  144. }
  145. static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
  146. {
  147. switch (bits) {
  148. case 16: {
  149. signed short *s16dst = (signed short*)dst;
  150. s16dst += channel;
  151. sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now...
  152. break;
  153. }
  154. case 24: {
  155. char *s24dst = (char*)dst;
  156. s24dst += channel * 3;
  157. sample_move_d24_sS(s24dst, src, nframes, chcount*3, NULL);
  158. break;
  159. }
  160. case 32: {
  161. signed int *s32dst = (signed int*)dst;
  162. s32dst += channel;
  163. sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
  164. break;
  165. }
  166. }
  167. }
  168. void JackOSSDriver::DisplayDeviceInfo()
  169. {
  170. audio_buf_info info;
  171. memset(&info, 0, sizeof(audio_buf_info));
  172. int cap = 0;
  173. // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
  174. jack_info("Audio Interface Description :");
  175. jack_info("Sampling Frequency : %d, Sample Size : %d", fEngineControl->fSampleRate, fInSampleSize * 8);
  176. if (fPlayback) {
  177. oss_sysinfo si;
  178. if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
  179. jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  180. } else {
  181. jack_info("OSS product %s", si.product);
  182. jack_info("OSS version %s", si.version);
  183. jack_info("OSS version num %d", si.versionnum);
  184. jack_info("OSS numaudios %d", si.numaudios);
  185. jack_info("OSS numaudioengines %d", si.numaudioengines);
  186. jack_info("OSS numcards %d", si.numcards);
  187. }
  188. jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
  189. jack_info("Output block size = %d", fOutputBufferSize);
  190. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  191. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  192. } else {
  193. jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  194. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  195. }
  196. if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  197. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  198. } else {
  199. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  200. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  201. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  202. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  203. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  204. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  205. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  206. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  207. }
  208. }
  209. if (fCapture) {
  210. oss_sysinfo si;
  211. if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
  212. jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  213. } else {
  214. jack_info("OSS product %s", si.product);
  215. jack_info("OSS version %s", si.version);
  216. jack_info("OSS version num %d", si.versionnum);
  217. jack_info("OSS numaudios %d", si.numaudios);
  218. jack_info("OSS numaudioengines %d", si.numaudioengines);
  219. jack_info("OSS numcards %d", si.numcards);
  220. }
  221. jack_info("Input capabilities - %d channels : ", fCaptureChannels);
  222. jack_info("Input block size = %d", fInputBufferSize);
  223. if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
  224. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  225. } else {
  226. jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  227. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  228. }
  229. if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  230. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  231. } else {
  232. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  233. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  234. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  235. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  236. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  237. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  238. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  239. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  240. }
  241. }
  242. }
  243. int JackOSSDriver::ProbeInBlockSize()
  244. {
  245. jack_nframes_t blocks[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  246. int probes = 0;
  247. int ret = 0;
  248. // Default values in case of an error.
  249. fInMeanStep = fEngineControl->fBufferSize;
  250. fInBlockSize = 1;
  251. if (fInFD > 0) {
  252. // Read one frame into a new hardware block so we can check its size.
  253. // Repeat that for multiple probes, sometimes the first reads differ.
  254. jack_nframes_t frames = 1;
  255. for (int p = 0; p < 8 && frames > 0; ++p) {
  256. ret = Discard(frames);
  257. frames = 0;
  258. if (ret == 0) {
  259. oss_count_t ptr;
  260. if (ioctl(fInFD, SNDCTL_DSP_CURRENT_IPTR, &ptr) == 0 && ptr.fifo_samples > 0) {
  261. // Success, store probed hardware block size for later.
  262. blocks[p] = 1U + ptr.fifo_samples;
  263. ++probes;
  264. // Proceed by reading one frame into the next hardware block.
  265. frames = blocks[p];
  266. }
  267. } else {
  268. // Read error - abort.
  269. jack_error("JackOSSDriver::ProbeInBlockSize read failed with %d", ret);
  270. }
  271. }
  272. // Stop recording.
  273. ioctl(fInFD, SNDCTL_DSP_HALT_INPUT, NULL);
  274. }
  275. if (probes == 8) {
  276. // Compute mean block size of the last six probes.
  277. jack_nframes_t sum = 0;
  278. for (int p = 2; p < 8; ++p) {
  279. jack_log("JackOSSDriver::ProbeInBlockSize read block of %d frames", blocks[p]);
  280. sum += blocks[p];
  281. }
  282. fInMeanStep = sum / 6;
  283. // Check that none of the probed block sizes deviates too much.
  284. jack_nframes_t slack = fInMeanStep / 16;
  285. bool strict = true;
  286. for (int p = 2; p < 8; ++p) {
  287. strict = strict && (blocks[p] > fInMeanStep - slack) && (blocks[p] < fInMeanStep + slack);
  288. }
  289. if (strict && fInMeanStep <= fEngineControl->fBufferSize) {
  290. // Regular hardware block size, use it for rounding.
  291. jack_info("JackOSSDriver::ProbeInBlockSize read blocks are %d frames", fInMeanStep);
  292. fInBlockSize = fInMeanStep;
  293. } else {
  294. jack_info("JackOSSDriver::ProbeInBlockSize irregular read block sizes");
  295. jack_info("JackOSSDriver::ProbeInBlockSize mean read block was %d frames", fInMeanStep);
  296. }
  297. if (fInBlockSize > fEngineControl->fBufferSize / 2) {
  298. jack_info("JackOSSDriver::ProbeInBlockSize less than two read blocks per cycle");
  299. jack_info("JackOSSDriver::ProbeInBlockSize for best results make period a multiple of %d", fInBlockSize);
  300. }
  301. if (fInMeanStep > fEngineControl->fBufferSize) {
  302. jack_error("JackOSSDriver::ProbeInBlockSize period is too small, minimum is %d frames", fInMeanStep);
  303. return -1;
  304. }
  305. }
  306. return ret;
  307. }
  308. int JackOSSDriver::ProbeOutBlockSize()
  309. {
  310. jack_nframes_t blocks[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  311. int probes = 0;
  312. int ret = 0;
  313. // Default values in case of an error.
  314. fOutMeanStep = fEngineControl->fBufferSize;
  315. fOutBlockSize = 1;
  316. if (fOutFD) {
  317. // Write one frame over the low water mark, then check the consumed block size.
  318. // Repeat that for multiple probes, sometimes the initial ones differ.
  319. jack_nframes_t mark = fNperiods * fEngineControl->fBufferSize;
  320. WriteSilence(mark + 1);
  321. for (int p = 0; p < 8 && ret >= 0; ++p) {
  322. pollfd poll_fd;
  323. poll_fd.fd = fOutFD;
  324. poll_fd.events = POLLOUT;
  325. ret = poll(&poll_fd, 1, 500);
  326. if (ret < 0) {
  327. jack_error("JackOSSDriver::ProbeOutBlockSize poll failed with %d", ret);
  328. break;
  329. }
  330. if (poll_fd.revents & POLLOUT) {
  331. oss_count_t ptr;
  332. if (ioctl(fOutFD, SNDCTL_DSP_CURRENT_OPTR, &ptr) != -1 && ptr.fifo_samples >= 0) {
  333. // Success, store probed hardware block size for later.
  334. blocks[p] = mark + 1 - ptr.fifo_samples;
  335. ++probes;
  336. // Proceed by writing one frame over the low water mark.
  337. WriteSilence(blocks[p]);
  338. }
  339. poll_fd.revents = 0;
  340. }
  341. }
  342. // Stop playback.
  343. ioctl(fOutFD, SNDCTL_DSP_HALT_INPUT, NULL);
  344. }
  345. if (probes == 8) {
  346. // Compute mean and maximum block size of the last six probes.
  347. jack_nframes_t sum = 0;
  348. for (int p = 2; p < 8; ++p) {
  349. jack_log("JackOSSDriver::ProbeOutBlockSize write block of %d frames", blocks[p]);
  350. sum += blocks[p];
  351. }
  352. fOutMeanStep = sum / 6;
  353. // Check that none of the probed block sizes deviates too much.
  354. jack_nframes_t slack = fOutMeanStep / 16;
  355. bool strict = true;
  356. for (int p = 2; p < 8; ++p) {
  357. strict = strict && (blocks[p] > fOutMeanStep - slack) && (blocks[p] < fOutMeanStep + slack);
  358. }
  359. if (strict && fOutMeanStep <= fEngineControl->fBufferSize) {
  360. // Regular hardware block size, use it for rounding.
  361. jack_info("JackOSSDriver::ProbeOutBlockSize write blocks are %d frames", fOutMeanStep);
  362. fOutBlockSize = fOutMeanStep;
  363. } else {
  364. jack_info("JackOSSDriver::ProbeOutBlockSize irregular write block sizes");
  365. jack_info("JackOSSDriver::ProbeOutBlockSize mean write block was %d frames", fOutMeanStep);
  366. }
  367. if (fOutBlockSize > fEngineControl->fBufferSize / 2) {
  368. jack_info("JackOSSDriver::ProbeOutBlockSize less than two write blocks per cycle");
  369. jack_info("JackOSSDriver::ProbeOutBlockSize for best results make period a multiple of %d", fOutBlockSize);
  370. }
  371. if (fOutMeanStep > fEngineControl->fBufferSize) {
  372. jack_error("JackOSSDriver::ProbeOutBlockSize period is too small, minimum is %d frames", fOutMeanStep);
  373. return -1;
  374. }
  375. }
  376. return ret;
  377. }
  378. int JackOSSDriver::Discard(jack_nframes_t frames)
  379. {
  380. if (fInFD < 0) {
  381. return -1;
  382. }
  383. // Read frames from OSS capture buffer to be discarded.
  384. ssize_t size = frames * fInSampleSize * fCaptureChannels;
  385. while (size > 0) {
  386. ssize_t chunk = (size > fInputBufferSize) ? fInputBufferSize : size;
  387. ssize_t count = ::read(fInFD, fInputBuffer, chunk);
  388. if (count <= 0) {
  389. jack_error("JackOSSDriver::Discard error bytes read = %ld", count);
  390. return -1;
  391. }
  392. fOSSReadOffset += count / (fInSampleSize * fCaptureChannels);
  393. size -= count;
  394. }
  395. return 0;
  396. }
  397. int JackOSSDriver::WriteSilence(jack_nframes_t frames)
  398. {
  399. if (fOutFD < 0) {
  400. return -1;
  401. }
  402. // Fill OSS playback buffer, write some periods of silence.
  403. memset(fOutputBuffer, 0, fOutputBufferSize);
  404. ssize_t size = frames * fOutSampleSize * fPlaybackChannels;
  405. while (size > 0) {
  406. ssize_t chunk = (size > fOutputBufferSize) ? fOutputBufferSize : size;
  407. ssize_t count = ::write(fOutFD, fOutputBuffer, chunk);
  408. if (count <= 0) {
  409. jack_error("JackOSSDriver::WriteSilence error bytes written = %ld", count);
  410. return -1;
  411. }
  412. fOSSWriteOffset += (count / (fOutSampleSize * fPlaybackChannels));
  413. size -= count;
  414. }
  415. return 0;
  416. }
  417. int JackOSSDriver::WaitAndSync()
  418. {
  419. oss_count_t ptr = {0, 0, {0}};
  420. if (fInFD > 0 && fOSSReadSync != 0) {
  421. // Predict time of next capture sync (poll() return).
  422. if (fOSSReadOffset + fEngineControl->fBufferSize > 0) {
  423. jack_nframes_t frames = fOSSReadOffset + fEngineControl->fBufferSize;
  424. jack_nframes_t rounded = RoundUp(frames, fInBlockSize);
  425. fOSSReadSync += FramesToTime(rounded, fEngineControl->fSampleRate);
  426. fOSSReadOffset -= rounded;
  427. }
  428. }
  429. if (fOutFD > 0 && fOSSWriteSync != 0) {
  430. // Predict time of next playback sync (poll() return).
  431. if (fOSSWriteOffset > fNperiods * fEngineControl->fBufferSize) {
  432. jack_nframes_t frames = fOSSWriteOffset - fNperiods * fEngineControl->fBufferSize;
  433. jack_nframes_t rounded = RoundUp(frames, fOutBlockSize);
  434. fOSSWriteSync += FramesToTime(rounded, fEngineControl->fSampleRate);
  435. fOSSWriteOffset -= rounded;
  436. }
  437. }
  438. jack_time_t poll_start = GetMicroSeconds();
  439. // Poll until recording and playback buffer are ready for this cycle.
  440. pollfd poll_fd[2];
  441. poll_fd[0].fd = fInFD;
  442. if (fInFD > 0 && (fForceSync || poll_start < fOSSReadSync)) {
  443. poll_fd[0].events = POLLIN;
  444. } else {
  445. poll_fd[0].events = 0;
  446. }
  447. poll_fd[1].fd = fOutFD;
  448. if (fOutFD > 0 && (fForceSync || poll_start < fOSSWriteSync)) {
  449. poll_fd[1].events = POLLOUT;
  450. } else {
  451. poll_fd[1].events = 0;
  452. }
  453. while (poll_fd[0].events != 0 || poll_fd[1].events != 0) {
  454. poll_fd[0].revents = 0;
  455. poll_fd[1].revents = 0;
  456. int ret = poll(poll_fd, 2, 500);
  457. jack_time_t now = GetMicroSeconds();
  458. if (ret <= 0) {
  459. jack_error("JackOSSDriver::WaitAndSync poll failed with %d after %ld us", ret, now - poll_start);
  460. return ret;
  461. }
  462. if (poll_fd[0].revents & POLLIN) {
  463. // Check the excess recording frames.
  464. if (ioctl(fInFD, SNDCTL_DSP_CURRENT_IPTR, &ptr) != -1 && ptr.fifo_samples >= 0) {
  465. if (fInBlockSize <= 1) {
  466. // Irregular block size, let sync time converge slowly when late.
  467. fOSSReadSync = min(fOSSReadSync, now) / 2 + now / 2;
  468. fOSSReadOffset = -ptr.fifo_samples;
  469. } else if (ptr.fifo_samples - fEngineControl->fBufferSize >= fInBlockSize) {
  470. // Too late for a reliable sync, make sure sync time is not in the future.
  471. if (now < fOSSReadSync) {
  472. fOSSReadOffset = -ptr.fifo_samples;
  473. jack_info("JackOSSDriver::WaitAndSync capture sync %ld us early, %ld frames", fOSSReadSync - now, fOSSReadOffset);
  474. fOSSReadSync = now;
  475. }
  476. } else if (fForceSync) {
  477. // Uncertain previous sync, just use sync time directly.
  478. fOSSReadSync = now;
  479. fOSSReadOffset = -ptr.fifo_samples;
  480. } else {
  481. // Adapt expected sync time when early or late - in whole block intervals.
  482. // Account for some speed drift, but otherwise round down to earlier interval.
  483. jack_time_t interval = FramesToTime(fInBlockSize, fEngineControl->fSampleRate);
  484. jack_time_t remainder = fOSSReadSync % interval;
  485. jack_time_t max_drift = interval / 4;
  486. jack_time_t rounded = RoundDown((now - remainder) + max_drift, interval) + remainder;
  487. // Let sync time converge slowly when late, prefer earlier sync times.
  488. fOSSReadSync = min(rounded, now) / 2 + now / 2;
  489. fOSSReadOffset = -ptr.fifo_samples;
  490. }
  491. }
  492. poll_fd[0].events = 0;
  493. }
  494. if (poll_fd[1].revents & POLLOUT) {
  495. // Check the remaining playback frames.
  496. if (ioctl(fOutFD, SNDCTL_DSP_CURRENT_OPTR, &ptr) != -1 && ptr.fifo_samples >= 0) {
  497. if (fOutBlockSize <= 1) {
  498. // Irregular block size, let sync time converge slowly when late.
  499. fOSSWriteSync = min(fOSSWriteSync, now) / 2 + now / 2;
  500. fOSSWriteOffset = ptr.fifo_samples;
  501. } else if (ptr.fifo_samples + fOutBlockSize <= fNperiods * fEngineControl->fBufferSize) {
  502. // Too late for a reliable sync, make sure sync time is not in the future.
  503. if (now < fOSSWriteSync) {
  504. fOSSWriteOffset = ptr.fifo_samples;
  505. jack_info("JackOSSDriver::WaitAndSync playback sync %ld us early, %ld frames", fOSSWriteSync - now, fOSSWriteOffset);
  506. fOSSWriteSync = now;
  507. }
  508. } else if (fForceSync) {
  509. // Uncertain previous sync, just use sync time directly.
  510. fOSSWriteSync = now;
  511. fOSSWriteOffset = ptr.fifo_samples;
  512. } else {
  513. // Adapt expected sync time when early or late - in whole block intervals.
  514. // Account for some speed drift, but otherwise round down to earlier interval.
  515. jack_time_t interval = FramesToTime(fOutBlockSize, fEngineControl->fSampleRate);
  516. jack_time_t remainder = fOSSWriteSync % interval;
  517. jack_time_t max_drift = interval / 4;
  518. jack_time_t rounded = RoundDown((now - remainder) + max_drift, interval) + remainder;
  519. // Let sync time converge slowly when late, prefer earlier sync times.
  520. fOSSWriteSync = min(rounded, now) / 2 + now / 2;
  521. fOSSWriteOffset = ptr.fifo_samples;
  522. }
  523. }
  524. poll_fd[1].events = 0;
  525. }
  526. }
  527. fForceSync = false;
  528. // Compute balance of read and write buffers combined.
  529. fBufferBalance = 0;
  530. if (fInFD > 0 && fOutFD > 0) {
  531. // Compare actual buffer content with target of (1 + n) * period.
  532. fBufferBalance += ((1 + fNperiods) * fEngineControl->fBufferSize);
  533. fBufferBalance -= (fOSSWriteOffset - fOSSReadOffset);
  534. fBufferBalance += TimeToOffset(fOSSWriteSync, fOSSReadSync, fEngineControl->fSampleRate);
  535. // Force balancing if sync times deviate too much.
  536. jack_time_t slack = FramesToTime((fEngineControl->fBufferSize * 2) / 3, fEngineControl->fSampleRate);
  537. fForceBalancing = fForceBalancing || (fOSSReadSync > fOSSWriteSync + slack);
  538. fForceBalancing = fForceBalancing || (fOSSWriteSync > fOSSReadSync + slack);
  539. // Force balancing if buffer is badly balanced.
  540. fForceBalancing = fForceBalancing || (abs(fBufferBalance) > max(fInMeanStep, fOutMeanStep));
  541. }
  542. // Print debug info every 10 seconds.
  543. if (ptr.samples > 0 && (ptr.samples % (10 * fEngineControl->fSampleRate)) < fEngineControl->fBufferSize) {
  544. jack_log("JackOSSDriver::Read buffer balance is %ld frames", fBufferBalance);
  545. jack_time_t now = GetMicroSeconds();
  546. jack_log("JackOSSDriver::Read recording sync %ld frames %ld us ago", fOSSReadOffset, now - fOSSReadSync);
  547. jack_log("JackOSSDriver::Read playback sync %ld frames %ld us ago", fOSSWriteOffset, now - fOSSWriteSync);
  548. }
  549. return 0;
  550. }
  551. int JackOSSDriver::OpenInput()
  552. {
  553. int flags = 0;
  554. int gFragFormat;
  555. int cur_capture_channels;
  556. int cur_sample_format;
  557. jack_nframes_t cur_sample_rate;
  558. audio_buf_info info;
  559. if (fCaptureChannels == 0) fCaptureChannels = 2;
  560. if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  561. jack_error("JackOSSDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  562. return -1;
  563. }
  564. jack_log("JackOSSDriver::OpenInput input fInFD = %d", fInFD);
  565. if (fExcl) {
  566. if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  567. jack_error("JackOSSDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  568. goto error;
  569. }
  570. }
  571. cur_sample_format = GetSampleFormat(fBits);
  572. if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &cur_sample_format) == -1) {
  573. jack_error("JackOSSDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  574. goto error;
  575. }
  576. fInSampleSize = GetSampleSize(cur_sample_format);
  577. if (cur_sample_format != GetSampleFormat(fBits)) {
  578. if (fInSampleSize > 0) {
  579. jack_info("JackOSSDriver::OpenInput driver forced %d bit sample format", fInSampleSize * 8);
  580. } else {
  581. jack_error("JackOSSDriver::OpenInput unsupported sample format %#x", cur_sample_format);
  582. goto error;
  583. }
  584. }
  585. cur_capture_channels = fCaptureChannels;
  586. if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
  587. jack_error("JackOSSDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  588. goto error;
  589. }
  590. if (cur_capture_channels != fCaptureChannels) {
  591. jack_info("JackOSSDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
  592. }
  593. cur_sample_rate = fEngineControl->fSampleRate;
  594. if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  595. jack_error("JackOSSDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  596. goto error;
  597. }
  598. if (cur_sample_rate != fEngineControl->fSampleRate) {
  599. jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  600. }
  601. // Internal buffer size required for one period.
  602. fInputBufferSize = fEngineControl->fBufferSize * fInSampleSize * fCaptureChannels;
  603. // Get the total size of the OSS recording buffer, in sample frames.
  604. info = {0, 0, 0, 0};
  605. if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1 || info.fragsize <= 0 || info.fragstotal <= 0) {
  606. jack_error("JackOSSDriver::OpenInput failed to get buffer info : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  607. goto error;
  608. }
  609. fOSSInBuffer = info.fragstotal * info.fragsize / (fInSampleSize * fCaptureChannels);
  610. if (fOSSInBuffer < fEngineControl->fBufferSize * (1 + fNperiods)) {
  611. // Total size of the OSS recording buffer is too small, resize it.
  612. unsigned int buf_size = fInputBufferSize * (1 + fNperiods);
  613. // Keep current fragment size if possible - respect OSS latency settings.
  614. gFragFormat = UpToPower2(info.fragsize);
  615. unsigned int frag_size = 1U << gFragFormat;
  616. gFragFormat |= ((buf_size + frag_size - 1) / frag_size) << 16;
  617. jack_info("JackOSSDriver::OpenInput request %d fragments of %d", (gFragFormat >> 16), frag_size);
  618. if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  619. jack_error("JackOSSDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  620. goto error;
  621. }
  622. // Check the new OSS recording buffer size.
  623. info = {0, 0, 0, 0};
  624. if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1 || info.fragsize <= 0 || info.fragstotal <= 0) {
  625. jack_error("JackOSSDriver::OpenInput failed to get buffer info : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  626. goto error;
  627. }
  628. fOSSInBuffer = info.fragstotal * info.fragsize / (fInSampleSize * fCaptureChannels);
  629. }
  630. if (fOSSInBuffer > fEngineControl->fBufferSize) {
  631. int mark = fInputBufferSize;
  632. if (ioctl(fInFD, SNDCTL_DSP_LOW_WATER, &mark) != 0) {
  633. jack_error("JackOSSDriver::OpenInput failed to set low water mark : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  634. goto error;
  635. }
  636. jack_info("JackOSSDriver::OpenInput set low water mark to %d", mark);
  637. }
  638. fInputBuffer = (void*)calloc(fInputBufferSize, 1);
  639. assert(fInputBuffer);
  640. if (ProbeInBlockSize() < 0) {
  641. goto error;
  642. }
  643. return 0;
  644. error:
  645. ::close(fInFD);
  646. return -1;
  647. }
  648. int JackOSSDriver::OpenOutput()
  649. {
  650. int flags = 0;
  651. int gFragFormat;
  652. int cur_sample_format;
  653. int cur_playback_channels;
  654. jack_nframes_t cur_sample_rate;
  655. audio_buf_info info;
  656. if (fPlaybackChannels == 0) fPlaybackChannels = 2;
  657. if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  658. jack_error("JackOSSDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  659. return -1;
  660. }
  661. jack_log("JackOSSDriver::OpenOutput output fOutFD = %d", fOutFD);
  662. if (fExcl) {
  663. if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  664. jack_error("JackOSSDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  665. goto error;
  666. }
  667. }
  668. cur_sample_format = GetSampleFormat(fBits);
  669. if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &cur_sample_format) == -1) {
  670. jack_error("JackOSSDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  671. goto error;
  672. }
  673. fOutSampleSize = GetSampleSize(cur_sample_format);
  674. if (cur_sample_format != GetSampleFormat(fBits)) {
  675. if (fOutSampleSize > 0) {
  676. jack_info("JackOSSDriver::OpenOutput driver forced %d bit sample format", fOutSampleSize * 8);
  677. } else {
  678. jack_error("JackOSSDriver::OpenOutput unsupported sample format %#x", cur_sample_format);
  679. goto error;
  680. }
  681. }
  682. cur_playback_channels = fPlaybackChannels;
  683. if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
  684. jack_error("JackOSSDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  685. goto error;
  686. }
  687. if (cur_playback_channels != fPlaybackChannels) {
  688. jack_info("JackOSSDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
  689. }
  690. cur_sample_rate = fEngineControl->fSampleRate;
  691. if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  692. jack_error("JackOSSDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  693. goto error;
  694. }
  695. if (cur_sample_rate != fEngineControl->fSampleRate) {
  696. jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  697. }
  698. // Internal buffer size required for one period.
  699. fOutputBufferSize = fEngineControl->fBufferSize * fOutSampleSize * fPlaybackChannels;
  700. // Get the total size of the OSS playback buffer, in sample frames.
  701. info = {0, 0, 0, 0};
  702. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1 || info.fragsize <= 0 || info.fragstotal <= 0) {
  703. jack_error("JackOSSDriver::OpenOutput failed to get buffer info : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  704. goto error;
  705. }
  706. fOSSOutBuffer = info.fragstotal * info.fragsize / (fOutSampleSize * fPlaybackChannels);
  707. if (fOSSOutBuffer < fEngineControl->fBufferSize * (1 + fNperiods)) {
  708. // Total size of the OSS playback buffer is too small, resize it.
  709. unsigned int buf_size = fOutputBufferSize * (1 + fNperiods);
  710. // Keep current fragment size if possible - respect OSS latency settings.
  711. // Some sound cards like Intel HDA may stutter when changing the fragment size.
  712. gFragFormat = UpToPower2(info.fragsize);
  713. unsigned int frag_size = 1U << gFragFormat;
  714. gFragFormat |= ((buf_size + frag_size - 1) / frag_size) << 16;
  715. jack_info("JackOSSDriver::OpenOutput request %d fragments of %d", (gFragFormat >> 16), frag_size);
  716. if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  717. jack_error("JackOSSDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  718. goto error;
  719. }
  720. // Check the new OSS playback buffer size.
  721. info = {0, 0, 0, 0};
  722. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1 || info.fragsize <= 0 || info.fragstotal <= 0) {
  723. jack_error("JackOSSDriver::OpenOutput failed to get buffer info : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  724. goto error;
  725. }
  726. fOSSOutBuffer = info.fragstotal * info.fragsize / (fOutSampleSize * fPlaybackChannels);
  727. }
  728. if (fOSSOutBuffer > fEngineControl->fBufferSize * fNperiods) {
  729. jack_nframes_t low = fOSSOutBuffer - (fNperiods * fEngineControl->fBufferSize);
  730. int mark = low * fOutSampleSize * fPlaybackChannels;
  731. if (ioctl(fOutFD, SNDCTL_DSP_LOW_WATER, &mark) != 0) {
  732. jack_error("JackOSSDriver::OpenOutput failed to set low water mark : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  733. goto error;
  734. }
  735. jack_info("JackOSSDriver::OpenOutput set low water mark to %d", mark);
  736. }
  737. fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
  738. assert(fOutputBuffer);
  739. if (ProbeOutBlockSize() < 0) {
  740. goto error;
  741. }
  742. return 0;
  743. error:
  744. ::close(fOutFD);
  745. return -1;
  746. }
  747. int JackOSSDriver::Open(jack_nframes_t nframes,
  748. int user_nperiods,
  749. jack_nframes_t samplerate,
  750. bool capturing,
  751. bool playing,
  752. int inchannels,
  753. int outchannels,
  754. bool excl,
  755. bool monitor,
  756. const char* capture_driver_uid,
  757. const char* playback_driver_uid,
  758. jack_nframes_t capture_latency,
  759. jack_nframes_t playback_latency,
  760. int bits,
  761. bool ignorehwbuf)
  762. {
  763. // Store local settings first.
  764. fCapture = capturing;
  765. fPlayback = playing;
  766. fBits = bits;
  767. fIgnoreHW = ignorehwbuf;
  768. fNperiods = user_nperiods;
  769. fExcl = excl;
  770. // Generic JackAudioDriver Open
  771. if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
  772. capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
  773. return -1;
  774. } else {
  775. #ifdef JACK_MONITOR
  776. // Force memory page in
  777. memset(&gCycleTable, 0, sizeof(gCycleTable));
  778. #endif
  779. if (OpenAux() < 0) {
  780. Close();
  781. return -1;
  782. } else {
  783. return 0;
  784. }
  785. }
  786. }
  787. int JackOSSDriver::Close()
  788. {
  789. #ifdef JACK_MONITOR
  790. FILE* file = fopen("OSSProfiling.log", "w");
  791. if (file) {
  792. jack_info("Writing OSS driver timing data....");
  793. for (int i = 1; i < gCycleCount; i++) {
  794. int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
  795. int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
  796. int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
  797. int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
  798. fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
  799. }
  800. fclose(file);
  801. } else {
  802. jack_error("JackOSSDriver::Close : cannot open OSSProfiling.log file");
  803. }
  804. file = fopen("TimingOSS.plot", "w");
  805. if (file == NULL) {
  806. jack_error("JackOSSDriver::Close cannot open TimingOSS.plot file");
  807. } else {
  808. fprintf(file, "set grid\n");
  809. fprintf(file, "set title \"OSS audio driver timing\"\n");
  810. fprintf(file, "set xlabel \"audio cycles\"\n");
  811. fprintf(file, "set ylabel \"usec\"\n");
  812. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  813. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  814. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  815. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  816. fprintf(file, "set output 'TimingOSS.pdf\n");
  817. fprintf(file, "set terminal pdf\n");
  818. fprintf(file, "set grid\n");
  819. fprintf(file, "set title \"OSS audio driver timing\"\n");
  820. fprintf(file, "set xlabel \"audio cycles\"\n");
  821. fprintf(file, "set ylabel \"usec\"\n");
  822. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  823. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  824. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  825. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  826. fclose(file);
  827. }
  828. #endif
  829. int res = JackAudioDriver::Close();
  830. CloseAux();
  831. return res;
  832. }
  833. int JackOSSDriver::OpenAux()
  834. {
  835. // (Re-)Initialize runtime variables.
  836. fInSampleSize = fOutSampleSize = 0;
  837. fInputBufferSize = fOutputBufferSize = 0;
  838. fInBlockSize = fOutBlockSize = 1;
  839. fInMeanStep = fOutMeanStep = 0;
  840. fOSSInBuffer = fOSSOutBuffer = 0;
  841. fOSSReadSync = fOSSWriteSync = 0;
  842. fOSSReadOffset = fOSSWriteOffset = 0;
  843. fBufferBalance = 0;
  844. fForceBalancing = false;
  845. fForceSync = false;
  846. if (fCapture && (OpenInput() < 0)) {
  847. return -1;
  848. }
  849. if (fPlayback && (OpenOutput() < 0)) {
  850. return -1;
  851. }
  852. DisplayDeviceInfo();
  853. return 0;
  854. }
  855. void JackOSSDriver::CloseAux()
  856. {
  857. if (fCapture && fInFD > 0) {
  858. close(fInFD);
  859. fInFD = -1;
  860. }
  861. if (fPlayback && fOutFD > 0) {
  862. close(fOutFD);
  863. fOutFD = -1;
  864. }
  865. if (fInputBuffer)
  866. free(fInputBuffer);
  867. fInputBuffer = NULL;
  868. if (fOutputBuffer)
  869. free(fOutputBuffer);
  870. fOutputBuffer = NULL;
  871. }
  872. int JackOSSDriver::Read()
  873. {
  874. if (fInFD > 0 && fOSSReadSync == 0) {
  875. // First cycle, account for leftover samples from previous reads.
  876. fOSSReadOffset = 0;
  877. oss_count_t ptr;
  878. if (ioctl(fInFD, SNDCTL_DSP_CURRENT_IPTR, &ptr) == 0 && ptr.fifo_samples > 0) {
  879. jack_log("JackOSSDriver::Read pre recording samples = %ld, fifo_samples = %d", ptr.samples, ptr.fifo_samples);
  880. fOSSReadOffset = -ptr.fifo_samples;
  881. }
  882. // Start capture by reading a new hardware block.,
  883. jack_nframes_t discard = fInMeanStep - fOSSReadOffset;
  884. // Let half a block or at most 1ms remain in buffer, avoid drift issues at start.
  885. discard -= min(TimeToFrames(1000, fEngineControl->fSampleRate), (fInMeanStep / 2));
  886. jack_log("JackOSSDriver::Read start recording discard %ld frames", discard);
  887. fOSSReadSync = GetMicroSeconds();
  888. Discard(discard);
  889. fForceSync = true;
  890. fForceBalancing = true;
  891. }
  892. if (fOutFD > 0 && fOSSWriteSync == 0) {
  893. // First cycle, account for leftover samples from previous writes.
  894. fOSSWriteOffset = 0;
  895. oss_count_t ptr;
  896. if (ioctl(fOutFD, SNDCTL_DSP_CURRENT_OPTR, &ptr) == 0 && ptr.fifo_samples > 0) {
  897. jack_log("JackOSSDriver::Read pre playback samples = %ld, fifo_samples = %d", ptr.samples, ptr.fifo_samples);
  898. fOSSWriteOffset = ptr.fifo_samples;
  899. }
  900. // Start playback with silence, target latency as given by the user.
  901. jack_nframes_t silence = (fNperiods + 1) * fEngineControl->fBufferSize;
  902. // Minus half a block or at most 1ms of frames, avoid drift issues at start.
  903. silence -= min(TimeToFrames(1000, fEngineControl->fSampleRate), (fOutMeanStep / 2));
  904. silence = max(silence - fOSSWriteOffset, 1LL);
  905. jack_log("JackOSSDriver::Read start playback with %ld frames of silence", silence);
  906. fOSSWriteSync = GetMicroSeconds();
  907. WriteSilence(silence);
  908. fForceSync = true;
  909. fForceBalancing = true;
  910. }
  911. #ifdef JACK_MONITOR
  912. gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds();
  913. #endif
  914. if (WaitAndSync() < 0) {
  915. return -1;
  916. }
  917. // Keep begin cycle time
  918. JackDriver::CycleTakeBeginTime();
  919. if (fInFD < 0) {
  920. return 0;
  921. }
  922. // Try to read multiple times in case of short reads.
  923. size_t count = 0;
  924. for (int i = 0; i < 3 && count < fInputBufferSize; ++i) {
  925. ssize_t ret = ::read(fInFD, ((char*)fInputBuffer) + count, fInputBufferSize - count);
  926. if (ret < 0) {
  927. jack_error("JackOSSDriver::Read error = %s", strerror(errno));
  928. return -1;
  929. }
  930. count += ret;
  931. }
  932. // Read offset accounting and overrun detection.
  933. if (count > 0) {
  934. jack_time_t now = GetMicroSeconds();
  935. jack_time_t sync = max(fOSSReadSync, fOSSWriteSync);
  936. if (now - sync > 1000) {
  937. // Blocking read() may indicate sample loss in OSS - force resync.
  938. jack_log("JackOSSDriver::Read long read duration of %ld us", now - sync);
  939. fForceSync = true;
  940. }
  941. long long passed = TimeToFrames(now - fOSSReadSync, fEngineControl->fSampleRate);
  942. passed -= (passed % fInBlockSize);
  943. if (passed > fOSSReadOffset + fOSSInBuffer) {
  944. // Overrun, adjust read and write position.
  945. long long missed = passed - (fOSSReadOffset + fOSSInBuffer);
  946. jack_error("JackOSSDriver::Read missed %ld frames by overrun, passed=%ld, sync=%ld, now=%ld", missed, passed, fOSSReadSync, now);
  947. fOSSReadOffset += missed;
  948. fOSSWriteOffset += missed;
  949. NotifyXRun(now, float(FramesToTime(missed, fEngineControl->fSampleRate)));
  950. }
  951. fOSSReadOffset += count / (fInSampleSize * fCaptureChannels);
  952. }
  953. #ifdef JACK_MONITOR
  954. if (count > 0 && count != (int)fInputBufferSize)
  955. jack_log("JackOSSDriver::Read count = %ld", count / (fInSampleSize * fCaptureChannels));
  956. gCycleTable.fTable[gCycleCount].fAfterRead = GetMicroSeconds();
  957. #endif
  958. // Check and clear OSS errors.
  959. audio_errinfo ei_in;
  960. if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
  961. // Not reliable for overrun detection, virtual_oss doesn't implement it.
  962. if (ei_in.rec_overruns > 0 ) {
  963. jack_error("JackOSSDriver::Read %d overrun events", ei_in.rec_overruns);
  964. }
  965. if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
  966. jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
  967. }
  968. }
  969. if (count < fInputBufferSize) {
  970. jack_error("JackOSSDriver::Read incomplete read of %ld bytes", count);
  971. return -1;
  972. }
  973. for (int i = 0; i < fCaptureChannels; i++) {
  974. if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
  975. CopyAndConvertIn(GetInputBuffer(i), fInputBuffer, fEngineControl->fBufferSize, i, fCaptureChannels, fInSampleSize * 8);
  976. }
  977. }
  978. #ifdef JACK_MONITOR
  979. gCycleTable.fTable[gCycleCount].fAfterReadConvert = GetMicroSeconds();
  980. #endif
  981. return 0;
  982. }
  983. int JackOSSDriver::Write()
  984. {
  985. if (fOutFD < 0) {
  986. return 0;
  987. }
  988. unsigned int skip = 0;
  989. jack_time_t start = GetMicroSeconds();
  990. if (fOSSWriteSync > 0) {
  991. // Check for underruns, rounded to hardware block size if available.
  992. long long passed = TimeToFrames(start - fOSSWriteSync, fEngineControl->fSampleRate);
  993. long long consumed = passed - (passed % fOutBlockSize);
  994. long long tolerance = (fOutBlockSize > 1) ? 0 : fOutMeanStep;
  995. long long overdue = 0;
  996. if (consumed > fOSSWriteOffset + tolerance) {
  997. // Skip playback data that already passed.
  998. overdue = consumed - fOSSWriteOffset - tolerance;
  999. jack_error("JackOSSDriver::Write underrun, late by %ld, skip %ld frames", passed - fOSSWriteOffset, overdue);
  1000. jack_log("JackOSSDriver::Write playback offset %ld frames synced %ld us ago", fOSSWriteOffset, start - fOSSWriteSync);
  1001. // Also consider buffer balance, there was a gap in playback anyway.
  1002. fForceBalancing = true;
  1003. }
  1004. // Account for buffer balance if needed.
  1005. long long progress = fEngineControl->fBufferSize;
  1006. if (fForceBalancing) {
  1007. fForceBalancing = false;
  1008. progress = max(progress + fBufferBalance, 0LL);
  1009. jack_info("JackOSSDriver::Write buffer balancing %ld frames", fBufferBalance);
  1010. jack_log("JackOSSDriver::Write recording sync %ld frames %ld us ago", fOSSReadOffset, start - fOSSReadSync);
  1011. jack_log("JackOSSDriver::Write playback sync %ld frames %ld us ago", fOSSWriteOffset, start - fOSSWriteSync);
  1012. }
  1013. // How many samples to skip or prepend due to underrun and balancing.
  1014. long long write_length = progress - overdue;
  1015. if (write_length <= 0) {
  1016. skip += fOutputBufferSize;
  1017. fOSSWriteOffset += progress;
  1018. } else if (write_length < fEngineControl->fBufferSize) {
  1019. skip += (fEngineControl->fBufferSize - write_length) * fOutSampleSize * fPlaybackChannels;
  1020. fOSSWriteOffset += overdue;
  1021. } else if (write_length > fEngineControl->fBufferSize) {
  1022. jack_nframes_t fill = write_length - fEngineControl->fBufferSize;
  1023. WriteSilence(fill);
  1024. }
  1025. }
  1026. #ifdef JACK_MONITOR
  1027. gCycleTable.fTable[gCycleCount].fBeforeWriteConvert = GetMicroSeconds();
  1028. #endif
  1029. memset(fOutputBuffer, 0, fOutputBufferSize);
  1030. for (int i = 0; i < fPlaybackChannels; i++) {
  1031. if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
  1032. CopyAndConvertOut(fOutputBuffer, GetOutputBuffer(i), fEngineControl->fBufferSize, i, fPlaybackChannels, fOutSampleSize * 8);
  1033. }
  1034. }
  1035. #ifdef JACK_MONITOR
  1036. gCycleTable.fTable[gCycleCount].fBeforeWrite = GetMicroSeconds();
  1037. #endif
  1038. // Try multiple times in case of short writes.
  1039. ssize_t count = skip;
  1040. for (int i = 0; i < 3 && count < fOutputBufferSize; ++i) {
  1041. ssize_t ret = ::write(fOutFD, ((char*)fOutputBuffer) + count, fOutputBufferSize - count);
  1042. if (ret < 0) {
  1043. jack_error("JackOSSDriver::Write error = %s", strerror(errno));
  1044. return -1;
  1045. }
  1046. count += ret;
  1047. }
  1048. fOSSWriteOffset += ((count - skip) / (fOutSampleSize * fPlaybackChannels));
  1049. jack_time_t duration = GetMicroSeconds() - start;
  1050. if (duration > 1000) {
  1051. // Blocking write() may indicate sample loss in OSS - force resync.
  1052. jack_log("JackOSSDriver::Write long write duration of %ld us", duration);
  1053. fForceSync = true;
  1054. }
  1055. #ifdef JACK_MONITOR
  1056. if (count > 0 && count != (int)fOutputBufferSize)
  1057. jack_log("JackOSSDriver::Write count = %ld", (count - skip) / (fOutSampleSize * fPlaybackChannels));
  1058. gCycleTable.fTable[gCycleCount].fAfterWrite = GetMicroSeconds();
  1059. gCycleCount = (gCycleCount == CYCLE_POINTS - 1) ? gCycleCount: gCycleCount + 1;
  1060. #endif
  1061. // Check and clear OSS errors.
  1062. audio_errinfo ei_out;
  1063. if (ioctl(fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) {
  1064. // Not reliable for underrun detection, virtual_oss does not implement it.
  1065. if (ei_out.play_underruns > 0) {
  1066. jack_error("JackOSSDriver::Write %d underrun events", ei_out.play_underruns);
  1067. }
  1068. if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
  1069. jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
  1070. }
  1071. }
  1072. if (count < (int)fOutputBufferSize) {
  1073. jack_error("JackOSSDriver::Write incomplete write of %ld bytes", count - skip);
  1074. return -1;
  1075. }
  1076. return 0;
  1077. }
  1078. void JackOSSDriver::UpdateLatencies()
  1079. {
  1080. // Reimplement from JackAudioDriver. Base latency is smaller, and there's
  1081. // additional latency due to OSS playback buffer management.
  1082. jack_latency_range_t input_range;
  1083. jack_latency_range_t output_range;
  1084. for (int i = 0; i < fCaptureChannels; i++) {
  1085. input_range.max = input_range.min = (fEngineControl->fBufferSize / 2) + fCaptureLatency;
  1086. fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
  1087. }
  1088. for (int i = 0; i < fPlaybackChannels; i++) {
  1089. output_range.max = (fEngineControl->fBufferSize / 2) + fPlaybackLatency;
  1090. // Additional latency introduced by the OSS buffer.
  1091. output_range.max += fNperiods * fEngineControl->fBufferSize;
  1092. // Plus one period if in async mode.
  1093. if (!fEngineControl->fSyncMode) {
  1094. output_range.max += fEngineControl->fBufferSize;
  1095. }
  1096. output_range.min = output_range.max;
  1097. fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
  1098. }
  1099. }
  1100. int JackOSSDriver::SetBufferSize(jack_nframes_t buffer_size)
  1101. {
  1102. // Close and reopen device, we have to adjust the OSS buffer management.
  1103. CloseAux();
  1104. JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
  1105. return OpenAux();
  1106. }
  1107. } // end of namespace
  1108. #ifdef __cplusplus
  1109. extern "C"
  1110. {
  1111. #endif
  1112. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
  1113. {
  1114. jack_driver_desc_t * desc;
  1115. jack_driver_desc_filler_t filler;
  1116. jack_driver_param_value_t value;
  1117. desc = jack_driver_descriptor_construct("oss", JackDriverMaster, "OSS API based audio backend", &filler);
  1118. value.ui = OSS_DRIVER_DEF_FS;
  1119. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  1120. value.ui = OSS_DRIVER_DEF_BLKSIZE;
  1121. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  1122. value.ui = OSS_DRIVER_DEF_NPERIODS;
  1123. jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
  1124. value.i = OSS_DRIVER_DEF_BITS;
  1125. jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
  1126. value.ui = OSS_DRIVER_DEF_INS;
  1127. jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
  1128. value.ui = OSS_DRIVER_DEF_OUTS;
  1129. jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
  1130. value.i = false;
  1131. jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusive and direct device access", NULL);
  1132. strcpy(value.str, OSS_DRIVER_DEF_DEV);
  1133. jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
  1134. jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
  1135. jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
  1136. value.i = false;
  1137. jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
  1138. value.ui = 0;
  1139. jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
  1140. jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
  1141. return desc;
  1142. }
  1143. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  1144. {
  1145. int bits = OSS_DRIVER_DEF_BITS;
  1146. jack_nframes_t srate = OSS_DRIVER_DEF_FS;
  1147. jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE;
  1148. const char* capture_pcm_name = OSS_DRIVER_DEF_DEV;
  1149. const char* playback_pcm_name = OSS_DRIVER_DEF_DEV;
  1150. bool capture = false;
  1151. bool playback = false;
  1152. int chan_in = 0;
  1153. int chan_out = 0;
  1154. bool monitor = false;
  1155. bool excl = false;
  1156. unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
  1157. const JSList *node;
  1158. const jack_driver_param_t *param;
  1159. bool ignorehwbuf = false;
  1160. jack_nframes_t systemic_input_latency = 0;
  1161. jack_nframes_t systemic_output_latency = 0;
  1162. for (node = params; node; node = jack_slist_next(node)) {
  1163. param = (const jack_driver_param_t *)node->data;
  1164. switch (param->character) {
  1165. case 'r':
  1166. srate = param->value.ui;
  1167. break;
  1168. case 'p':
  1169. frames_per_interrupt = (unsigned int)param->value.ui;
  1170. break;
  1171. case 'n':
  1172. nperiods = (unsigned int)param->value.ui;
  1173. break;
  1174. case 'w':
  1175. bits = param->value.i;
  1176. break;
  1177. case 'i':
  1178. chan_in = (int)param->value.ui;
  1179. break;
  1180. case 'o':
  1181. chan_out = (int)param->value.ui;
  1182. break;
  1183. case 'C':
  1184. capture = true;
  1185. if (strcmp(param->value.str, "none") != 0) {
  1186. capture_pcm_name = param->value.str;
  1187. }
  1188. break;
  1189. case 'P':
  1190. playback = true;
  1191. if (strcmp(param->value.str, "none") != 0) {
  1192. playback_pcm_name = param->value.str;
  1193. }
  1194. break;
  1195. case 'd':
  1196. playback_pcm_name = param->value.str;
  1197. capture_pcm_name = param->value.str;
  1198. break;
  1199. case 'b':
  1200. ignorehwbuf = true;
  1201. break;
  1202. case 'e':
  1203. excl = true;
  1204. break;
  1205. case 'I':
  1206. systemic_input_latency = param->value.ui;
  1207. break;
  1208. case 'O':
  1209. systemic_output_latency = param->value.ui;
  1210. break;
  1211. }
  1212. }
  1213. // duplex is the default
  1214. if (!capture && !playback) {
  1215. capture = true;
  1216. playback = true;
  1217. }
  1218. Jack::JackOSSDriver* oss_driver = new Jack::JackOSSDriver("system", "oss", engine, table);
  1219. Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(oss_driver);
  1220. // Special open for OSS driver...
  1221. if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
  1222. excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) {
  1223. return threaded_driver;
  1224. } else {
  1225. delete threaded_driver; // Delete the decorated driver
  1226. return NULL;
  1227. }
  1228. }
  1229. #ifdef __cplusplus
  1230. }
  1231. #endif