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.

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