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.

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