//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// /* This should work for OS/2 Dart History: 1.0 - By Kevin Langman */ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #define INCL_DOS #include #include #include #include #include "xmpi.h" #include "driver.h" #include "mixer.h" #define BUFFERCOUNT 4 #define BUF_MIN 8 #define BUF_MAX 32 static int init (struct xmp_control *); static int setaudio (struct xmp_control *); static void bufdump (int); static void shutdown (void); static MCI_MIX_BUFFER MixBuffers[BUFFERCOUNT]; static MCI_MIXSETUP_PARMS MixSetupParms; static MCI_BUFFER_PARMS BufferParms; static MCI_GENERIC_PARMS GenericParms; static ULONG DeviceID = 0; static int bsize = 16; static short next = 2; static short ready = 1; static HMTX mutex; static void dummy () { } static char *help[] = { "sharing={Y,N}", "Device Sharing (default is N)", "device=val", "OS/2 Audio Device (default is 0 auto-detect)", "buffer=val", "Audio buffer size (default is 16)", NULL }; struct xmp_drv_info drv_os2dart = { "dart", /* driver ID */ "OS/2 Direct Audio Realtime", /* driver description */ help, /* help */ init, /* init */ shutdown, /* shutdown */ xmp_smix_numvoices, /* numvoices */ dummy, /* voicepos */ xmp_smix_echoback, /* echoback */ dummy, /* setpatch */ xmp_smix_setvol, /* setvol */ dummy, /* setnote */ xmp_smix_setpan, /* setpan */ dummy, /* setbend */ xmp_smix_seteffect, /* seteffect */ dummy, /* starttimer */ dummy, /* stctlimer */ dummy, /* reset */ bufdump, /* bufdump */ dummy, /* bufwipe */ dummy, /* clearmem */ dummy, /* sync */ xmp_smix_writepatch,/* writepatch */ xmp_smix_getmsg, /* getmsg */ NULL }; // Buffer update thread (created and called by DART) static LONG APIENTRY OS2_Dart_UpdateBuffers (ULONG ulStatus,PMCI_MIX_BUFFER pBuffer,ULONG ulFlags) { if((ulFlags==MIX_WRITE_COMPLETE)|| ((ulFlags==(MIX_WRITE_COMPLETE|MIX_STREAM_ERROR))&& (ulStatus==ERROR_DEVICE_UNDERRUN))) { DosRequestMutexSem(mutex,SEM_INDEFINITE_WAIT); ready++; DosReleaseMutexSem(mutex); } return(TRUE); } static int setaudio (struct xmp_control *ctl) { char sharing = 0; int device = 0; int flags; int i; MCI_AMP_OPEN_PARMS AmpOpenParms; char *token; char **parm = ctl->parm; //printf( "In SetAudio...\n" ); parm_init (); chkparm1 ("sharing", sharing = *token ); chkparm1 ("device", device = atoi (token)); chkparm1 ("buffer", bsize = atoi (token)); parm_end (); if( (bsize < BUF_MIN || bsize > BUF_MAX) && bsize != 0 ){ bsize = 16 * 1024; }else{ bsize *=1024; } // if( sharing < 1 || sharing > 0 ){ // sharing = 0; // } MixBuffers[0].pBuffer=NULL; /* marker */ memset(&GenericParms,0,sizeof(MCI_GENERIC_PARMS)); /* open AMP device */ memset(&AmpOpenParms,0,sizeof(MCI_AMP_OPEN_PARMS)); AmpOpenParms.usDeviceID=0; AmpOpenParms.pszDeviceType = (PSZ) MAKEULONG( MCI_DEVTYPE_AUDIO_AMPMIX, (USHORT)device ); flags = MCI_WAIT|MCI_OPEN_TYPE_ID; if( sharing == 'Y' || sharing== 'y' ){ flags = flags | MCI_OPEN_SHAREABLE; } if(mciSendCommand(0,MCI_OPEN, flags, (PVOID)&AmpOpenParms,0)!=MCIERR_SUCCESS) { return -1; } DeviceID=AmpOpenParms.usDeviceID; /* setup playback parameters */ memset(&MixSetupParms,0,sizeof(MCI_MIXSETUP_PARMS)); MixSetupParms.ulBitsPerSample = ctl->resol; MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; MixSetupParms.ulSamplesPerSec = ctl->freq; MixSetupParms.ulChannels = ctl->outfmt & XMP_FMT_MONO?1:2; MixSetupParms.ulFormatMode = MCI_PLAY; MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; MixSetupParms.pmixEvent = OS2_Dart_UpdateBuffers; if(mciSendCommand(DeviceID,MCI_MIXSETUP, MCI_WAIT|MCI_MIXSETUP_INIT, (PVOID)&MixSetupParms,0)!=MCIERR_SUCCESS) { mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0); return -1; } /* take in account the DART suggested buffer size... */ if( bsize == 0 ){ bsize=MixSetupParms.ulBufferSize; } //printf( "Dart Buffer Size = %d\n", bsize ); BufferParms.ulNumBuffers=BUFFERCOUNT; BufferParms.ulBufferSize=bsize; BufferParms.pBufList=MixBuffers; if(mciSendCommand(DeviceID,MCI_BUFFER, MCI_WAIT|MCI_ALLOCATE_MEMORY, (PVOID)&BufferParms,0)!=MCIERR_SUCCESS) { mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0); return -1; } for( i=0 ; i bsize ){ //printf("Next = %d, ready = %d\n", next, ready); do{ DosRequestMutexSem(mutex,SEM_INDEFINITE_WAIT); if( ready!=0){ DosReleaseMutexSem(mutex); break; } DosReleaseMutexSem(mutex); DosSleep(20); }while(TRUE); MixBuffers[next].ulBufferLength = index; MixSetupParms.pmixWrite( MixSetupParms.ulMixHandle, &(MixBuffers[next]),1); ready--; next++; index = 0; if( next == BUFFERCOUNT ){ next=0; } } memcpy( &((char*)MixBuffers[next].pBuffer)[index], b, i ); index += i; } static void shutdown () { //printf( "In ShutDown...\n" ); xmp_smix_off (); if(MixBuffers[0].pBuffer) { mciSendCommand(DeviceID,MCI_BUFFER,MCI_WAIT|MCI_DEALLOCATE_MEMORY, &BufferParms,0); MixBuffers[0].pBuffer=NULL; } if (DeviceID) { mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0); DeviceID=0; } }