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.

767 lines
26KB

  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 short *s32src = (signed short*)src;
  38. s32src += channel;
  39. sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
  40. break;
  41. }
  42. case 32: {
  43. signed short *s32src = (signed short*)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. }
  154. }
  155. fRWMode |= kRead;
  156. fRWMode |= kWrite;
  157. }
  158. void JackOSSAdapter::DisplayDeviceInfo()
  159. {
  160. audio_buf_info info;
  161. oss_audioinfo ai_in, ai_out;
  162. memset(&info, 0, sizeof(audio_buf_info));
  163. int cap = 0;
  164. // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
  165. jack_info("Audio Interface Description :");
  166. jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode);
  167. if (fRWMode & kWrite) {
  168. oss_sysinfo si;
  169. if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
  170. jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  171. } else {
  172. jack_info("OSS product %s", si.product);
  173. jack_info("OSS version %s", si.version);
  174. jack_info("OSS version num %d", si.versionnum);
  175. jack_info("OSS numaudios %d", si.numaudios);
  176. jack_info("OSS numaudioengines %d", si.numaudioengines);
  177. jack_info("OSS numcards %d", si.numcards);
  178. }
  179. jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
  180. jack_info("Output block size = %d", fOutputBufferSize);
  181. if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  182. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  183. } else {
  184. jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  185. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  186. }
  187. if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  188. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  189. } else {
  190. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  191. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  192. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  193. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  194. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  195. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  196. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  197. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  198. }
  199. }
  200. if (fRWMode & kRead) {
  201. oss_sysinfo si;
  202. if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
  203. jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  204. } else {
  205. jack_info("OSS product %s", si.product);
  206. jack_info("OSS version %s", si.version);
  207. jack_info("OSS version num %d", si.versionnum);
  208. jack_info("OSS numaudios %d", si.numaudios);
  209. jack_info("OSS numaudioengines %d", si.numaudioengines);
  210. jack_info("OSS numcards %d", si.numcards);
  211. }
  212. jack_info("Input capabilities - %d channels : ", fCaptureChannels);
  213. jack_info("Input block size = %d", fInputBufferSize);
  214. if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
  215. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  216. } else {
  217. jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
  218. info.fragments, info.fragstotal, info.fragsize, info.bytes);
  219. }
  220. if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
  221. jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  222. } else {
  223. if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX");
  224. if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
  225. if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH");
  226. if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC");
  227. if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER");
  228. if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP");
  229. if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
  230. if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
  231. }
  232. }
  233. if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) {
  234. jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name);
  235. }
  236. if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) {
  237. jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name);
  238. }
  239. if (ai_in.rate_source != ai_out.rate_source) {
  240. jack_info("Warning : input and output are not necessarily driven by the same clock!");
  241. }
  242. }
  243. int JackOSSAdapter::OpenInput()
  244. {
  245. int flags = 0;
  246. int gFragFormat;
  247. int cur_sample_format, cur_capture_channels;
  248. jack_nframes_t cur_sample_rate;
  249. if (fCaptureChannels == 0) fCaptureChannels = 2;
  250. if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  251. jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  252. return -1;
  253. }
  254. jack_log("JackOSSAdapter::OpenInput input fInFD = %d", fInFD);
  255. if (fExcl) {
  256. if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  257. jack_error("JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  258. goto error;
  259. }
  260. }
  261. printf("fAdaptedBufferSize %d %d %d %d %s\n", fExcl, fAdaptedBufferSize, fSampleSize, fCaptureChannels, fCaptureDriverName);
  262. gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
  263. if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  264. jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  265. goto error;
  266. }
  267. cur_sample_format = fSampleFormat;
  268. if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  269. jack_error("JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  270. goto error;
  271. }
  272. if (cur_sample_format != fSampleFormat) {
  273. jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat);
  274. }
  275. cur_capture_channels = fCaptureChannels;
  276. if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
  277. jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  278. goto error;
  279. }
  280. if (cur_capture_channels != fCaptureChannels) {
  281. jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
  282. }
  283. cur_sample_rate = fAdaptedSampleRate;
  284. if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
  285. jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  286. goto error;
  287. }
  288. if (cur_sample_rate != fAdaptedSampleRate) {
  289. jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
  290. }
  291. fInputBufferSize = 0;
  292. if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
  293. jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  294. goto error;
  295. }
  296. if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) {
  297. if (fIgnoreHW) {
  298. jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize);
  299. } else {
  300. jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
  301. goto error;
  302. }
  303. }
  304. fInputBuffer = (void*)calloc(fInputBufferSize, 1);
  305. assert(fInputBuffer);
  306. fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*));
  307. assert(fInputSampleBuffer);
  308. for (int i = 0; i < fCaptureChannels; i++) {
  309. fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
  310. assert(fInputSampleBuffer[i]);
  311. }
  312. return 0;
  313. error:
  314. ::close(fInFD);
  315. return -1;
  316. }
  317. int JackOSSAdapter::OpenOutput()
  318. {
  319. int flags = 0;
  320. int gFragFormat;
  321. int cur_sample_format, cur_playback_channels;
  322. jack_nframes_t cur_sample_rate;
  323. if (fPlaybackChannels == 0) fPlaybackChannels = 2;
  324. if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
  325. jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  326. return -1;
  327. }
  328. if (fExcl) {
  329. if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
  330. jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  331. goto error;
  332. }
  333. }
  334. printf("fAdaptedBufferSize %d %d %d %d %s\n", fExcl, fAdaptedBufferSize, fSampleSize, fPlaybackChannels, fPlaybackDriverName);
  335. gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
  336. if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
  337. jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  338. goto error;
  339. }
  340. cur_sample_format = fSampleFormat;
  341. if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
  342. jack_error("JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  343. goto error;
  344. }
  345. if (cur_sample_format != fSampleFormat) {
  346. jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat);
  347. }
  348. cur_playback_channels = fPlaybackChannels;
  349. if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
  350. jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  351. goto error;
  352. }
  353. if (cur_playback_channels != fPlaybackChannels) {
  354. jack_info("JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
  355. }
  356. cur_sample_rate = fAdaptedSampleRate;
  357. if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
  358. jack_error("JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  359. goto error;
  360. }
  361. if (cur_sample_rate != fAdaptedSampleRate) {
  362. jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
  363. }
  364. fOutputBufferSize = 0;
  365. if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
  366. jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  367. goto error;
  368. }
  369. if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) {
  370. if (fIgnoreHW) {
  371. jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize);
  372. } else {
  373. jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
  374. goto error;
  375. }
  376. }
  377. fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
  378. assert(fOutputBuffer);
  379. fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*));
  380. assert(fOutputSampleBuffer);
  381. for (int i = 0; i < fPlaybackChannels; i++) {
  382. fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
  383. assert(fOutputSampleBuffer[i]);
  384. }
  385. fFirstCycle = true;
  386. return 0;
  387. error:
  388. ::close(fOutFD);
  389. return -1;
  390. }
  391. int JackOSSAdapter::Open()
  392. {
  393. SetSampleFormat();
  394. if ((fRWMode & kRead) && (OpenInput() < 0)) {
  395. return -1;
  396. }
  397. if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
  398. return -1;
  399. }
  400. // In duplex mode, check that input and output use the same buffer size
  401. if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
  402. jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!");
  403. goto error;
  404. }
  405. DisplayDeviceInfo();
  406. fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority);
  407. return fThread.StartSync();
  408. error:
  409. CloseAux();
  410. return -1;
  411. }
  412. int JackOSSAdapter::Close()
  413. {
  414. #ifdef DEBUG
  415. fTable.Save();
  416. #endif
  417. fThread.Stop();
  418. CloseAux();
  419. return 0;
  420. }
  421. void JackOSSAdapter::CloseAux()
  422. {
  423. if (fRWMode & kRead) {
  424. close(fInFD);
  425. fInFD = -1;
  426. }
  427. if (fRWMode & kWrite) {
  428. close(fOutFD);
  429. fOutFD = -1;
  430. }
  431. free(fInputBuffer);
  432. fInputBuffer = NULL;
  433. free(fOutputBuffer);
  434. fOutputBuffer = NULL;
  435. for (int i = 0; i < fCaptureChannels; i++) {
  436. free(fInputSampleBuffer[i]);
  437. }
  438. free(fInputSampleBuffer);
  439. for (int i = 0; i < fPlaybackChannels; i++) {
  440. free(fOutputSampleBuffer[i]);
  441. }
  442. free(fOutputSampleBuffer);
  443. }
  444. int JackOSSAdapter::Read()
  445. {
  446. ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
  447. if (count < fInputBufferSize) {
  448. jack_error("JackOSSAdapter::Read error bytes read = %ld", count);
  449. return -1;
  450. } else {
  451. for (int i = 0; i < fCaptureChannels; i++) {
  452. CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
  453. }
  454. return 0;
  455. }
  456. }
  457. int JackOSSAdapter::Write()
  458. {
  459. ssize_t count;
  460. // Maybe necessay to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
  461. if (fFirstCycle) {
  462. fFirstCycle = false;
  463. memset(fOutputBuffer, 0, fOutputBufferSize);
  464. // Prefill ouput buffer
  465. for (int i = 0; i < fNperiods; i++) {
  466. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  467. if (count < fOutputBufferSize) {
  468. jack_error("JackOSSDriver::Write error bytes written = %ld", count);
  469. return -1;
  470. }
  471. }
  472. int delay;
  473. if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
  474. jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
  475. return -1;
  476. }
  477. delay /= fSampleSize * fPlaybackChannels;
  478. jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
  479. }
  480. for (int i = 0; i < fPlaybackChannels; i++) {
  481. CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits);
  482. }
  483. count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
  484. if (count < fOutputBufferSize) {
  485. jack_error("JackOSSAdapter::Write error bytes written = %ld", count);
  486. return -1;
  487. } else {
  488. return 0;
  489. }
  490. }
  491. bool JackOSSAdapter::Execute()
  492. {
  493. if (Read() < 0)
  494. return false;
  495. bool failure = false;
  496. jack_nframes_t time1, time2;
  497. ResampleFactor(time1, time2);
  498. for (int i = 0; i < fCaptureChannels; i++) {
  499. fCaptureRingBuffer[i]->SetRatio(time1, time2);
  500. if (fCaptureRingBuffer[i]->WriteResample(fInputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize)
  501. failure = true;
  502. }
  503. for (int i = 0; i < fPlaybackChannels; i++) {
  504. fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  505. if (fPlaybackRingBuffer[i]->ReadResample(fOutputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize)
  506. failure = true;
  507. }
  508. #ifdef DEBUG
  509. fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
  510. fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace());
  511. #endif
  512. if (Write() < 0)
  513. return false;
  514. // Reset all ringbuffers in case of failure
  515. if (failure) {
  516. jack_error("JackOSSAdapter::Execute ringbuffer failure... reset");
  517. ResetRingBuffers();
  518. }
  519. return true;
  520. }
  521. int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size)
  522. {
  523. JackAudioAdapterInterface::SetBufferSize(buffer_size);
  524. Close();
  525. return Open();
  526. }
  527. } // namespace
  528. #ifdef __cplusplus
  529. extern "C"
  530. {
  531. #endif
  532. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  533. {
  534. jack_driver_desc_t *desc;
  535. unsigned int i;
  536. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  537. strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  538. strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  539. desc->nparams = OSS_DRIVER_N_PARAMS;
  540. desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  541. i = 0;
  542. strcpy(desc->params[i].name, "rate");
  543. desc->params[i].character = 'r';
  544. desc->params[i].type = JackDriverParamUInt;
  545. desc->params[i].value.ui = OSS_DRIVER_DEF_FS;
  546. strcpy(desc->params[i].short_desc, "Sample rate");
  547. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  548. i++;
  549. strcpy(desc->params[i].name, "period");
  550. desc->params[i].character = 'p';
  551. desc->params[i].type = JackDriverParamUInt;
  552. desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE;
  553. strcpy(desc->params[i].short_desc, "Frames per period");
  554. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  555. i++;
  556. strcpy(desc->params[i].name, "nperiods");
  557. desc->params[i].character = 'n';
  558. desc->params[i].type = JackDriverParamUInt;
  559. desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS;
  560. strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer");
  561. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  562. i++;
  563. strcpy(desc->params[i].name, "wordlength");
  564. desc->params[i].character = 'w';
  565. desc->params[i].type = JackDriverParamInt;
  566. desc->params[i].value.i = OSS_DRIVER_DEF_BITS;
  567. strcpy(desc->params[i].short_desc, "Word length");
  568. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  569. i++;
  570. strcpy(desc->params[i].name, "inchannels");
  571. desc->params[i].character = 'i';
  572. desc->params[i].type = JackDriverParamUInt;
  573. desc->params[i].value.ui = OSS_DRIVER_DEF_INS;
  574. strcpy(desc->params[i].short_desc, "Capture channels");
  575. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  576. i++;
  577. strcpy(desc->params[i].name, "outchannels");
  578. desc->params[i].character = 'o';
  579. desc->params[i].type = JackDriverParamUInt;
  580. desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS;
  581. strcpy(desc->params[i].short_desc, "Playback channels");
  582. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  583. i++;
  584. strcpy(desc->params[i].name, "excl");
  585. desc->params[i].character = 'e';
  586. desc->params[i].type = JackDriverParamBool;
  587. desc->params[i].value.i = false;
  588. strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode");
  589. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  590. i++;
  591. strcpy(desc->params[i].name, "capture");
  592. desc->params[i].character = 'C';
  593. desc->params[i].type = JackDriverParamString;
  594. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  595. strcpy(desc->params[i].short_desc, "Input device");
  596. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  597. i++;
  598. strcpy(desc->params[i].name, "playback");
  599. desc->params[i].character = 'P';
  600. desc->params[i].type = JackDriverParamString;
  601. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  602. strcpy(desc->params[i].short_desc, "Output device");
  603. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  604. i++;
  605. strcpy (desc->params[i].name, "device");
  606. desc->params[i].character = 'd';
  607. desc->params[i].type = JackDriverParamString;
  608. strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
  609. strcpy(desc->params[i].short_desc, "OSS device name");
  610. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  611. i++;
  612. strcpy(desc->params[i].name, "ignorehwbuf");
  613. desc->params[i].character = 'b';
  614. desc->params[i].type = JackDriverParamBool;
  615. desc->params[i].value.i = true;
  616. strcpy(desc->params[i].short_desc, "Ignore hardware period size");
  617. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  618. i++;
  619. strcpy(desc->params[i].name, "quality");
  620. desc->params[i].character = 'q';
  621. desc->params[i].type = JackDriverParamInt;
  622. desc->params[i].value.ui = 0;
  623. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  624. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  625. return desc;
  626. }
  627. #ifdef __cplusplus
  628. }
  629. #endif