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