JackASIODriver.cpp

00001 /*
00002 Copyright (C) 2006 Grame
00003 
00004 Portable Audio I/O Library for ASIO Drivers
00005 Author: Stephane Letz
00006 Based on the Open Source API proposed by Ross Bencina
00007 Copyright (c) 2000-2002 Stephane Letz, Phil Burk, Ross Bencina
00008 
00009 This program is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2 of the License, or
00012 (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 
00023 */
00024 
00025 #include "pa_asio.h"
00026 #include "JackDriverLoader.h"
00027 #include "driver_interface.h"
00028 
00029 #include "JackASIODriver.h"
00030 #include "JackEngineControl.h"
00031 #include "JackGraphManager.h"
00032 #include "JackError.h"
00033 #include "JackClientControl.h"
00034 #include "JackGlobals.h"
00035 #include <iostream>
00036 
00037 
00038 #include <windows.h>
00039 #include <mmsystem.h>
00040 
00041 #include "asiosys.h"
00042 #include "asio.h"
00043 #include "asiodrivers.h"
00044 #include "iasiothiscallresolver.h"
00045 
00046 
00047 /* external references */
00048 extern AsioDrivers* asioDrivers ;
00049 bool loadAsioDriver(char *name);
00050 
00051 
00052 namespace Jack
00053 {
00054 
00055 
00056 /*
00057     load the asio driver named by <driverName> and return statistics about
00058     the driver in info. If no error occurred, the driver will remain open
00059     and must be closed by the called by calling ASIOExit() - if an error
00060     is returned the driver will already be closed.
00061 */
00062 static PaError LoadAsioDriver( const char *driverName,
00063         PaAsioDriverInfo *driverInfo, void *systemSpecific )
00064 {
00065     PaError result = paNoError;
00066     ASIOError asioError;
00067     int asioIsInitialized = 0;
00068 
00069     if( !loadAsioDriver(const_cast<char*>(driverName)))
00070     {
00071         result = paUnanticipatedHostError;
00072         PA_ASIO_SET_LAST_HOST_ERROR( 0, "Failed to load ASIO driver" );
00073         goto error;
00074     }
00075 
00076     memset( &driverInfo->asioDriverInfo, 0, sizeof(ASIODriverInfo) );
00077     driverInfo->asioDriverInfo.asioVersion = 2;
00078     driverInfo->asioDriverInfo.sysRef = systemSpecific;
00079     if( (asioError = ASIOInit( &driverInfo->asioDriverInfo )) != ASE_OK )
00080     {
00081         result = paUnanticipatedHostError;
00082         PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
00083         goto error;
00084     }
00085     else
00086     {
00087         asioIsInitialized = 1;
00088     }
00089 
00090     if( (asioError = ASIOGetChannels(&driverInfo->inputChannelCount,
00091             &driverInfo->outputChannelCount)) != ASE_OK )
00092     {
00093         result = paUnanticipatedHostError;
00094         PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
00095         goto error;
00096     }
00097 
00098     if( (asioError = ASIOGetBufferSize(&driverInfo->bufferMinSize,
00099             &driverInfo->bufferMaxSize, &driverInfo->bufferPreferredSize,
00100             &driverInfo->bufferGranularity)) != ASE_OK )
00101     {
00102         result = paUnanticipatedHostError;
00103         PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
00104         goto error;
00105     }
00106 
00107     if( ASIOOutputReady() == ASE_OK )
00108         driverInfo->postOutput = true;
00109     else
00110         driverInfo->postOutput = false;
00111 
00112     return result;
00113 
00114 error:
00115     if( asioIsInitialized )
00116         ASIOExit();
00117 
00118     return result;
00119 }
00120 
00121 
00122 int JackASIODriver::bufferSwitch(long index, ASIOBool directProcess)
00123 {
00124     JackASIODriver* driver = (JackASIODriver*)userData;
00125         
00126         // the actual processing callback.
00127     // Beware that this is normally in a seperate thread, hence be sure that
00128     // you take care about thread synchronization. This is omitted here for
00129     // simplicity.
00130 
00131     // as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs
00132     // to be created though it will only set the timeInfo.samplePosition and
00133     // timeInfo.systemTime fields and the according flags
00134 
00135     ASIOTime  timeInfo;
00136     memset(&timeInfo, 0, sizeof(timeInfo));
00137 
00138     // get the time stamp of the buffer, not necessary if no
00139     // synchronization to other media is required
00140     if( ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
00141             timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
00142         
00143         
00144     driver->fLastWaitUst = GetMicroSeconds(); // Take callback date here
00145         driver->fInputBuffer = (float**)inputBuffer;
00146         driver->fOutputBuffer = (float**)outputBuffer;
00147         
00148          // Call the real callback
00149     bufferSwitchTimeInfo( &timeInfo, index, directProcess );
00150         
00151         return driver->Process();
00152 }
00153 
00154 int JackASIODriver::Read()
00155 {
00156         return 0;
00157 }
00158 
00159 int JackASIODriver::Write()
00160 {
00161     return 0;
00162 }
00163 
00164 
00165 int JackASIODriver::Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
00166 {
00167     PaError result = paNoError;
00168     int i, driverCount;
00169     PaAsioHostApiRepresentation *asioHostApi;
00170     PaAsioDeviceInfo *deviceInfoArray;
00171     char **names;
00172     PaAsioDriverInfo paAsioDriverInfo;
00173 
00174     asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) );
00175     if( !asioHostApi )
00176     {
00177         result = paInsufficientMemory;
00178         goto error;
00179     }
00180 
00181     asioHostApi->allocations = PaUtil_CreateAllocationGroup();
00182     if( !asioHostApi->allocations )
00183     {
00184         result = paInsufficientMemory;
00185         goto error;
00186     }
00187 
00188     asioHostApi->systemSpecific = 0;
00189     asioHostApi->openAsioDeviceIndex = paNoDevice;
00190 
00191     *hostApi = &asioHostApi->inheritedHostApiRep;
00192     (*hostApi)->info.structVersion = 1;
00193 
00194     (*hostApi)->info.type = paASIO;
00195     (*hostApi)->info.name = "ASIO";
00196     (*hostApi)->info.deviceCount = 0;
00197 
00198     #ifdef WINDOWS
00199         /* use desktop window as system specific ptr */
00200         asioHostApi->systemSpecific = GetDesktopWindow();
00201         CoInitialize(NULL);
00202     #endif
00203 
00204     /* MUST BE CHECKED : to force fragments loading on Mac */
00205     loadAsioDriver( "dummy" ); 
00206 
00207     /* driverCount is the number of installed drivers - not necessarily
00208         the number of installed physical devices. */
00209     #if MAC
00210         driverCount = asioDrivers->getNumFragments();
00211     #elif WINDOWS
00212         driverCount = asioDrivers->asioGetNumDev();
00213     #endif
00214 
00215     if( driverCount > 0 )
00216     {
00217         names = GetAsioDriverNames( asioHostApi->allocations, driverCount );
00218         if( !names )
00219         {
00220             result = paInsufficientMemory;
00221             goto error;
00222         }
00223 
00224 
00225         /* allocate enough space for all drivers, even if some aren't installed */
00226 
00227         (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
00228                 asioHostApi->allocations, sizeof(PaDeviceInfo*) * driverCount );
00229         if( !(*hostApi)->deviceInfos )
00230         {
00231             result = paInsufficientMemory;
00232             goto error;
00233         }
00234 
00235         /* allocate all device info structs in a contiguous block */
00236         deviceInfoArray = (PaAsioDeviceInfo*)PaUtil_GroupAllocateMemory(
00237                 asioHostApi->allocations, sizeof(PaAsioDeviceInfo) * driverCount );
00238         if( !deviceInfoArray )
00239         {
00240             result = paInsufficientMemory;
00241             goto error;
00242         }
00243 
00244         for( i=0; i < driverCount; ++i )
00245         {
00246 
00247             PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i]));
00248 
00249             // Since portaudio opens ALL ASIO drivers, and no one else does that,
00250             // we face fact that some drivers were not meant for it, drivers which act
00251             // like shells on top of REAL drivers, for instance.
00252             // so we get duplicate handles, locks and other problems.
00253             // so lets NOT try to load any such wrappers. 
00254             // The ones i [davidv] know of so far are:
00255 
00256             if (   strcmp (names[i],"ASIO DirectX Full Duplex Driver") == 0
00257                 || strcmp (names[i],"ASIO Multimedia Driver")          == 0
00258                 || strncmp(names[i],"Premiere",8)                      == 0   //"Premiere Elements Windows Sound 1.0"
00259                 || strncmp(names[i],"Adobe",5)                         == 0 ) //"Adobe Default Windows Sound 1.5"
00260             {
00261                 PA_DEBUG(("BLACKLISTED!!!\n"));
00262                 continue;
00263             }
00264 
00265 
00266             /* Attempt to load the asio driver... */
00267             if( LoadAsioDriver( names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
00268             {
00269                 PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
00270                 PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
00271 
00272                 deviceInfo->structVersion = 2;
00273                 deviceInfo->hostApi = hostApiIndex;
00274 
00275                 deviceInfo->name = names[i];
00276                 PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n",  i,deviceInfo->name));
00277                 PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels       = %d\n", i, paAsioDriverInfo.inputChannelCount));
00278                 PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels      = %d\n", i, paAsioDriverInfo.outputChannelCount));
00279                 PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize       = %d\n", i, paAsioDriverInfo.bufferMinSize));
00280                 PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize       = %d\n", i, paAsioDriverInfo.bufferMaxSize));
00281                 PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize));
00282                 PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity   = %d\n", i, paAsioDriverInfo.bufferGranularity));
00283 
00284                 deviceInfo->maxInputChannels  = paAsioDriverInfo.inputChannelCount;
00285                 deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount;
00286 
00287                 deviceInfo->defaultSampleRate = 0.;
00288                 bool foundDefaultSampleRate = false;
00289                 for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
00290                 {
00291                     ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
00292                     if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
00293                     {
00294                         deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
00295                         foundDefaultSampleRate = true;
00296                         break;
00297                     }
00298                 }
00299 
00300                 PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", i, deviceInfo->defaultSampleRate));
00301 
00302                 if( foundDefaultSampleRate ){
00303 
00304                     /* calculate default latency values from bufferPreferredSize
00305                         for default low latency, and bufferPreferredSize * 3
00306                         for default high latency.
00307                         use the default sample rate to convert from samples to
00308                         seconds. Without knowing what sample rate the user will
00309                         use this is the best we can do.
00310                     */
00311 
00312                     double defaultLowLatency =
00313                             paAsioDriverInfo.bufferPreferredSize / deviceInfo->defaultSampleRate;
00314 
00315                     deviceInfo->defaultLowInputLatency = defaultLowLatency;
00316                     deviceInfo->defaultLowOutputLatency = defaultLowLatency;
00317 
00318                     long defaultHighLatencyBufferSize =
00319                             paAsioDriverInfo.bufferPreferredSize * 3;
00320 
00321                     if( defaultHighLatencyBufferSize > paAsioDriverInfo.bufferMaxSize )
00322                         defaultHighLatencyBufferSize = paAsioDriverInfo.bufferMaxSize;
00323 
00324                     double defaultHighLatency =
00325                             defaultHighLatencyBufferSize / deviceInfo->defaultSampleRate;
00326 
00327                     if( defaultHighLatency < defaultLowLatency )
00328                         defaultHighLatency = defaultLowLatency; /* just incase the driver returns something strange */ 
00329                             
00330                     deviceInfo->defaultHighInputLatency = defaultHighLatency;
00331                     deviceInfo->defaultHighOutputLatency = defaultHighLatency;
00332                     
00333                 }else{
00334 
00335                     deviceInfo->defaultLowInputLatency = 0.;
00336                     deviceInfo->defaultLowOutputLatency = 0.;
00337                     deviceInfo->defaultHighInputLatency = 0.;
00338                     deviceInfo->defaultHighOutputLatency = 0.;
00339                 }
00340 
00341                 PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowInputLatency = %f\n", i, deviceInfo->defaultLowInputLatency));
00342                 PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowOutputLatency = %f\n", i, deviceInfo->defaultLowOutputLatency));
00343                 PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", i, deviceInfo->defaultHighInputLatency));
00344                 PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", i, deviceInfo->defaultHighOutputLatency));
00345 
00346                 asioDeviceInfo->minBufferSize = paAsioDriverInfo.bufferMinSize;
00347                 asioDeviceInfo->maxBufferSize = paAsioDriverInfo.bufferMaxSize;
00348                 asioDeviceInfo->preferredBufferSize = paAsioDriverInfo.bufferPreferredSize;
00349                 asioDeviceInfo->bufferGranularity = paAsioDriverInfo.bufferGranularity;
00350 
00351 
00352                 asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory(
00353                         asioHostApi->allocations,
00354                         sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels
00355                                 + deviceInfo->maxOutputChannels) );
00356                 if( !asioDeviceInfo->asioChannelInfos )
00357                 {
00358                     result = paInsufficientMemory;
00359                     goto error;
00360                 }
00361 
00362                 int a;
00363 
00364                 for( a=0; a < deviceInfo->maxInputChannels; ++a ){
00365                     asioDeviceInfo->asioChannelInfos[a].channel = a;
00366                     asioDeviceInfo->asioChannelInfos[a].isInput = ASIOTrue;
00367                     ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[a] );
00368                     if( asioError != ASE_OK )
00369                     {
00370                         result = paUnanticipatedHostError;
00371                         PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
00372                         goto error;
00373                     }
00374                 }
00375 
00376                 for( a=0; a < deviceInfo->maxOutputChannels; ++a ){
00377                     int b = deviceInfo->maxInputChannels + a;
00378                     asioDeviceInfo->asioChannelInfos[b].channel = a;
00379                     asioDeviceInfo->asioChannelInfos[b].isInput = ASIOFalse;
00380                     ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[b] );
00381                     if( asioError != ASE_OK )
00382                     {
00383                         result = paUnanticipatedHostError;
00384                         PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
00385                         goto error;
00386                     }
00387                 }
00388 
00389 
00390                 /* unload the driver */
00391                 ASIOExit();
00392 
00393                 (*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
00394                 ++(*hostApi)->info.deviceCount;
00395             }
00396         }
00397     }
00398 
00399     if( (*hostApi)->info.deviceCount > 0 )
00400     {
00401         (*hostApi)->info.defaultInputDevice = 0;
00402         (*hostApi)->info.defaultOutputDevice = 0;
00403     }
00404     else
00405     {
00406         (*hostApi)->info.defaultInputDevice = paNoDevice;
00407         (*hostApi)->info.defaultOutputDevice = paNoDevice;
00408     }
00409 
00410 
00411     (*hostApi)->Terminate = Terminate;
00412     (*hostApi)->OpenStream = OpenStream;
00413     (*hostApi)->IsFormatSupported = IsFormatSupported;
00414 
00415     PaUtil_InitializeStreamInterface( &asioHostApi->callbackStreamInterface, CloseStream, StartStream,
00416                                       StopStream, AbortStream, IsStreamStopped, IsStreamActive,
00417                                       GetStreamTime, GetStreamCpuLoad,
00418                                       PaUtil_DummyRead, PaUtil_DummyWrite,
00419                                       PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
00420 
00421     PaUtil_InitializeStreamInterface( &asioHostApi->blockingStreamInterface, CloseStream, StartStream,
00422                                       StopStream, AbortStream, IsStreamStopped, IsStreamActive,
00423                                       GetStreamTime, PaUtil_DummyGetCpuLoad,
00424                                       ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
00425 
00426     return result;
00427 
00428 error:
00429     if( asioHostApi )
00430     {
00431         if( asioHostApi->allocations )
00432         {
00433             PaUtil_FreeAllAllocations( asioHostApi->allocations );
00434             PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
00435         }
00436 
00437         PaUtil_FreeMemory( asioHostApi );
00438     }
00439     return result;
00440 }
00441 
00442 
00443 
00444 void JackASIODriverTerminate( struct PaUtilHostApiRepresentation *hostApi )
00445 {
00446     PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*)hostApi;
00447 
00448     /*
00449         IMPLEMENT ME:
00450             - clean up any resources not handled by the allocation group
00451     */
00452 
00453     if( asioHostApi->allocations )
00454     {
00455         PaUtil_FreeAllAllocations( asioHostApi->allocations );
00456         PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
00457     }
00458 
00459     PaUtil_FreeMemory( asioHostApi );
00460 }
00461 
00462 
00463 int JackASIODriver::Open(jack_nframes_t nframes,
00464                               jack_nframes_t samplerate,
00465                               int capturing,
00466                               int playing,
00467                               int inchannels,
00468                               int outchannels,
00469                                                           bool monitor,
00470                               const char* capture_driver_uid,
00471                                                           const char* playback_driver_uid,
00472                                                           jack_nframes_t capture_latency,
00473                                                           jack_nframes_t playback_latency)
00474 {
00475         return 0;
00476 
00477 error:
00478    return -1;
00479 }
00480 
00481 int JackASIODriver::Close()
00482 {
00483         return 0;
00484 }
00485 
00486 int JackASIODriver::Start()
00487 {
00488     JackLog("JackASIODriver::Start\n");
00489         return 0;
00490 }
00491 
00492 int JackASIODriver::Stop()
00493 {
00494         JackLog("JackASIODriver::Stop\n");
00495     return 0;
00496 }
00497 
00498 int JackASIODriver::SetBufferSize(jack_nframes_t nframes)
00499 {
00500         return 0;
00501 }
00502 
00503 void JackASIODriver::PrintState()
00504 {
00505         int i;
00506     std::cout << "JackASIODriver state" << std::endl;
00507 
00508     jack_port_id_t port_index;
00509 
00510     std::cout << "Input ports" << std::endl;
00511 
00512         /*
00513     for (i = 0; i < fPlaybackChannels; i++) {
00514         port_index = fCapturePortList[i];
00515         JackPort* port = fGraphManager->GetPort(port_index);
00516         std::cout << port->GetName() << std::endl;
00517         if (fGraphManager->GetConnectionsNum(port_index)) {}
00518     }
00519 
00520     std::cout << "Output ports" << std::endl;
00521 
00522     for (i = 0; i < fCaptureChannels; i++) {
00523         port_index = fPlaybackPortList[i];
00524         JackPort* port = fGraphManager->GetPort(port_index);
00525         std::cout << port->GetName() << std::endl;
00526         if (fGraphManager->GetConnectionsNum(port_index)) {}
00527     }
00528         */
00529 }
00530 
00531 } // end of namespace
00532 
00533 #ifdef __cplusplus
00534 extern "C"
00535 {
00536 #endif
00537 
00538 #include "JackExports.h"
00539 
00540     EXPORT jack_driver_desc_t* driver_get_descriptor() {
00541         jack_driver_desc_t *desc;
00542         unsigned int i;
00543         desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00544 
00545         strcpy(desc->name, "ASIO");
00546 
00547         desc->nparams = 13;
00548         desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00549 
00550         i = 0;
00551         strcpy(desc->params[i].name, "channels");
00552         desc->params[i].character = 'c';
00553         desc->params[i].type = JackDriverParamInt;
00554         desc->params[i].value.ui = 0;
00555         strcpy(desc->params[i].short_desc, "Maximum number of channels");
00556         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00557 
00558         i++;
00559         strcpy(desc->params[i].name, "inchannels");
00560         desc->params[i].character = 'i';
00561         desc->params[i].type = JackDriverParamInt;
00562         desc->params[i].value.ui = 0;
00563         strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00564         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00565 
00566         i++;
00567         strcpy(desc->params[i].name, "outchannels");
00568         desc->params[i].character = 'o';
00569         desc->params[i].type = JackDriverParamInt;
00570         desc->params[i].value.ui = 0;
00571         strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00572         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00573 
00574         i++;
00575         strcpy(desc->params[i].name, "capture");
00576         desc->params[i].character = 'C';
00577         desc->params[i].type = JackDriverParamString;
00578         strcpy(desc->params[i].value.str, "will take default PortAudio input device");
00579         strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00580         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00581 
00582         i++;
00583         strcpy(desc->params[i].name, "playback");
00584         desc->params[i].character = 'P';
00585         desc->params[i].type = JackDriverParamString;
00586         strcpy(desc->params[i].value.str, "will take default PortAudio output device");
00587         strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00588         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00589                 
00590                 i++;
00591         strcpy (desc->params[i].name, "monitor");
00592         desc->params[i].character = 'm';
00593         desc->params[i].type = JackDriverParamBool;
00594         desc->params[i].value.i = 0;
00595         strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
00596         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00597 
00598         i++;
00599         strcpy(desc->params[i].name, "duplex");
00600         desc->params[i].character = 'D';
00601         desc->params[i].type = JackDriverParamBool;
00602         desc->params[i].value.i = TRUE;
00603         strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
00604         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00605 
00606         i++;
00607         strcpy(desc->params[i].name, "rate");
00608         desc->params[i].character = 'r';
00609         desc->params[i].type = JackDriverParamUInt;
00610         desc->params[i].value.ui = 44100U;
00611         strcpy(desc->params[i].short_desc, "Sample rate");
00612         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00613 
00614         i++;
00615         strcpy(desc->params[i].name, "period");
00616         desc->params[i].character = 'p';
00617         desc->params[i].type = JackDriverParamUInt;
00618         desc->params[i].value.ui = 128U;
00619         strcpy(desc->params[i].short_desc, "Frames per period");
00620         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00621 
00622         i++;
00623         strcpy(desc->params[i].name, "device");
00624         desc->params[i].character = 'd';
00625         desc->params[i].type = JackDriverParamString;
00626         desc->params[i].value.ui = 128U;
00627                 strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
00628         strcpy(desc->params[i].short_desc, "CoreAudio device name");
00629         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00630 
00631         i++;
00632         strcpy(desc->params[i].name, "input-latency");
00633         desc->params[i].character = 'I';
00634         desc->params[i].type = JackDriverParamUInt;
00635         desc->params[i].value.i = 0;
00636         strcpy(desc->params[i].short_desc, "Extra input latency");
00637         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00638 
00639         i++;
00640         strcpy(desc->params[i].name, "output-latency");
00641         desc->params[i].character = 'O';
00642         desc->params[i].type = JackDriverParamUInt;
00643         desc->params[i].value.i = 0;
00644         strcpy(desc->params[i].short_desc, "Extra output latency");
00645         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00646                 
00647                 i++;
00648                 strcpy(desc->params[i].name, "list-devices");
00649                 desc->params[i].character  = 'l';
00650                 desc->params[i].type = JackDriverParamBool;
00651                 desc->params[i].value.i  = TRUE;
00652                 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
00653                 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00654 
00655         return desc;
00656     }
00657 
00658     EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackEngine* engine, Jack::JackSynchro** table, const JSList* params) 
00659         {
00660         jack_nframes_t srate = 44100;
00661         jack_nframes_t frames_per_interrupt = 512;
00662         int capture = FALSE;
00663         int playback = FALSE;
00664         int chan_in = 0;
00665         int chan_out = 0;
00666                 bool monitor = false;   
00667         char* capture_pcm_name = "";
00668                 char* playback_pcm_name = "";
00669         const JSList *node;
00670         const jack_driver_param_t *param;
00671         jack_nframes_t systemic_input_latency = 0;
00672         jack_nframes_t systemic_output_latency = 0;
00673 
00674                 for (node = params; node; node = jack_slist_next(node)) {
00675             param = (const jack_driver_param_t *) node->data;
00676 
00677             switch (param->character) {
00678 
00679                 case 'd':
00680                     capture_pcm_name = strdup(param->value.str);
00681                                         playback_pcm_name = strdup(param->value.str);
00682                     break;
00683 
00684                 case 'D':
00685                     capture = TRUE;
00686                     playback = TRUE;
00687                     break;
00688 
00689                 case 'c':
00690                     chan_in = chan_out = (int) param->value.ui;
00691                     break;
00692 
00693                 case 'i':
00694                     chan_in = (int) param->value.ui;
00695                     break;
00696 
00697                 case 'o':
00698                     chan_out = (int) param->value.ui;
00699                     break;
00700 
00701                 case 'C':
00702                                         capture = TRUE;
00703                                         if (strcmp(param->value.str, "none") != 0) {
00704                         capture_pcm_name = strdup(param->value.str);
00705                     }
00706                     break;
00707 
00708                 case 'P':
00709                                         playback = TRUE;
00710                                         if (strcmp(param->value.str, "none") != 0) {
00711                         playback_pcm_name = strdup(param->value.str);
00712                     }
00713                     break;
00714                                 
00715                                 case 'm':
00716                     monitor = param->value.i;
00717                     break;
00718 
00719                 case 'r':
00720                     srate = param->value.ui;
00721                     break;
00722 
00723                 case 'p':
00724                     frames_per_interrupt = (unsigned int) param->value.ui;
00725                     break;
00726 
00727                 case 'I':
00728                     systemic_input_latency = param->value.ui;
00729                     break;
00730 
00731                 case 'O':
00732                     systemic_output_latency = param->value.ui;
00733                     break;
00734                                 
00735                                 case 'l':
00736                                         Jack::DisplayDeviceNames();
00737                                         break;
00738             }
00739         }
00740 
00741         // duplex is the default 
00742         if (!capture && !playback) {
00743             capture = TRUE;
00744             playback = TRUE;
00745         }
00746 
00747         Jack::JackDriverClientInterface* driver = new Jack::JackASIODriver("ASIO", engine, table);
00748                 if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency) == 0) {
00749                         return driver;
00750         } else {
00751             delete driver;
00752             return NULL;
00753         }
00754     }
00755 
00756 #ifdef __cplusplus
00757 }
00758 #endif

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1