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.

692 lines
23KB

  1. /*
  2. Copyright (C) 2008 Grame & RTL 2008
  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 "JackOSSAdapter.h"
  16. #include "JackServerGlobals.h"
  17. #include "JackEngineControl.h"
  18. #include "memops.h"
  19. #include <sys/ioctl.h>
  20. #include <sys/soundcard.h>
  21. #include <fcntl.h>
  22. #include <iostream>
  23. #include <assert.h>
  24. namespace Jack
  25. {
  26. inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; }
  27. static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
  28. {
  29. switch (bits) {
  30. case 16: {
  31. signed short *s16src = (signed short*)src;
  32. s16src += channel;
  33. sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
  34. break;
  35. }
  36. case 24: {
  37. signed int *s32src = (signed int*)src;
  38. s32src += channel;
  39. sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
  40. break;
  41. }
  42. case 32: {
  43. signed int *s32src = (signed int*)src;
  44. s32src += channel;
  45. sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
  46. break;
  47. }
  48. }
  49. }
  50. static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
  51. {
  52. switch (bits) {
  53. case 16: {
  54. signed short *s16dst = (signed short*)dst;
  55. s16dst += channel;
  56. sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now...
  57. break;
  58. }
  59. case 24: {
  60. signed int *s32dst = (signed int*)dst;
  61. s32dst += channel;
  62. sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
  63. break;
  64. }
  65. case 32: {
  66. signed int *s32dst = (signed int*)dst;
  67. s32dst += channel;
  68. sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
  69. break;
  70. }
  71. }
  72. }
  73. void JackOSSAdapter::SetSampleFormat()
  74. {
  75. switch (fBits) {
  76. case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */
  77. fSampleFormat = AFMT_S24_NE;
  78. fSampleSize = sizeof(int);
  79. break;
  80. case 32: /* native-endian 32-bit integer */
  81. fSampleFormat = AFMT_S32_NE;
  82. fSampleSize = sizeof(int);
  83. break;
  84. case 16: /* native-endian 16-bit integer */
  85. default:
  86. fSampleFormat = AFMT_S16_NE;
  87. fSampleSize = sizeof(short);
  88. break;
  89. }
  90. }
  91. JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  92. :JackAudioAdapterInterface(buffer_size, sample_rate)
  93. ,fThread(this),
  94. fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS),
  95. fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false),
  96. fInputBufferSize(0), fOutputBufferSize(0),
  97. fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true)
  98. {
  99. const JSList* node;
  100. const jack_driver_param_t* param;
  101. fCaptureChannels = 2;
  102. fPlaybackChannels = 2;
  103. strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV);
  104. strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV);
  105. for (node = params; node; node = jack_slist_next(node)) {
  106. param = (const jack_driver_param_t*) node->data;
  107. switch (param->character) {
  108. case 'r':
  109. SetAdaptedSampleRate(param->value.ui);
  110. break;
  111. case 'p':
  112. SetAdaptedBufferSize(param->value.ui);
  113. break;
  114. case 'n':
  115. fNperiods = param->value.ui;
  116. break;
  117. case 'w':
  118. fBits = param->value.i;
  119. break;
  120. case 'i':
  121. fCaptureChannels = param->value.ui;
  122. break;
  123. case 'o':
  124. fPlaybackChannels = param->value.ui;
  125. break;
  126. case 'e':
  127. fExcl = true;
  128. break;
  129. case 'C':
  130. fRWMode |= kRead;
  131. if (strcmp(param->value.str, "none") != 0) {
  132. strcpy(fCaptureDriverName, param->value.str);
  133. }
  134. break;
  135. case 'P':
  136. fRWMode |= kWrite;
  137. if (strcmp(param->value.str, "none") != 0) {
  138. strcpy(fPlaybackDriverName, param->value.str);
  139. }
  140. break;
  141. case 'd':
  142. fRWMode |= kRead;
  143. fRWMode |= kWrite;
  144. strcpy(fCaptureDriverName, param->value.str);
  145. strcpy(fPlaybackDriverName, param->value.str);
  146. break;
  147. case 'b':
  148. fIgnoreHW = true;
  149. break;
  150. case 'q':
  151. fQuality = param->value.ui;
  152. break;
  153. case 'g':
  154. fRingbufferCurSize = param->value.ui;
  155. fAdaptative = false;
  156. break;
  157. case 'R':
  158. fResampleRatioPerChannel = true;
  159. break;
  160. }
  161. }
  162. fRWMode |= kRead;
  163. fRWMode |= kWrite;
  164. }
  165. void JackOSSAdapter::DisplayDeviceInfo()
  166. {
  167. audio_buf_info info;
  168. oss_audioinfo ai_in, ai_out;
  169. memset(&info, 0, sizeof(audio_buf_info));
  170. int cap = 0;
  171. // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
  172. jack_info("Audio Interface Description :");
  173. jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode);
  174. if (fRWMode & kWrite) {
  175. oss_sysinfo si;
  176. if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
  177. jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  178. } else {
  179. jack_info("OSS product %s", si.product);
  180. jack_info("OSS version %s", si.version);
  181. jack_info("OSS version num %d", si.versionnum);
  182. jack_info("OSS numaudios %d", si.numaudios);
  183. jack_info("OSS numaudioengines %d", si.numaudioengines);
  184. jack_info("OSS numcards %d", si.numcards);
  185. }
  186. jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
  187. jack_info("Output block size = %d", fOutputBufferSize);
  188. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  189. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  190. } else {
  191. jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  192. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  193. }
  194. if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  195. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  196. } else {
  197. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  198. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  199. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  200. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  201. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  202. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  203. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  204. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  205. }
  206. }
  207. if (fRWMode & kRead) {
  208. oss_sysinfo si;
  209. if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
  210. jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  211. } else {
  212. jack_info("OSS product %s", si.product);
  213. jack_info("OSS version %s", si.version);
  214. jack_info("OSS version num %d", si.versionnum);
  215. jack_info("OSS numaudios %d", si.numaudios);
  216. jack_info("OSS numaudioengines %d", si.numaudioengines);
  217. jack_info("OSS numcards %d", si.numcards);
  218. }
  219. jack_info("Input capabilities - %d channels : ", fCaptureChannels);
  220. jack_info("Input block size = %d", fInputBufferSize);
  221. if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  222. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  223. } else {
  224. jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  225. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  226. }
  227. if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  228. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  229. } else {
  230. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  231. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  232. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  233. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  234. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  235. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  236. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  237. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  238. }
  239. }
  240. if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) {
  241. jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name);
  242. }
  243. if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) {
  244. jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name);
  245. }
  246. if (ai_in.rate_source != ai_out.rate_source) {
  247. jack_info("Warning : input and output are not necessarily driven by the same clock!");
  248. }
  249. }
  250. int JackOSSAdapter::OpenInput()
  251. {
  252. int flags = 0;
  253. int gFragFormat;
  254. int cur_sample_format, cur_capture_channels;
  255. jack_nframes_t cur_sample_rate;
  256. if (fCaptureChannels == 0) fCaptureChannels = 2;
  257. if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  258. jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  259. return -1;
  260. }
  261. if (fExcl) {
  262. if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  263. jack_error("JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  264. goto error;
  265. }
  266. }
  267. gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
  268. if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  269. jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  270. goto error;
  271. }
  272. cur_sample_format = fSampleFormat;
  273. if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  274. jack_error("JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  275. goto error;
  276. }
  277. if (cur_sample_format != fSampleFormat) {
  278. jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat);
  279. }
  280. cur_capture_channels = fCaptureChannels;
  281. if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
  282. jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  283. goto error;
  284. }
  285. if (cur_capture_channels != fCaptureChannels) {
  286. jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
  287. }
  288. cur_sample_rate = fAdaptedSampleRate;
  289. if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
  290. jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  291. goto error;
  292. }
  293. if (cur_sample_rate != fAdaptedSampleRate) {
  294. jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
  295. }
  296. fInputBufferSize = 0;
  297. if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
  298. jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  299. goto error;
  300. }
  301. if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) {
  302. if (fIgnoreHW) {
  303. jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize);
  304. } else {
  305. jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
  306. goto error;
  307. }
  308. }
  309. fInputBuffer = (void*)calloc(fInputBufferSize, 1);
  310. assert(fInputBuffer);
  311. fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*));
  312. assert(fInputSampleBuffer);
  313. for (int i = 0; i < fCaptureChannels; i++) {
  314. fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
  315. assert(fInputSampleBuffer[i]);
  316. }
  317. return 0;
  318. error:
  319. ::close(fInFD);
  320. return -1;
  321. }
  322. int JackOSSAdapter::OpenOutput()
  323. {
  324. int flags = 0;
  325. int gFragFormat;
  326. int cur_sample_format, cur_playback_channels;
  327. jack_nframes_t cur_sample_rate;
  328. if (fPlaybackChannels == 0) fPlaybackChannels = 2;
  329. if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  330. jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  331. return -1;
  332. }
  333. if (fExcl) {
  334. if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  335. jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  336. goto error;
  337. }
  338. }
  339. gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
  340. if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  341. jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  342. goto error;
  343. }
  344. cur_sample_format = fSampleFormat;
  345. if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  346. jack_error("JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  347. goto error;
  348. }
  349. if (cur_sample_format != fSampleFormat) {
  350. jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat);
  351. }
  352. cur_playback_channels = fPlaybackChannels;
  353. if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
  354. jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  355. goto error;
  356. }
  357. if (cur_playback_channels != fPlaybackChannels) {
  358. jack_info("JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
  359. }
  360. cur_sample_rate = fAdaptedSampleRate;
  361. if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
  362. jack_error("JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  363. goto error;
  364. }
  365. if (cur_sample_rate != fAdaptedSampleRate) {
  366. jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
  367. }
  368. fOutputBufferSize = 0;
  369. if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
  370. jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  371. goto error;
  372. }
  373. if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) {
  374. if (fIgnoreHW) {
  375. jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize);
  376. } else {
  377. jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
  378. goto error;
  379. }
  380. }
  381. fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
  382. assert(fOutputBuffer);
  383. fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*));
  384. assert(fOutputSampleBuffer);
  385. for (int i = 0; i < fPlaybackChannels; i++) {
  386. fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
  387. assert(fOutputSampleBuffer[i]);
  388. }
  389. fFirstCycle = true;
  390. return 0;
  391. error:
  392. ::close(fOutFD);
  393. return -1;
  394. }
  395. int JackOSSAdapter::Open()
  396. {
  397. SetSampleFormat();
  398. if ((fRWMode & kRead) && (OpenInput() < 0)) {
  399. return -1;
  400. }
  401. if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
  402. return -1;
  403. }
  404. // In duplex mode, check that input and output use the same buffer size
  405. if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
  406. jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!");
  407. goto error;
  408. }
  409. DisplayDeviceInfo();
  410. //start adapter thread
  411. if (fThread.StartSync() < 0) {
  412. jack_error ( "Cannot start audioadapter thread" );
  413. return -1;
  414. }
  415. //turn the thread realtime
  416. fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority);
  417. return 0;
  418. error:
  419. CloseAux();
  420. return -1;
  421. }
  422. int JackOSSAdapter::Close()
  423. {
  424. #ifdef JACK_MONITOR
  425. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  426. #endif
  427. fThread.Stop();
  428. CloseAux();
  429. return 0;
  430. }
  431. void JackOSSAdapter::CloseAux()
  432. {
  433. if (fRWMode & kRead) {
  434. close(fInFD);
  435. fInFD = -1;
  436. }
  437. if (fRWMode & kWrite) {
  438. close(fOutFD);
  439. fOutFD = -1;
  440. }
  441. free(fInputBuffer);
  442. fInputBuffer = NULL;
  443. free(fOutputBuffer);
  444. fOutputBuffer = NULL;
  445. for (int i = 0; i < fCaptureChannels; i++) {
  446. free(fInputSampleBuffer[i]);
  447. }
  448. free(fInputSampleBuffer);
  449. for (int i = 0; i < fPlaybackChannels; i++) {
  450. free(fOutputSampleBuffer[i]);
  451. }
  452. free(fOutputSampleBuffer);
  453. }
  454. int JackOSSAdapter::Read()
  455. {
  456. ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
  457. if (count < fInputBufferSize) {
  458. jack_error("JackOSSAdapter::Read error bytes read = %ld", count);
  459. return -1;
  460. } else {
  461. for (int i = 0; i < fCaptureChannels; i++) {
  462. CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
  463. }
  464. return 0;
  465. }
  466. }
  467. int JackOSSAdapter::Write()
  468. {
  469. ssize_t count;
  470. // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
  471. if (fFirstCycle) {
  472. fFirstCycle = false;
  473. memset(fOutputBuffer, 0, fOutputBufferSize);
  474. // Prefill output buffer
  475. for (int i = 0; i < fNperiods; i++) {
  476. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  477. if (count < fOutputBufferSize) {
  478. jack_error("JackOSSDriver::Write error bytes written = %ld", count);
  479. return -1;
  480. }
  481. }
  482. int delay;
  483. if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
  484. jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  485. return -1;
  486. }
  487. delay /= fSampleSize * fPlaybackChannels;
  488. jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
  489. }
  490. for (int i = 0; i < fPlaybackChannels; i++) {
  491. CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits);
  492. }
  493. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  494. if (count < fOutputBufferSize) {
  495. jack_error("JackOSSAdapter::Write error bytes written = %ld", count);
  496. return -1;
  497. } else {
  498. return 0;
  499. }
  500. }
  501. bool JackOSSAdapter::Execute()
  502. {
  503. //read data from audio interface
  504. if (Read() < 0)
  505. return false;
  506. PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize);
  507. //write data to audio interface
  508. if (Write() < 0)
  509. return false;
  510. return true;
  511. }
  512. int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size)
  513. {
  514. JackAudioAdapterInterface::SetBufferSize(buffer_size);
  515. Close();
  516. return Open();
  517. }
  518. } // namespace
  519. #ifdef __cplusplus
  520. extern "C"
  521. {
  522. #endif
  523. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  524. {
  525. jack_driver_desc_t * desc;
  526. jack_driver_desc_filler_t filler;
  527. jack_driver_param_value_t value;
  528. desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
  529. value.ui = OSS_DRIVER_DEF_FS;
  530. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  531. value.ui = OSS_DRIVER_DEF_BLKSIZE;
  532. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  533. value.ui = OSS_DRIVER_DEF_NPERIODS;
  534. jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
  535. value.i = OSS_DRIVER_DEF_BITS;
  536. jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
  537. value.ui = OSS_DRIVER_DEF_INS;
  538. jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
  539. value.ui = OSS_DRIVER_DEF_OUTS;
  540. jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
  541. value.i = false;
  542. jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
  543. strcpy(value.str, OSS_DRIVER_DEF_DEV);
  544. jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
  545. jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
  546. jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
  547. value.i = true;
  548. jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
  549. value.ui = 0;
  550. jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
  551. value.i = 32768;
  552. jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
  553. value.i = false;
  554. jack_driver_descriptor_add_parameter(desc, &filler, "multi-ratios", 'R', JackDriverParamBool, &value, NULL, "Calculate resample ratio per channel"
  555. , "Calculate resample ratio per channel in case of repeated ringbuffer errors because of clock drift between the channels from the same device.");
  556. return desc;
  557. }
  558. #ifdef __cplusplus
  559. }
  560. #endif