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.

984 lines
33KB

  1. /*
  2. Copyright (C) 2009 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "driver_interface.h"
  16. #include "JackThreadedDriver.h"
  17. #include "JackDriverLoader.h"
  18. #include "JackBoomerDriver.h"
  19. #include "JackEngineControl.h"
  20. #include "JackGraphManager.h"
  21. #include "JackError.h"
  22. #include "JackTime.h"
  23. #include "JackShmMem.h"
  24. #include "JackGlobals.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 gCycleReadCount = 0;
  52. int gCycleWriteCount = 0;
  53. #endif
  54. inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; }
  55. static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
  56. {
  57. switch (bits) {
  58. case 16: {
  59. signed short *s16src = (signed short*)src;
  60. s16src += channel;
  61. sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
  62. break;
  63. }
  64. case 24: {
  65. signed short *s32src = (signed short*)src;
  66. s32src += channel;
  67. sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
  68. break;
  69. }
  70. case 32: {
  71. signed short *s32src = (signed short*)src;
  72. s32src += channel;
  73. sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
  74. break;
  75. }
  76. }
  77. }
  78. static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
  79. {
  80. switch (bits) {
  81. case 16: {
  82. signed short *s16dst = (signed short*)dst;
  83. s16dst += channel;
  84. sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now...
  85. break;
  86. }
  87. case 24: {
  88. signed int *s32dst = (signed int*)dst;
  89. s32dst += channel;
  90. sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
  91. break;
  92. }
  93. case 32: {
  94. signed int *s32dst = (signed int*)dst;
  95. s32dst += channel;
  96. sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
  97. break;
  98. }
  99. }
  100. }
  101. void JackBoomerDriver::SetSampleFormat()
  102. {
  103. switch (fBits) {
  104. case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */
  105. fSampleFormat = AFMT_S24_NE;
  106. fSampleSize = sizeof(int);
  107. break;
  108. case 32: /* native-endian 32-bit integer */
  109. fSampleFormat = AFMT_S32_NE;
  110. fSampleSize = sizeof(int);
  111. break;
  112. case 16: /* native-endian 16-bit integer */
  113. default:
  114. fSampleFormat = AFMT_S16_NE;
  115. fSampleSize = sizeof(short);
  116. break;
  117. }
  118. }
  119. void JackBoomerDriver::DisplayDeviceInfo()
  120. {
  121. audio_buf_info info;
  122. oss_audioinfo ai_in, ai_out;
  123. memset(&info, 0, sizeof(audio_buf_info));
  124. int cap = 0;
  125. // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
  126. jack_info("Audio Interface Description :");
  127. jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
  128. if (fRWMode & kWrite) {
  129. oss_sysinfo si;
  130. if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
  131. jack_error("JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  132. } else {
  133. jack_info("OSS product %s", si.product);
  134. jack_info("OSS version %s", si.version);
  135. jack_info("OSS version num %d", si.versionnum);
  136. jack_info("OSS numaudios %d", si.numaudios);
  137. jack_info("OSS numaudioengines %d", si.numaudioengines);
  138. jack_info("OSS numcards %d", si.numcards);
  139. }
  140. jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
  141. jack_info("Output block size = %d", fOutputBufferSize);
  142. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  143. jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  144. } else {
  145. jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  146. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  147. }
  148. if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  149. jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  150. } else {
  151. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  152. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  153. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  154. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  155. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  156. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  157. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  158. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  159. }
  160. }
  161. if (fRWMode & kRead) {
  162. oss_sysinfo si;
  163. if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
  164. jack_error("JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  165. } else {
  166. jack_info("OSS product %s", si.product);
  167. jack_info("OSS version %s", si.version);
  168. jack_info("OSS version num %d", si.versionnum);
  169. jack_info("OSS numaudios %d", si.numaudios);
  170. jack_info("OSS numaudioengines %d", si.numaudioengines);
  171. jack_info("OSS numcards %d", si.numcards);
  172. }
  173. jack_info("Input capabilities - %d channels : ", fCaptureChannels);
  174. jack_info("Input block size = %d", fInputBufferSize);
  175. if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
  176. jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  177. } else {
  178. jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  179. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  180. }
  181. if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  182. jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  183. } else {
  184. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  185. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  186. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  187. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  188. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  189. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  190. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  191. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  192. }
  193. }
  194. if (ai_in.rate_source != ai_out.rate_source) {
  195. jack_info("Warning : input and output are not necessarily driven by the same clock!");
  196. }
  197. }
  198. int JackBoomerDriver::OpenInput()
  199. {
  200. int flags = 0;
  201. int gFragFormat;
  202. int cur_capture_channels;
  203. int cur_sample_format;
  204. jack_nframes_t cur_sample_rate;
  205. if (fCaptureChannels == 0) fCaptureChannels = 2;
  206. if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  207. jack_error("JackBoomerDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  208. return -1;
  209. }
  210. jack_log("JackBoomerDriver::OpenInput input fInFD = %d", fInFD);
  211. if (fExcl) {
  212. if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  213. jack_error("JackBoomerDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  214. goto error;
  215. }
  216. }
  217. gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
  218. if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  219. jack_error("JackBoomerDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  220. goto error;
  221. }
  222. cur_sample_format = fSampleFormat;
  223. if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  224. jack_error("JackBoomerDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  225. goto error;
  226. }
  227. if (cur_sample_format != fSampleFormat) {
  228. jack_info("JackBoomerDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
  229. }
  230. cur_capture_channels = fCaptureChannels;
  231. if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
  232. jack_error("JackBoomerDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  233. goto error;
  234. }
  235. if (cur_capture_channels != fCaptureChannels) {
  236. jack_info("JackBoomerDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
  237. }
  238. cur_sample_rate = fEngineControl->fSampleRate;
  239. if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  240. jack_error("JackBoomerDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  241. goto error;
  242. }
  243. if (cur_sample_rate != fEngineControl->fSampleRate) {
  244. jack_info("JackBoomerDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  245. }
  246. // Just set the read size to the value we want...
  247. fInputBufferSize = fEngineControl->fBufferSize * fSampleSize * fCaptureChannels;
  248. fInputBuffer = (void*)calloc(fInputBufferSize, 1);
  249. assert(fInputBuffer);
  250. return 0;
  251. error:
  252. ::close(fInFD);
  253. return -1;
  254. }
  255. int JackBoomerDriver::OpenOutput()
  256. {
  257. int flags = 0;
  258. int gFragFormat;
  259. int cur_sample_format;
  260. int cur_playback_channels;
  261. jack_nframes_t cur_sample_rate;
  262. if (fPlaybackChannels == 0) fPlaybackChannels = 2;
  263. if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  264. jack_error("JackBoomerDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  265. return -1;
  266. }
  267. jack_log("JackBoomerDriver::OpenOutput output fOutFD = %d", fOutFD);
  268. if (fExcl) {
  269. if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  270. jack_error("JackBoomerDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  271. goto error;
  272. }
  273. }
  274. gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
  275. if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  276. jack_error("JackBoomerDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  277. goto error;
  278. }
  279. cur_sample_format = fSampleFormat;
  280. if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  281. jack_error("JackBoomerDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  282. goto error;
  283. }
  284. if (cur_sample_format != fSampleFormat) {
  285. jack_info("JackBoomerDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
  286. }
  287. cur_playback_channels = fPlaybackChannels;
  288. if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
  289. jack_error("JackBoomerDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  290. goto error;
  291. }
  292. if (cur_playback_channels != fPlaybackChannels) {
  293. jack_info("JackBoomerDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
  294. }
  295. cur_sample_rate = fEngineControl->fSampleRate;
  296. if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
  297. jack_error("JackBoomerDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  298. goto error;
  299. }
  300. if (cur_sample_rate != fEngineControl->fSampleRate) {
  301. jack_info("JackBoomerDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate);
  302. }
  303. // Just set the write size to the value we want...
  304. fOutputBufferSize = fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels;
  305. fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
  306. assert(fOutputBuffer);
  307. return 0;
  308. error:
  309. ::close(fOutFD);
  310. return -1;
  311. }
  312. int JackBoomerDriver::Open(jack_nframes_t nframes,
  313. int user_nperiods,
  314. jack_nframes_t samplerate,
  315. bool capturing,
  316. bool playing,
  317. int inchannels,
  318. int outchannels,
  319. bool excl,
  320. bool monitor,
  321. const char* capture_driver_uid,
  322. const char* playback_driver_uid,
  323. jack_nframes_t capture_latency,
  324. jack_nframes_t playback_latency,
  325. int bits,
  326. bool ignorehwbuf)
  327. {
  328. if (playing && !capturing) {
  329. jack_error("Playback only mode is not yet supported, use duplex instead");
  330. return -1;
  331. }
  332. // Generic JackAudioDriver Open
  333. if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
  334. capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
  335. return -1;
  336. } else {
  337. if (!fEngineControl->fSyncMode) {
  338. jack_error("Cannot run in asynchronous mode, use the -S parameter for jackd");
  339. return -1;
  340. }
  341. fRWMode |= ((capturing) ? kRead : 0);
  342. fRWMode |= ((playing) ? kWrite : 0);
  343. fBits = bits;
  344. fIgnoreHW = ignorehwbuf;
  345. fNperiods = user_nperiods;
  346. fExcl = excl;
  347. #ifdef JACK_MONITOR
  348. // Force memory page in
  349. memset(&gCycleTable, 0, sizeof(gCycleTable));
  350. #endif
  351. if (OpenAux() < 0) {
  352. Close();
  353. return -1;
  354. } else {
  355. return 0;
  356. }
  357. }
  358. }
  359. int JackBoomerDriver::Close()
  360. {
  361. #ifdef JACK_MONITOR
  362. FILE* file = fopen("OSSProfiling.log", "w");
  363. if (file) {
  364. jack_info("Writing OSS driver timing data....");
  365. for (int i = 1; i < std::min(gCycleReadCount, gCycleWriteCount); i++) {
  366. int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
  367. int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
  368. int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
  369. int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
  370. fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
  371. }
  372. fclose(file);
  373. } else {
  374. jack_error("JackBoomerDriver::Close : cannot open OSSProfiling.log file");
  375. }
  376. file = fopen("TimingOSS.plot", "w");
  377. if (file == NULL) {
  378. jack_error("JackBoomerDriver::Close cannot open TimingOSS.plot file");
  379. } else {
  380. fprintf(file, "set grid\n");
  381. fprintf(file, "set title \"OSS audio driver timing\"\n");
  382. fprintf(file, "set xlabel \"audio cycles\"\n");
  383. fprintf(file, "set ylabel \"usec\"\n");
  384. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  385. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  386. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  387. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  388. fprintf(file, "set output 'TimingOSS.pdf\n");
  389. fprintf(file, "set terminal pdf\n");
  390. fprintf(file, "set grid\n");
  391. fprintf(file, "set title \"OSS audio driver timing\"\n");
  392. fprintf(file, "set xlabel \"audio cycles\"\n");
  393. fprintf(file, "set ylabel \"usec\"\n");
  394. fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \
  395. \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
  396. \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
  397. \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
  398. fclose(file);
  399. }
  400. #endif
  401. int res = JackAudioDriver::Close();
  402. CloseAux();
  403. return res;
  404. }
  405. int JackBoomerDriver::OpenAux()
  406. {
  407. SetSampleFormat();
  408. if ((fRWMode & kRead) && (OpenInput() < 0)) {
  409. return -1;
  410. }
  411. if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
  412. return -1;
  413. }
  414. // Prepare ringbuffers used for output
  415. if (fPlaybackChannels > 0) {
  416. fRingBuffer = new jack_ringbuffer_t*[fPlaybackChannels];
  417. for (int i = 0; i < fPlaybackChannels; i++) {
  418. fRingBuffer[i] = jack_ringbuffer_create(fOutputBufferSize * 2);
  419. jack_ringbuffer_read_advance(fRingBuffer[i], fOutputBufferSize);
  420. }
  421. }
  422. DisplayDeviceInfo();
  423. return 0;
  424. }
  425. void JackBoomerDriver::CloseAux()
  426. {
  427. if (fRWMode & kRead && fInFD > 0) {
  428. close(fInFD);
  429. fInFD = -1;
  430. }
  431. if (fRWMode & kWrite && fOutFD > 0) {
  432. close(fOutFD);
  433. fOutFD = -1;
  434. }
  435. if (fInputBuffer)
  436. free(fInputBuffer);
  437. fInputBuffer = NULL;
  438. if (fOutputBuffer)
  439. free(fOutputBuffer);
  440. fOutputBuffer = NULL;
  441. for (int i = 0; i < fPlaybackChannels; i++) {
  442. if (fRingBuffer[i])
  443. jack_ringbuffer_free(fRingBuffer[i]);
  444. fRingBuffer[i] = NULL;
  445. }
  446. delete [] fRingBuffer;
  447. fRingBuffer = NULL;
  448. }
  449. int JackBoomerDriver::Start()
  450. {
  451. jack_log("JackBoomerDriver::Start");
  452. JackAudioDriver::Start();
  453. // Start output thread only when needed
  454. if (fOutFD > 0) {
  455. if (fThread.StartSync() < 0) {
  456. jack_error("Cannot start thread");
  457. return -1;
  458. }
  459. }
  460. return 0;
  461. }
  462. int JackBoomerDriver::Stop()
  463. {
  464. // Stop output thread only when needed
  465. if (fOutFD > 0) {
  466. return fThread.Kill();
  467. } else {
  468. return 0;
  469. }
  470. }
  471. int JackBoomerDriver::Read()
  472. {
  473. if (fInFD < 0) {
  474. // Keep begin cycle time
  475. JackDriver::CycleTakeBeginTime();
  476. return 0;
  477. }
  478. #ifdef JACK_MONITOR
  479. gCycleTable.fTable[gCycleReadCount].fBeforeRead = GetMicroSeconds();
  480. #endif
  481. audio_errinfo ei_in;
  482. ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
  483. #ifdef JACK_MONITOR
  484. if (count > 0 && count != (int)fInputBufferSize)
  485. jack_log("JackBoomerDriver::Read count = %ld", count / (fSampleSize * fCaptureChannels));
  486. gCycleTable.fTable[gCycleReadCount].fAfterRead = GetMicroSeconds();
  487. #endif
  488. // XRun detection
  489. if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
  490. if (ei_in.rec_overruns > 0 ) {
  491. jack_error("JackBoomerDriver::Read overruns");
  492. jack_time_t cur_time = GetMicroSeconds();
  493. NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
  494. }
  495. if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
  496. jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
  497. }
  498. }
  499. if (count < 0) {
  500. jack_log("JackBoomerDriver::Read error = %s", strerror(errno));
  501. return -1;
  502. } else if (count < (int)fInputBufferSize) {
  503. jack_error("JackBoomerDriver::Read error bytes read = %ld", count);
  504. return -1;
  505. } else {
  506. // Keep begin cycle time
  507. JackDriver::CycleTakeBeginTime();
  508. for (int i = 0; i < fCaptureChannels; i++) {
  509. if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
  510. CopyAndConvertIn(GetInputBuffer(i), fInputBuffer, fEngineControl->fBufferSize, i, fCaptureChannels, fBits);
  511. }
  512. }
  513. #ifdef JACK_MONITOR
  514. gCycleTable.fTable[gCycleReadCount].fAfterReadConvert = GetMicroSeconds();
  515. gCycleReadCount = (gCycleReadCount == CYCLE_POINTS - 1) ? gCycleReadCount: gCycleReadCount + 1;
  516. #endif
  517. return 0;
  518. }
  519. }
  520. int JackBoomerDriver::Write()
  521. {
  522. for (int i = 0; i < fPlaybackChannels; i++) {
  523. if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
  524. if (jack_ringbuffer_write(fRingBuffer[i], (char*)GetOutputBuffer(i), fOutputBufferSize) < fOutputBufferSize) {
  525. jack_error("JackBoomerDriver::Write ringbuffer full");
  526. }
  527. }
  528. }
  529. return 0;
  530. }
  531. bool JackBoomerDriver::Init()
  532. {
  533. if (IsRealTime()) {
  534. jack_log("JackBoomerDriver::Init IsRealTime");
  535. if (fThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
  536. jack_error("AcquireRealTime error");
  537. } else {
  538. set_threaded_log_function();
  539. }
  540. }
  541. // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
  542. memset(fOutputBuffer, 0, fOutputBufferSize);
  543. // Prefill ouput buffer
  544. if (fOutFD > 0) {
  545. for (int i = 0; i < fNperiods; i++) {
  546. ssize_t count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  547. if (count < (int)fOutputBufferSize) {
  548. jack_error("JackBoomerDriver::Write error bytes written = %ld", count);
  549. }
  550. }
  551. int delay;
  552. if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
  553. jack_error("JackBoomerDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  554. }
  555. delay /= fSampleSize * fPlaybackChannels;
  556. jack_info("JackBoomerDriver::Write output latency frames = %ld", delay);
  557. }
  558. return true;
  559. }
  560. bool JackBoomerDriver::Execute()
  561. {
  562. memset(fOutputBuffer, 0, fOutputBufferSize);
  563. #ifdef JACK_MONITOR
  564. gCycleTable.fTable[gCycleWriteCount].fBeforeWriteConvert = GetMicroSeconds();
  565. #endif
  566. for (int i = 0; i < fPlaybackChannels; i++) {
  567. if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
  568. jack_ringbuffer_data_t ring_buffer_data[2];
  569. jack_ringbuffer_get_read_vector(fRingBuffer[i], ring_buffer_data);
  570. unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(float);
  571. jack_log("Output available = %ld", available_frames);
  572. unsigned int needed_bytes = fOutputBufferSize;
  573. float* output = (float*)fOutputBuffer;
  574. for (int j = 0; j < 2; j++) {
  575. unsigned int consumed_bytes = std::min(needed_bytes, ring_buffer_data[j].len);
  576. CopyAndConvertOut(output, (float*)ring_buffer_data[j].buf, consumed_bytes / sizeof(float), i, fPlaybackChannels, fBits);
  577. output += consumed_bytes / sizeof(float);
  578. needed_bytes -= consumed_bytes;
  579. }
  580. if (needed_bytes > 0) {
  581. jack_error("JackBoomerDriver::Execute missing bytes = %ld", needed_bytes);
  582. }
  583. jack_ringbuffer_read_advance(fRingBuffer[i], fOutputBufferSize - needed_bytes);
  584. }
  585. }
  586. #ifdef JACK_MONITOR
  587. gCycleTable.fTable[gCycleWriteCount].fBeforeWrite = GetMicroSeconds();
  588. #endif
  589. ssize_t count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  590. #ifdef JACK_MONITOR
  591. if (count > 0 && count != (int)fOutputBufferSize)
  592. jack_log("JackBoomerDriver::Execute count = %ld", count / (fSampleSize * fPlaybackChannels));
  593. gCycleTable.fTable[gCycleWriteCount].fAfterWrite = GetMicroSeconds();
  594. gCycleWriteCount = (gCycleWriteCount == CYCLE_POINTS - 1) ? gCycleWriteCount: gCycleWriteCount + 1;
  595. #endif
  596. // XRun detection
  597. audio_errinfo ei_out;
  598. if (ioctl(fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) {
  599. if (ei_out.play_underruns > 0) {
  600. jack_error("JackBoomerDriver::Execute underruns");
  601. jack_time_t cur_time = GetMicroSeconds();
  602. NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
  603. }
  604. if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
  605. jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
  606. }
  607. }
  608. if (count < 0) {
  609. jack_log("JackBoomerDriver::Execute error = %s", strerror(errno));
  610. } else if (count < (int)fOutputBufferSize) {
  611. jack_error("JackBoomerDriver::Execute error bytes written = %ld", count);
  612. }
  613. return true;
  614. }
  615. int JackBoomerDriver::SetBufferSize(jack_nframes_t buffer_size)
  616. {
  617. CloseAux();
  618. JackAudioDriver::SetBufferSize(buffer_size); // never fails
  619. return OpenAux();
  620. }
  621. } // end of namespace
  622. #ifdef __cplusplus
  623. extern "C"
  624. {
  625. #endif
  626. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
  627. {
  628. jack_driver_desc_t *desc;
  629. unsigned int i;
  630. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  631. strcpy(desc->name, "boomer"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  632. strcpy(desc->desc, "Boomer/OSS API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  633. desc->nparams = OSS_DRIVER_N_PARAMS;
  634. desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  635. i = 0;
  636. strcpy(desc->params[i].name, "rate");
  637. desc->params[i].character = 'r';
  638. desc->params[i].type = JackDriverParamUInt;
  639. desc->params[i].value.ui = OSS_DRIVER_DEF_FS;
  640. strcpy(desc->params[i].short_desc, "Sample rate");
  641. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  642. i++;
  643. strcpy(desc->params[i].name, "period");
  644. desc->params[i].character = 'p';
  645. desc->params[i].type = JackDriverParamUInt;
  646. desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE;
  647. strcpy(desc->params[i].short_desc, "Frames per period");
  648. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  649. i++;
  650. strcpy(desc->params[i].name, "nperiods");
  651. desc->params[i].character = 'n';
  652. desc->params[i].type = JackDriverParamUInt;
  653. desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS;
  654. strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer");
  655. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  656. i++;
  657. strcpy(desc->params[i].name, "wordlength");
  658. desc->params[i].character = 'w';
  659. desc->params[i].type = JackDriverParamInt;
  660. desc->params[i].value.i = OSS_DRIVER_DEF_BITS;
  661. strcpy(desc->params[i].short_desc, "Word length");
  662. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  663. i++;
  664. strcpy(desc->params[i].name, "inchannels");
  665. desc->params[i].character = 'i';
  666. desc->params[i].type = JackDriverParamUInt;
  667. desc->params[i].value.ui = OSS_DRIVER_DEF_INS;
  668. strcpy(desc->params[i].short_desc, "Capture channels");
  669. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  670. i++;
  671. strcpy(desc->params[i].name, "outchannels");
  672. desc->params[i].character = 'o';
  673. desc->params[i].type = JackDriverParamUInt;
  674. desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS;
  675. strcpy(desc->params[i].short_desc, "Playback channels");
  676. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  677. i++;
  678. strcpy(desc->params[i].name, "excl");
  679. desc->params[i].character = 'e';
  680. desc->params[i].type = JackDriverParamBool;
  681. desc->params[i].value.i = false;
  682. strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode");
  683. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  684. i++;
  685. strcpy(desc->params[i].name, "capture");
  686. desc->params[i].character = 'C';
  687. desc->params[i].type = JackDriverParamString;
  688. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  689. strcpy(desc->params[i].short_desc, "Input device");
  690. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  691. i++;
  692. strcpy(desc->params[i].name, "playback");
  693. desc->params[i].character = 'P';
  694. desc->params[i].type = JackDriverParamString;
  695. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  696. strcpy(desc->params[i].short_desc, "Output device");
  697. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  698. i++;
  699. strcpy (desc->params[i].name, "device");
  700. desc->params[i].character = 'd';
  701. desc->params[i].type = JackDriverParamString;
  702. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  703. strcpy(desc->params[i].short_desc, "OSS device name");
  704. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  705. i++;
  706. strcpy(desc->params[i].name, "ignorehwbuf");
  707. desc->params[i].character = 'b';
  708. desc->params[i].type = JackDriverParamBool;
  709. desc->params[i].value.i = false;
  710. strcpy(desc->params[i].short_desc, "Ignore hardware period size");
  711. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  712. i++;
  713. strcpy(desc->params[i].name, "input-latency");
  714. desc->params[i].character = 'I';
  715. desc->params[i].type = JackDriverParamUInt;
  716. desc->params[i].value.i = 0;
  717. strcpy(desc->params[i].short_desc, "Extra input latency");
  718. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  719. i++;
  720. strcpy(desc->params[i].name, "output-latency");
  721. desc->params[i].character = 'O';
  722. desc->params[i].type = JackDriverParamUInt;
  723. desc->params[i].value.i = 0;
  724. strcpy(desc->params[i].short_desc, "Extra output latency");
  725. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  726. return desc;
  727. }
  728. EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  729. {
  730. int bits = OSS_DRIVER_DEF_BITS;
  731. jack_nframes_t srate = OSS_DRIVER_DEF_FS;
  732. jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE;
  733. const char* capture_pcm_name = OSS_DRIVER_DEF_DEV;
  734. const char* playback_pcm_name = OSS_DRIVER_DEF_DEV;
  735. bool capture = false;
  736. bool playback = false;
  737. int chan_in = 0;
  738. int chan_out = 0;
  739. bool monitor = false;
  740. bool excl = false;
  741. unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
  742. const JSList *node;
  743. const jack_driver_param_t *param;
  744. bool ignorehwbuf = false;
  745. jack_nframes_t systemic_input_latency = 0;
  746. jack_nframes_t systemic_output_latency = 0;
  747. for (node = params; node; node = jack_slist_next(node)) {
  748. param = (const jack_driver_param_t *)node->data;
  749. switch (param->character) {
  750. case 'r':
  751. srate = param->value.ui;
  752. break;
  753. case 'p':
  754. frames_per_interrupt = (unsigned int)param->value.ui;
  755. break;
  756. case 'n':
  757. nperiods = (unsigned int)param->value.ui;
  758. break;
  759. case 'w':
  760. bits = param->value.i;
  761. break;
  762. case 'i':
  763. chan_in = (int)param->value.ui;
  764. break;
  765. case 'o':
  766. chan_out = (int)param->value.ui;
  767. break;
  768. case 'C':
  769. capture = true;
  770. if (strcmp(param->value.str, "none") != 0) {
  771. capture_pcm_name = strdup(param->value.str);
  772. }
  773. break;
  774. case 'P':
  775. playback = true;
  776. if (strcmp(param->value.str, "none") != 0) {
  777. playback_pcm_name = strdup(param->value.str);
  778. }
  779. break;
  780. case 'd':
  781. playback_pcm_name = strdup (param->value.str);
  782. capture_pcm_name = strdup (param->value.str);
  783. break;
  784. case 'b':
  785. ignorehwbuf = true;
  786. break;
  787. case 'e':
  788. excl = true;
  789. break;
  790. case 'I':
  791. systemic_input_latency = param->value.ui;
  792. break;
  793. case 'O':
  794. systemic_output_latency = param->value.ui;
  795. break;
  796. }
  797. }
  798. // duplex is the default
  799. if (!capture && !playback) {
  800. capture = true;
  801. playback = true;
  802. }
  803. Jack::JackBoomerDriver* boomer_driver = new Jack::JackBoomerDriver("system", "boomer", engine, table);
  804. Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(boomer_driver);
  805. // Special open for Boomer driver...
  806. if (boomer_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
  807. excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) {
  808. return threaded_driver;
  809. } else {
  810. delete threaded_driver; // Delete the decorated driver
  811. return NULL;
  812. }
  813. }
  814. #ifdef __cplusplus
  815. }
  816. #endif