Jack2 1.9.10

JackOSSAdapter.cpp

00001 /*
00002 Copyright (C) 2008 Grame & RTL 2008
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackOSSAdapter.h"
00021 #include "JackServerGlobals.h"
00022 #include "JackEngineControl.h"
00023 #include "memops.h"
00024 
00025 #include <sys/ioctl.h>
00026 #include <sys/soundcard.h>
00027 #include <fcntl.h>
00028 #include <iostream>
00029 #include <assert.h>
00030 
00031 namespace Jack
00032 {
00033 
00034 inline int int2pow2(int x)      { int r = 0; while ((1 << r) < x) r++; return r; }
00035 
00036 static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits)
00037 {
00038     switch (bits) {
00039 
00040                 case 16: {
00041                     signed short *s16src = (signed short*)src;
00042             s16src += channel;
00043             sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1);
00044                         break;
00045         }
00046                 case 24: {
00047                         signed int *s32src = (signed int*)src;
00048             s32src += channel;
00049             sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2);
00050                         break;
00051         }
00052                 case 32: {
00053                         signed int *s32src = (signed int*)src;
00054             s32src += channel;
00055             sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2);
00056                         break;
00057         }
00058         }
00059 }
00060 
00061 static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits)
00062 {
00063         switch (bits) {
00064 
00065                 case 16: {
00066                         signed short *s16dst = (signed short*)dst;
00067             s16dst += channel;
00068             sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now...
00069                         break;
00070         }
00071                 case 24: {
00072                         signed int *s32dst = (signed int*)dst;
00073             s32dst += channel;
00074             sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
00075                         break;
00076         }
00077                 case 32: {
00078             signed int *s32dst = (signed int*)dst;
00079             s32dst += channel;
00080             sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
00081                         break;
00082         }
00083         }
00084 }
00085 
00086 void JackOSSAdapter::SetSampleFormat()
00087 {
00088     switch (fBits) {
00089 
00090             case 24:    /* native-endian LSB aligned 24-bits in 32-bits  integer */
00091             fSampleFormat = AFMT_S24_NE;
00092             fSampleSize = sizeof(int);
00093                         break;
00094                 case 32:        /* native-endian 32-bit integer */
00095             fSampleFormat = AFMT_S32_NE;
00096             fSampleSize = sizeof(int);
00097                         break;
00098                 case 16:        /* native-endian 16-bit integer */
00099                 default:
00100             fSampleFormat = AFMT_S16_NE;
00101             fSampleSize = sizeof(short);
00102                         break;
00103     }
00104 }
00105 
00106 JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
00107                 :JackAudioAdapterInterface(buffer_size, sample_rate)
00108                 ,fThread(this),
00109                 fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS),
00110                 fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false),
00111                 fInputBufferSize(0), fOutputBufferSize(0),
00112                 fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true)
00113 {
00114     const JSList* node;
00115     const jack_driver_param_t* param;
00116 
00117     fCaptureChannels = 2;
00118     fPlaybackChannels = 2;
00119 
00120     strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV);
00121     strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV);
00122 
00123     for (node = params; node; node = jack_slist_next(node)) {
00124         param = (const jack_driver_param_t*) node->data;
00125 
00126         switch (param->character) {
00127 
00128             case 'r':
00129                 SetAdaptedSampleRate(param->value.ui);
00130                 break;
00131 
00132             case 'p':
00133                 SetAdaptedBufferSize(param->value.ui);
00134                 break;
00135 
00136             case 'n':
00137                 fNperiods = param->value.ui;
00138                 break;
00139 
00140             case 'w':
00141                 fBits = param->value.i;
00142                 break;
00143 
00144             case 'i':
00145                 fCaptureChannels = param->value.ui;
00146                 break;
00147 
00148             case 'o':
00149                 fPlaybackChannels = param->value.ui;
00150                 break;
00151 
00152             case 'e':
00153                 fExcl = true;
00154                 break;
00155 
00156             case 'C':
00157                 fRWMode |= kRead;
00158                 if (strcmp(param->value.str, "none") != 0) {
00159                    strcpy(fCaptureDriverName, param->value.str);
00160                 }
00161                 break;
00162 
00163             case 'P':
00164                 fRWMode |= kWrite;
00165                 if (strcmp(param->value.str, "none") != 0) {
00166                    strcpy(fPlaybackDriverName, param->value.str);
00167                 }
00168                 break;
00169 
00170             case 'd':
00171                fRWMode |= kRead;
00172                fRWMode |= kWrite;
00173                strcpy(fCaptureDriverName, param->value.str);
00174                strcpy(fPlaybackDriverName, param->value.str);
00175                break;
00176 
00177             case 'b':
00178                 fIgnoreHW = true;
00179                 break;
00180 
00181             case 'q':
00182                 fQuality = param->value.ui;
00183                 break;
00184 
00185             case 'g':
00186                 fRingbufferCurSize = param->value.ui;
00187                 fAdaptative = false;
00188                 break;
00189 
00190            }
00191     }
00192 
00193     fRWMode |= kRead;
00194     fRWMode |= kWrite;
00195 }
00196 
00197 void JackOSSAdapter::DisplayDeviceInfo()
00198 {
00199     audio_buf_info info;
00200     oss_audioinfo ai_in, ai_out;
00201     memset(&info, 0, sizeof(audio_buf_info));
00202     int cap = 0;
00203 
00204     // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
00205 
00206     jack_info("Audio Interface Description :");
00207     jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode);
00208 
00209     if (fRWMode & kWrite) {
00210 
00211        oss_sysinfo si;
00212         if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
00213             jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00214         } else {
00215             jack_info("OSS product %s", si.product);
00216             jack_info("OSS version %s", si.version);
00217             jack_info("OSS version num %d", si.versionnum);
00218             jack_info("OSS numaudios %d", si.numaudios);
00219             jack_info("OSS numaudioengines %d", si.numaudioengines);
00220             jack_info("OSS numcards %d", si.numcards);
00221         }
00222 
00223         jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
00224         jack_info("Output block size = %d", fOutputBufferSize);
00225 
00226         if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1)  {
00227             jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00228         } else {
00229             jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
00230                 info.fragments, info.fragstotal, info.fragsize, info.bytes);
00231         }
00232 
00233         if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1)  {
00234             jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00235         } else {
00236             if (cap & DSP_CAP_DUPLEX)   jack_info(" DSP_CAP_DUPLEX");
00237             if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
00238             if (cap & DSP_CAP_BATCH)    jack_info(" DSP_CAP_BATCH");
00239             if (cap & DSP_CAP_COPROC)   jack_info(" DSP_CAP_COPROC");
00240             if (cap & DSP_CAP_TRIGGER)  jack_info(" DSP_CAP_TRIGGER");
00241             if (cap & DSP_CAP_MMAP)     jack_info(" DSP_CAP_MMAP");
00242             if (cap & DSP_CAP_MULTI)    jack_info(" DSP_CAP_MULTI");
00243             if (cap & DSP_CAP_BIND)     jack_info(" DSP_CAP_BIND");
00244         }
00245     }
00246 
00247     if (fRWMode & kRead) {
00248 
00249         oss_sysinfo si;
00250         if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
00251             jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00252         } else {
00253             jack_info("OSS product %s", si.product);
00254             jack_info("OSS version %s", si.version);
00255             jack_info("OSS version num %d", si.versionnum);
00256             jack_info("OSS numaudios %d", si.numaudios);
00257             jack_info("OSS numaudioengines %d", si.numaudioengines);
00258             jack_info("OSS numcards %d", si.numcards);
00259         }
00260 
00261         jack_info("Input capabilities - %d channels : ", fCaptureChannels);
00262         jack_info("Input block size = %d", fInputBufferSize);
00263 
00264         if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
00265             jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00266         } else {
00267             jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
00268                 info.fragments, info.fragstotal, info.fragsize, info.bytes);
00269         }
00270 
00271         if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
00272             jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00273         } else {
00274             if (cap & DSP_CAP_DUPLEX)   jack_info(" DSP_CAP_DUPLEX");
00275             if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME");
00276             if (cap & DSP_CAP_BATCH)    jack_info(" DSP_CAP_BATCH");
00277             if (cap & DSP_CAP_COPROC)   jack_info(" DSP_CAP_COPROC");
00278             if (cap & DSP_CAP_TRIGGER)  jack_info(" DSP_CAP_TRIGGER");
00279             if (cap & DSP_CAP_MMAP)     jack_info(" DSP_CAP_MMAP");
00280             if (cap & DSP_CAP_MULTI)    jack_info(" DSP_CAP_MULTI");
00281             if (cap & DSP_CAP_BIND)     jack_info(" DSP_CAP_BIND");
00282         }
00283     }
00284 
00285     if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) {
00286         jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name);
00287     }
00288 
00289     if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) {
00290         jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name);
00291     }
00292 
00293     if (ai_in.rate_source != ai_out.rate_source) {
00294         jack_info("Warning : input and output are not necessarily driven by the same clock!");
00295     }
00296 }
00297 
00298 int JackOSSAdapter::OpenInput()
00299 {
00300     int flags = 0;
00301     int gFragFormat;
00302     int cur_sample_format, cur_capture_channels;
00303     jack_nframes_t cur_sample_rate;
00304 
00305     if (fCaptureChannels == 0) fCaptureChannels = 2;
00306 
00307     if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
00308         jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00309         return -1;
00310     }
00311 
00312     if (fExcl) {
00313         if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
00314             jack_error("JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00315             goto error;
00316         }
00317     }
00318 
00319     gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
00320     if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
00321         jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00322         goto error;
00323     }
00324 
00325     cur_sample_format = fSampleFormat;
00326     if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
00327         jack_error("JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00328         goto error;
00329     }
00330     if (cur_sample_format != fSampleFormat) {
00331         jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat);
00332     }
00333 
00334     cur_capture_channels = fCaptureChannels;
00335     if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
00336         jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00337         goto error;
00338     }
00339     if (cur_capture_channels != fCaptureChannels) {
00340         jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
00341     }
00342 
00343     cur_sample_rate = fAdaptedSampleRate;
00344     if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
00345         jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00346         goto error;
00347     }
00348     if (cur_sample_rate != fAdaptedSampleRate) {
00349         jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
00350     }
00351 
00352     fInputBufferSize = 0;
00353     if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) {
00354         jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00355         goto error;
00356     }
00357 
00358     if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) {
00359        if (fIgnoreHW) {
00360            jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize);
00361        } else {
00362            jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
00363            goto error;
00364        }
00365     }
00366 
00367     fInputBuffer = (void*)calloc(fInputBufferSize, 1);
00368     assert(fInputBuffer);
00369 
00370     fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*));
00371     assert(fInputSampleBuffer);
00372 
00373     for (int i = 0; i < fCaptureChannels; i++) {
00374         fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
00375         assert(fInputSampleBuffer[i]);
00376     }
00377     return 0;
00378 
00379 error:
00380     ::close(fInFD);
00381     return -1;
00382 }
00383 
00384 int JackOSSAdapter::OpenOutput()
00385 {
00386     int flags = 0;
00387     int gFragFormat;
00388     int cur_sample_format, cur_playback_channels;
00389     jack_nframes_t cur_sample_rate;
00390 
00391     if (fPlaybackChannels == 0) fPlaybackChannels = 2;
00392 
00393     if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
00394        jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00395        return -1;
00396     }
00397 
00398     if (fExcl) {
00399         if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
00400             jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00401             goto error;
00402         }
00403     }
00404 
00405     gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
00406     if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
00407         jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00408         goto error;
00409     }
00410 
00411     cur_sample_format = fSampleFormat;
00412     if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
00413         jack_error("JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00414         goto error;
00415     }
00416     if (cur_sample_format != fSampleFormat) {
00417         jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat);
00418     }
00419 
00420     cur_playback_channels = fPlaybackChannels;
00421     if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
00422         jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00423         goto error;
00424     }
00425     if (cur_playback_channels != fPlaybackChannels) {
00426         jack_info("JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels);
00427     }
00428 
00429     cur_sample_rate = fAdaptedSampleRate;
00430     if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
00431         jack_error("JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00432         goto error;
00433     }
00434     if (cur_sample_rate != fAdaptedSampleRate) {
00435         jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate);
00436     }
00437 
00438     fOutputBufferSize = 0;
00439     if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) {
00440         jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00441         goto error;
00442     }
00443 
00444     if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) {
00445        if (fIgnoreHW) {
00446            jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize);
00447        } else {
00448            jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained");
00449            goto error;
00450        }
00451     }
00452 
00453     fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
00454     assert(fOutputBuffer);
00455 
00456     fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*));
00457     assert(fOutputSampleBuffer);
00458 
00459     for (int i = 0; i < fPlaybackChannels; i++) {
00460         fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
00461         assert(fOutputSampleBuffer[i]);
00462     }
00463 
00464     fFirstCycle = true;
00465     return 0;
00466 
00467 error:
00468     ::close(fOutFD);
00469     return -1;
00470 }
00471 
00472 int JackOSSAdapter::Open()
00473 {
00474     SetSampleFormat();
00475 
00476     if ((fRWMode & kRead) && (OpenInput() < 0)) {
00477         return -1;
00478     }
00479 
00480     if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
00481        return -1;
00482     }
00483 
00484     // In duplex mode, check that input and output use the same buffer size
00485     if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
00486        jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!");
00487        goto error;
00488     }
00489 
00490     DisplayDeviceInfo();
00491 
00492     //start adapter thread
00493     if (fThread.StartSync() < 0) {
00494         jack_error ( "Cannot start audioadapter thread" );
00495         return -1;
00496     }
00497 
00498     //turn the thread realtime
00499     fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority);
00500     return 0;
00501 
00502 error:
00503     CloseAux();
00504     return -1;
00505 }
00506 
00507 
00508 int JackOSSAdapter::Close()
00509 {
00510 #ifdef JACK_MONITOR
00511     fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
00512 #endif
00513     fThread.Stop();
00514     CloseAux();
00515     return 0;
00516 }
00517 
00518 void JackOSSAdapter::CloseAux()
00519 {
00520     if (fRWMode & kRead) {
00521         close(fInFD);
00522         fInFD = -1;
00523     }
00524 
00525     if (fRWMode & kWrite) {
00526         close(fOutFD);
00527         fOutFD = -1;
00528     }
00529 
00530     free(fInputBuffer);
00531     fInputBuffer = NULL;
00532 
00533     free(fOutputBuffer);
00534     fOutputBuffer = NULL;
00535 
00536     for (int i = 0; i < fCaptureChannels; i++) {
00537         free(fInputSampleBuffer[i]);
00538     }
00539     free(fInputSampleBuffer);
00540 
00541     for (int i = 0; i < fPlaybackChannels; i++) {
00542         free(fOutputSampleBuffer[i]);
00543     }
00544     free(fOutputSampleBuffer);
00545  }
00546 
00547 int JackOSSAdapter::Read()
00548 {
00549     ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
00550 
00551     if (count < fInputBufferSize) {
00552         jack_error("JackOSSAdapter::Read error bytes read = %ld", count);
00553         return -1;
00554     } else {
00555         for (int i = 0; i < fCaptureChannels; i++) {
00556              CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
00557         }
00558         return 0;
00559     }
00560 }
00561 
00562 int JackOSSAdapter::Write()
00563 {
00564     ssize_t count;
00565 
00566     // Maybe necessay to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
00567     if (fFirstCycle) {
00568 
00569         fFirstCycle = false;
00570         memset(fOutputBuffer, 0, fOutputBufferSize);
00571 
00572         // Prefill ouput buffer
00573         for (int i = 0; i < fNperiods; i++) {
00574            count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
00575            if (count < fOutputBufferSize) {
00576                 jack_error("JackOSSDriver::Write error bytes written = %ld", count);
00577                 return -1;
00578             }
00579         }
00580 
00581         int delay;
00582         if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
00583             jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
00584             return -1;
00585         }
00586 
00587         delay /= fSampleSize * fPlaybackChannels;
00588         jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
00589     }
00590 
00591     for (int i = 0; i < fPlaybackChannels; i++) {
00592         CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits);
00593     }
00594 
00595     count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
00596 
00597     if (count < fOutputBufferSize) {
00598         jack_error("JackOSSAdapter::Write error bytes written = %ld", count);
00599         return -1;
00600     } else {
00601         return 0;
00602     }
00603 }
00604 
00605 bool JackOSSAdapter::Execute()
00606 {
00607     //read data from audio interface
00608     if (Read() < 0)
00609         return false;
00610 
00611     PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize);
00612 
00613     //write data to audio interface
00614     if (Write() < 0)
00615         return false;
00616 
00617     return true;
00618 }
00619 
00620 int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size)
00621 {
00622     JackAudioAdapterInterface::SetBufferSize(buffer_size);
00623     Close();
00624     return Open();
00625 }
00626 
00627 } // namespace
00628 
00629 #ifdef __cplusplus
00630 extern "C"
00631 {
00632 #endif
00633 
00634     SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00635     {
00636         jack_driver_desc_t * desc;
00637         jack_driver_desc_filler_t filler;
00638         jack_driver_param_value_t value;
00639 
00640         desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
00641 
00642         value.ui = OSS_DRIVER_DEF_FS;
00643         jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00644 
00645         value.ui = OSS_DRIVER_DEF_BLKSIZE;
00646         jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
00647 
00648         value.ui = OSS_DRIVER_DEF_NPERIODS;
00649         jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
00650 
00651         value.i = OSS_DRIVER_DEF_BITS;
00652         jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
00653 
00654         value.ui = OSS_DRIVER_DEF_INS;
00655         jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
00656 
00657         value.ui = OSS_DRIVER_DEF_OUTS;
00658         jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
00659 
00660         value.i  = false;
00661         jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
00662 
00663         strcpy(value.str, OSS_DRIVER_DEF_DEV);
00664         jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
00665         jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
00666         jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
00667 
00668         value.i  = true;
00669         jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
00670 
00671         value.ui  = 0;
00672         jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
00673 
00674         value.i = 32768;
00675         jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
00676 
00677         return desc;
00678     }
00679 
00680 #ifdef __cplusplus
00681 }
00682 #endif
00683