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.

883 lines
30KB

  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 Jack
  34. {
  35. #ifdef JACK_MONITOR
  36. #define CYCLE_POINTS 500000
  37. struct OSSCycle {
  38. jack_time_t fBeforeRead;
  39. jack_time_t fAfterRead;
  40. jack_time_t fAfterReadConvert;
  41. jack_time_t fBeforeWrite;
  42. jack_time_t fAfterWrite;
  43. jack_time_t fBeforeWriteConvert;
  44. };
  45. struct OSSCycleTable {
  46. jack_time_t fBeforeFirstWrite;
  47. jack_time_t fAfterFirstWrite;
  48. OSSCycle fTable[CYCLE_POINTS];
  49. };
  50. OSSCycleTable gCycleTable;
  51. int gCycleCount = 0;
  52. #endif
  53. inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; }
  54. static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
  55. {
  56. switch (bits) {
  57. case 16: {
  58. signed short *s16src = (signed short*)src;
  59. s16src += channel;
  60. sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
  61. break;
  62. }
  63. case 24: {
  64. signed int *s32src = (signed int*)src;
  65. s32src += channel;
  66. sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
  67. break;
  68. }
  69. case 32: {
  70. signed int *s32src = (signed int*)src;
  71. s32src += channel;
  72. sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
  73. break;
  74. }
  75. }
  76. }
  77. static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
  78. {
  79. switch (bits) {
  80. case 16: {
  81. signed short *s16dst = (signed short*)dst;
  82. s16dst += channel;
  83. sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now...
  84. break;
  85. }
  86. case 24: {
  87. signed int *s32dst = (signed int*)dst;
  88. s32dst += channel;
  89. sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
  90. break;
  91. }
  92. case 32: {
  93. signed int *s32dst = (signed int*)dst;
  94. s32dst += channel;
  95. sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
  96. break;
  97. }
  98. }
  99. }
  100. void JackOSSDriver::SetSampleFormat()
  101. {
  102. switch (fBits) {
  103. case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */
  104. fSampleFormat = AFMT_S24_NE;
  105. fSampleSize = sizeof(int);
  106. break;
  107. case 32: /* native-endian 32-bit integer */
  108. fSampleFormat = AFMT_S32_NE;
  109. fSampleSize = sizeof(int);
  110. break;
  111. case 16: /* native-endian 16-bit integer */
  112. default:
  113. fSampleFormat = AFMT_S16_NE;
  114. fSampleSize = sizeof(short);
  115. break;
  116. }
  117. }
  118. void JackOSSDriver::DisplayDeviceInfo()
  119. {
  120. audio_buf_info info;
  121. memset(&info, 0, sizeof(audio_buf_info));
  122. int cap = 0;
  123. // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
  124. jack_info("Audio Interface Description :");
  125. jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
  126. if (fRWMode & kWrite) {
  127. oss_sysinfo si;
  128. if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
  129. jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  130. } else {
  131. jack_info("OSS product %s", si.product);
  132. jack_info("OSS version %s", si.version);
  133. jack_info("OSS version num %d", si.versionnum);
  134. jack_info("OSS numaudios %d", si.numaudios);
  135. jack_info("OSS numaudioengines %d", si.numaudioengines);
  136. jack_info("OSS numcards %d", si.numcards);
  137. }
  138. jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
  139. jack_info("Output block size = %d", fOutputBufferSize);
  140. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  141. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  142. } else {
  143. jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  144. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  145. }
  146. if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  147. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  148. } else {
  149. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  150. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  151. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  152. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  153. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  154. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  155. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  156. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  157. }
  158. }
  159. if (fRWMode & kRead) {
  160. oss_sysinfo si;
  161. if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
  162. jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  163. } else {
  164. jack_info("OSS product %s", si.product);
  165. jack_info("OSS version %s", si.version);
  166. jack_info("OSS version num %d", si.versionnum);
  167. jack_info("OSS numaudios %d", si.numaudios);
  168. jack_info("OSS numaudioengines %d", si.numaudioengines);
  169. jack_info("OSS numcards %d", si.numcards);
  170. }
  171. jack_info("Input capabilities - %d channels : ", fCaptureChannels);
  172. jack_info("Input block size = %d", fInputBufferSize);
  173. if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
  174. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  175. } else {
  176. jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  177. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  178. }
  179. if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  180. jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  181. } else {
  182. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  183. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  184. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  185. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  186. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  187. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  188. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  189. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  190. }
  191. }
  192. }
  193. int JackOSSDriver::OpenInput()
  194. {
  195. int flags = 0;
  196. int gFragFormat;
  197. int cur_capture_channels;
  198. int cur_sample_format;
  199. jack_nframes_t cur_sample_rate;
  200. if (fCaptureChannels == 0) fCaptureChannels = 2;
  201. if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  202. jack_error("JackOSSDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  203. return -1;
  204. }
  205. jack_log("JackOSSDriver::OpenInput input fInFD = %d", fInFD);
  206. if (fExcl) {
  207. if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  208. jack_error("JackOSSDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  209. goto error;
  210. }
  211. }
  212. gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
  213. if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  214. jack_error("JackOSSDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  215. goto error;
  216. }
  217. cur_sample_format = fSampleFormat;
  218. if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  219. jack_error("JackOSSDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  220. goto error;
  221. }
  222. if (cur_sample_format != fSampleFormat) {
  223. jack_info("JackOSSDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
  224. }
  225. cur_capture_channels = fCaptureChannels;
  226. if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
  227. jack_error("JackOSSDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  228. goto error;
  229. }
  230. if (cur_capture_channels != fCaptureChannels) {
  231. jack_info("JackOSSDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
  232. }
  233. cur_sample_rate = fEngineControl->fSampleRate;
  234. if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  235. jack_error("JackOSSDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  236. goto error;
  237. }
  238. if (cur_sample_rate != fEngineControl->fSampleRate) {
  239. jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  240. }
  241. fInputBufferSize = 0;
  242. if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
  243. jack_error("JackOSSDriver::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  244. goto error;
  245. }
  246. if (fInputBufferSize != fEngineControl->fBufferSize * fSampleSize * fCaptureChannels) {
  247. if (fIgnoreHW) {
  248. int new_buffer_size = fInputBufferSize / (fSampleSize * fCaptureChannels);
  249. jack_info("JackOSSDriver::OpenInput driver forced buffer size %ld", new_buffer_size);
  250. JackAudioDriver::SetBufferSize(new_buffer_size); // never fails
  251. } else {
  252. jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained");
  253. goto error;
  254. }
  255. }
  256. fInputBuffer = (void*)calloc(fInputBufferSize, 1);
  257. assert(fInputBuffer);
  258. return 0;
  259. error:
  260. ::close(fInFD);
  261. return -1;
  262. }
  263. int JackOSSDriver::OpenOutput()
  264. {
  265. int flags = 0;
  266. int gFragFormat;
  267. int cur_sample_format;
  268. int cur_playback_channels;
  269. jack_nframes_t cur_sample_rate;
  270. if (fPlaybackChannels == 0) fPlaybackChannels = 2;
  271. if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  272. jack_error("JackOSSDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  273. return -1;
  274. }
  275. jack_log("JackOSSDriver::OpenOutput output fOutFD = %d", fOutFD);
  276. if (fExcl) {
  277. if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  278. jack_error("JackOSSDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  279. goto error;
  280. }
  281. }
  282. gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
  283. if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  284. jack_error("JackOSSDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  285. goto error;
  286. }
  287. cur_sample_format = fSampleFormat;
  288. if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  289. jack_error("JackOSSDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  290. goto error;
  291. }
  292. if (cur_sample_format != fSampleFormat) {
  293. jack_info("JackOSSDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
  294. }
  295. cur_playback_channels = fPlaybackChannels;
  296. if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
  297. jack_error("JackOSSDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  298. goto error;
  299. }
  300. if (cur_playback_channels != fPlaybackChannels) {
  301. jack_info("JackOSSDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
  302. }
  303. cur_sample_rate = fEngineControl->fSampleRate;
  304. if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  305. jack_error("JackOSSDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  306. goto error;
  307. }
  308. if (cur_sample_rate != fEngineControl->fSampleRate) {
  309. jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  310. }
  311. fOutputBufferSize = 0;
  312. if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
  313. jack_error("JackOSSDriver::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  314. goto error;
  315. }
  316. if (fOutputBufferSize != fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels) {
  317. if (fIgnoreHW) {
  318. int new_buffer_size = fOutputBufferSize / (fSampleSize * fPlaybackChannels);
  319. jack_info("JackOSSDriver::OpenOutput driver forced buffer size %ld", new_buffer_size);
  320. JackAudioDriver::SetBufferSize(new_buffer_size); // never fails
  321. } else {
  322. jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained");
  323. goto error;
  324. }
  325. }
  326. fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
  327. fFirstCycle = true;
  328. assert(fOutputBuffer);
  329. return 0;
  330. error:
  331. ::close(fOutFD);
  332. return -1;
  333. }
  334. int JackOSSDriver::Open(jack_nframes_t nframes,
  335. int user_nperiods,
  336. jack_nframes_t samplerate,
  337. bool capturing,
  338. bool playing,
  339. int inchannels,
  340. int outchannels,
  341. bool excl,
  342. bool monitor,
  343. const char* capture_driver_uid,
  344. const char* playback_driver_uid,
  345. jack_nframes_t capture_latency,
  346. jack_nframes_t playback_latency,
  347. int bits,
  348. bool ignorehwbuf)
  349. {
  350. // Generic JackAudioDriver Open
  351. if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
  352. capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
  353. return -1;
  354. } else {
  355. if (!fEngineControl->fSyncMode) {
  356. jack_error("Cannot run in asynchronous mode, use the -S parameter for jackd");
  357. return -1;
  358. }
  359. fRWMode |= ((capturing) ? kRead : 0);
  360. fRWMode |= ((playing) ? kWrite : 0);
  361. fBits = bits;
  362. fIgnoreHW = ignorehwbuf;
  363. fNperiods = user_nperiods;
  364. fExcl = excl;
  365. #ifdef JACK_MONITOR
  366. // Force memory page in
  367. memset(&gCycleTable, 0, sizeof(gCycleTable));
  368. #endif
  369. if (OpenAux() < 0) {
  370. Close();
  371. return -1;
  372. } else {
  373. return 0;
  374. }
  375. }
  376. }
  377. int JackOSSDriver::Close()
  378. {
  379. #ifdef JACK_MONITOR
  380. FILE* file = fopen("OSSProfiling.log", "w");
  381. if (file) {
  382. jack_info("Writing OSS driver timing data....");
  383. for (int i = 1; i < gCycleCount; i++) {
  384. int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
  385. int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
  386. int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
  387. int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
  388. fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
  389. }
  390. fclose(file);
  391. } else {
  392. jack_error("JackOSSDriver::Close : cannot open OSSProfiling.log file");
  393. }
  394. file = fopen("TimingOSS.plot", "w");
  395. if (file == NULL) {
  396. jack_error("JackOSSDriver::Close cannot open TimingOSS.plot file");
  397. } else {
  398. fprintf(file, "set grid\n");
  399. fprintf(file, "set title \"OSS audio driver timing\"\n");
  400. fprintf(file, "set xlabel \"audio cycles\"\n");
  401. fprintf(file, "set ylabel \"usec\"\n");
  402. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  403. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  404. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  405. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  406. fprintf(file, "set output 'TimingOSS.pdf\n");
  407. fprintf(file, "set terminal pdf\n");
  408. fprintf(file, "set grid\n");
  409. fprintf(file, "set title \"OSS audio driver timing\"\n");
  410. fprintf(file, "set xlabel \"audio cycles\"\n");
  411. fprintf(file, "set ylabel \"usec\"\n");
  412. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  413. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  414. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  415. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  416. fclose(file);
  417. }
  418. #endif
  419. int res = JackAudioDriver::Close();
  420. CloseAux();
  421. return res;
  422. }
  423. int JackOSSDriver::OpenAux()
  424. {
  425. SetSampleFormat();
  426. if ((fRWMode & kRead) && (OpenInput() < 0)) {
  427. return -1;
  428. }
  429. if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
  430. return -1;
  431. }
  432. // In duplex mode, check that input and output use the same buffer size
  433. /*
  434. 10/02/09 : deactivated for now, needs more check (only needed when *same* device is used for input and output ??)
  435. if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
  436. jack_error("JackOSSDriver::OpenAux input and output buffer size are not the same!!");
  437. return -1;
  438. }
  439. */
  440. DisplayDeviceInfo();
  441. return 0;
  442. }
  443. void JackOSSDriver::CloseAux()
  444. {
  445. if (fRWMode & kRead && fInFD > 0) {
  446. close(fInFD);
  447. fInFD = -1;
  448. }
  449. if (fRWMode & kWrite && fOutFD > 0) {
  450. close(fOutFD);
  451. fOutFD = -1;
  452. }
  453. if (fInputBuffer)
  454. free(fInputBuffer);
  455. fInputBuffer = NULL;
  456. if (fOutputBuffer)
  457. free(fOutputBuffer);
  458. fOutputBuffer = NULL;
  459. }
  460. int JackOSSDriver::Read()
  461. {
  462. if (fInFD < 0) {
  463. // Keep begin cycle time
  464. JackDriver::CycleTakeBeginTime();
  465. return 0;
  466. }
  467. ssize_t count;
  468. #ifdef JACK_MONITOR
  469. gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds();
  470. #endif
  471. audio_errinfo ei_in;
  472. count = ::read(fInFD, fInputBuffer, fInputBufferSize);
  473. #ifdef JACK_MONITOR
  474. if (count > 0 && count != (int)fInputBufferSize)
  475. jack_log("JackOSSDriver::Read count = %ld", count / (fSampleSize * fCaptureChannels));
  476. gCycleTable.fTable[gCycleCount].fAfterRead = GetMicroSeconds();
  477. #endif
  478. // XRun detection
  479. if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
  480. if (ei_in.rec_overruns > 0 ) {
  481. jack_error("JackOSSDriver::Read overruns");
  482. jack_time_t cur_time = GetMicroSeconds();
  483. NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
  484. }
  485. if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
  486. jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
  487. }
  488. }
  489. if (count < 0) {
  490. jack_log("JackOSSDriver::Read error = %s", strerror(errno));
  491. return -1;
  492. } else if (count < (int)fInputBufferSize) {
  493. jack_error("JackOSSDriver::Read error bytes read = %ld", count);
  494. return -1;
  495. } else {
  496. // Keep begin cycle time
  497. JackDriver::CycleTakeBeginTime();
  498. for (int i = 0; i < fCaptureChannels; i++) {
  499. if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
  500. CopyAndConvertIn(GetInputBuffer(i), fInputBuffer, fEngineControl->fBufferSize, i, fCaptureChannels, fBits);
  501. }
  502. }
  503. #ifdef JACK_MONITOR
  504. gCycleTable.fTable[gCycleCount].fAfterReadConvert = GetMicroSeconds();
  505. #endif
  506. return 0;
  507. }
  508. }
  509. int JackOSSDriver::Write()
  510. {
  511. if (fOutFD < 0) {
  512. // Keep end cycle time
  513. JackDriver::CycleTakeEndTime();
  514. return 0;
  515. }
  516. ssize_t count;
  517. audio_errinfo ei_out;
  518. // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
  519. if (fFirstCycle) {
  520. fFirstCycle = false;
  521. memset(fOutputBuffer, 0, fOutputBufferSize);
  522. // Prefill output buffer
  523. for (int i = 0; i < fNperiods; i++) {
  524. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  525. if (count < (int)fOutputBufferSize) {
  526. jack_error("JackOSSDriver::Write error bytes written = %ld", count);
  527. return -1;
  528. }
  529. }
  530. int delay;
  531. if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
  532. jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  533. return -1;
  534. }
  535. delay /= fSampleSize * fPlaybackChannels;
  536. jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
  537. }
  538. #ifdef JACK_MONITOR
  539. gCycleTable.fTable[gCycleCount].fBeforeWriteConvert = GetMicroSeconds();
  540. #endif
  541. memset(fOutputBuffer, 0, fOutputBufferSize);
  542. for (int i = 0; i < fPlaybackChannels; i++) {
  543. if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
  544. CopyAndConvertOut(fOutputBuffer, GetOutputBuffer(i), fEngineControl->fBufferSize, i, fPlaybackChannels, fBits);
  545. }
  546. }
  547. #ifdef JACK_MONITOR
  548. gCycleTable.fTable[gCycleCount].fBeforeWrite = GetMicroSeconds();
  549. #endif
  550. // Keep end cycle time
  551. JackDriver::CycleTakeEndTime();
  552. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  553. #ifdef JACK_MONITOR
  554. if (count > 0 && count != (int)fOutputBufferSize)
  555. jack_log("JackOSSDriver::Write count = %ld", count / (fSampleSize * fPlaybackChannels));
  556. gCycleTable.fTable[gCycleCount].fAfterWrite = GetMicroSeconds();
  557. gCycleCount = (gCycleCount == CYCLE_POINTS - 1) ? gCycleCount: gCycleCount + 1;
  558. #endif
  559. // XRun detection
  560. if (ioctl(fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) {
  561. if (ei_out.play_underruns > 0) {
  562. jack_error("JackOSSDriver::Write underruns");
  563. jack_time_t cur_time = GetMicroSeconds();
  564. NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
  565. }
  566. if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
  567. jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
  568. }
  569. }
  570. if (count < 0) {
  571. jack_log("JackOSSDriver::Write error = %s", strerror(errno));
  572. return -1;
  573. } else if (count < (int)fOutputBufferSize) {
  574. jack_error("JackOSSDriver::Write error bytes written = %ld", count);
  575. return -1;
  576. } else {
  577. return 0;
  578. }
  579. }
  580. int JackOSSDriver::SetBufferSize(jack_nframes_t buffer_size)
  581. {
  582. CloseAux();
  583. JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
  584. return OpenAux();
  585. }
  586. int JackOSSDriver::ProcessSync()
  587. {
  588. // Read input buffers for the current cycle
  589. if (Read() < 0) {
  590. jack_error("ProcessSync: read error, skip cycle");
  591. return 0; // Non fatal error here, skip cycle, but continue processing...
  592. }
  593. if (fIsMaster) {
  594. ProcessGraphSync();
  595. } else {
  596. ResumeRefNum();
  597. }
  598. // Write output buffers for the current cycle
  599. if (Write() < 0) {
  600. jack_error("JackAudioDriver::ProcessSync: write error, skip cycle");
  601. return 0; // Non fatal error here, skip cycle, but continue processing...
  602. }
  603. return 0;
  604. }
  605. } // end of namespace
  606. #ifdef __cplusplus
  607. extern "C"
  608. {
  609. #endif
  610. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
  611. {
  612. jack_driver_desc_t * desc;
  613. jack_driver_desc_filler_t filler;
  614. jack_driver_param_value_t value;
  615. desc = jack_driver_descriptor_construct("oss", JackDriverMaster, "OSS API based audio backend", &filler);
  616. value.ui = OSS_DRIVER_DEF_FS;
  617. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  618. value.ui = OSS_DRIVER_DEF_BLKSIZE;
  619. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  620. value.ui = OSS_DRIVER_DEF_NPERIODS;
  621. jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
  622. value.i = OSS_DRIVER_DEF_BITS;
  623. jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
  624. value.ui = OSS_DRIVER_DEF_INS;
  625. jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
  626. value.ui = OSS_DRIVER_DEF_OUTS;
  627. jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
  628. value.i = false;
  629. jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusive and direct device access", NULL);
  630. strcpy(value.str, OSS_DRIVER_DEF_DEV);
  631. jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
  632. jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
  633. jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
  634. value.i = false;
  635. jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
  636. value.ui = 0;
  637. jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
  638. jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
  639. return desc;
  640. }
  641. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  642. {
  643. int bits = OSS_DRIVER_DEF_BITS;
  644. jack_nframes_t srate = OSS_DRIVER_DEF_FS;
  645. jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE;
  646. const char* capture_pcm_name = OSS_DRIVER_DEF_DEV;
  647. const char* playback_pcm_name = OSS_DRIVER_DEF_DEV;
  648. bool capture = false;
  649. bool playback = false;
  650. int chan_in = 0;
  651. int chan_out = 0;
  652. bool monitor = false;
  653. bool excl = false;
  654. unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
  655. const JSList *node;
  656. const jack_driver_param_t *param;
  657. bool ignorehwbuf = false;
  658. jack_nframes_t systemic_input_latency = 0;
  659. jack_nframes_t systemic_output_latency = 0;
  660. for (node = params; node; node = jack_slist_next(node)) {
  661. param = (const jack_driver_param_t *)node->data;
  662. switch (param->character) {
  663. case 'r':
  664. srate = param->value.ui;
  665. break;
  666. case 'p':
  667. frames_per_interrupt = (unsigned int)param->value.ui;
  668. break;
  669. case 'n':
  670. nperiods = (unsigned int)param->value.ui;
  671. break;
  672. case 'w':
  673. bits = param->value.i;
  674. break;
  675. case 'i':
  676. chan_in = (int)param->value.ui;
  677. break;
  678. case 'o':
  679. chan_out = (int)param->value.ui;
  680. break;
  681. case 'C':
  682. capture = true;
  683. if (strcmp(param->value.str, "none") != 0) {
  684. capture_pcm_name = param->value.str;
  685. }
  686. break;
  687. case 'P':
  688. playback = true;
  689. if (strcmp(param->value.str, "none") != 0) {
  690. playback_pcm_name = param->value.str;
  691. }
  692. break;
  693. case 'd':
  694. playback_pcm_name = param->value.str;
  695. capture_pcm_name = param->value.str;
  696. break;
  697. case 'b':
  698. ignorehwbuf = true;
  699. break;
  700. case 'e':
  701. excl = true;
  702. break;
  703. case 'I':
  704. systemic_input_latency = param->value.ui;
  705. break;
  706. case 'O':
  707. systemic_output_latency = param->value.ui;
  708. break;
  709. }
  710. }
  711. // duplex is the default
  712. if (!capture && !playback) {
  713. capture = true;
  714. playback = true;
  715. }
  716. Jack::JackOSSDriver* oss_driver = new Jack::JackOSSDriver("system", "oss", engine, table);
  717. Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(oss_driver);
  718. // Special open for OSS driver...
  719. if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
  720. excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) {
  721. return threaded_driver;
  722. } else {
  723. delete threaded_driver; // Delete the decorated driver
  724. return NULL;
  725. }
  726. }
  727. #ifdef __cplusplus
  728. }
  729. #endif