static void MciError(ULONG ulError) { unsigned char buffer[128]; ULONG rc; rc = mciGetErrorString(ulError, buffer, sizeof(buffer)); if (rc == MCIERR_SUCCESS) sprintf(mmerror,"MCI Error %d: %s",ULONG_LOWD(ulError),buffer); else sprintf(mmerror,"MCI Error %d: Cannot query error message.",ULONG_LOWD(rc)); error1("%s",mmerror); }
static int write_os2(audio_output_t *ao,unsigned char *buf,int len) { if(len > audiobufsize || !playingbuffer) return -1; if(mmp.ulBitsPerSample == 16) ao->format = MPG123_ENC_SIGNED_16; else if(mmp.ulBitsPerSample == 8) ao->format = MPG123_ENC_UNSIGNED_8; else return -1; ao->rate = mmp.ulSamplesPerSec; ao->channels = mmp.ulChannels; if(buf && len) { ULONG rc; int upto; mstatp.ulItem = MCI_STATUS_POSITION; rc = mciSendCommand( maop.usDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, &mstatp, 0 ); if ( ULONG_LOWD(rc) != MCIERR_SUCCESS ) { MciError(rc); maop.usDeviceID = 0; return(-1); } /* this is hypocrite... DART returns the value in ulReturn instead of ulValue, also it returns in milliseconds and not MMTIME... arg */ upto = (mstatp.ulReturn-playedbuffer.ulTime) * mmp.ulSamplesPerSec / 1000; upto *= mmp.ulChannels * (mmp.ulBitsPerSample>>3); /* if a timing problem occurs, let's at least not crash */ if(upto > playingbuffer->ulBufferLength) upto = playingbuffer->ulBufferLength; if(len < upto) { memcpy(buf,(char *) (playingbuffer->pBuffer)+upto-len, len); } else { memcpy(buf,(char *) playedbuffer.pBuffer+playedbuffer.ulBufferLength-(len-upto),len-upto); memcpy(buf+(len-upto),playingbuffer->pBuffer,upto); } }
int open_os2(audio_output_t *ao) { ULONG rc,i; char *temp; ULONG openflags; PPIB ppib; USHORT bits; if(maop.usDeviceID) return (maop.usDeviceID); if(!ai) return -1; if(!ao->device) ao->device = "0"; if(ao->rate < 0) ao->rate = 44100; if(ao->channels < 0) ao->channels = 2; if(ao->format < 0) ao->format = MPG123_ENC_SIGNED_16; if(ao->format == MPG123_ENC_SIGNED_16) bits = 16; else if(ao->format == MPG123_ENC_UNSIGNED_8) bits = 8; else return -1; /* open the mixer device */ memset (&maop, 0, sizeof(maop)); maop.usDeviceID = 0; maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, atoi(ao->device)); openflags = MCI_WAIT | MCI_OPEN_TYPE_ID; if(!lockdevice) openflags |= MCI_OPEN_SHAREABLE; rc = mciSendCommand(0, MCI_OPEN, openflags, &maop, 0); if (ULONG_LOWD(rc) != MCIERR_SUCCESS) { MciError(rc); maop.usDeviceID = 0; return(-1); } /* volume in ao->gain ?? */ /* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */ memset(&mmp, 0, sizeof(mmp)); mmp.ulBitsPerSample = bits; mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM; mmp.ulSamplesPerSec = ao->rate; mmp.ulChannels = ao->channels; /* Setup the mixer for playback of wave data */ mmp.ulFormatMode = MCI_PLAY; mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; mmp.pmixEvent = DARTEvent; rc = mciSendCommand( maop.usDeviceID, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT, &mmp, 0 ); if ( ULONG_LOWD(rc) != MCIERR_SUCCESS ) { MciError(rc); maop.usDeviceID = 0; return(-1); } volume = audio_set_volume(ai,volume); /* Set up the BufferParms data structure and allocate * device buffers from the Amp-Mixer */ memset(&mbp, 0, sizeof(mbp)); free(MixBuffers); free(bufferinfo); if(numbuffers < 5) numbuffers = 5; if(numbuffers > 200) numbuffers = 200; MixBuffers = calloc(numbuffers, sizeof(*MixBuffers)); bufferinfo = calloc(numbuffers, sizeof(*bufferinfo)); ulMCIBuffers = numbuffers; mbp.ulNumBuffers = ulMCIBuffers; /* mbp.ulBufferSize = mmp.ulBufferSize; */ /* I don't like this... they must be smaller than 64KB or else the engine needs major rewrite */ mbp.ulBufferSize = audiobufsize; mbp.pBufList = MixBuffers; rc = mciSendCommand( maop.usDeviceID, MCI_BUFFER, MCI_WAIT | MCI_ALLOCATE_MEMORY, (PVOID) &mbp, 0 ); if ( ULONG_LOWD(rc) != MCIERR_SUCCESS ) { MciError(rc); maop.usDeviceID = 0; return(-1); } pBufferplayed = playedbuffer.pBuffer = calloc(1,audiobufsize); ulMCIBuffers = mbp.ulNumBuffers; /* never know! */ /* Fill all device buffers with zeros and set linked list */ for(i = 0; i < ulMCIBuffers; i++) { MixBuffers[i].ulFlags = 0; MixBuffers[i].ulBufferLength = mbp.ulBufferSize; memset(MixBuffers[i].pBuffer, 0, MixBuffers[i].ulBufferLength); MixBuffers[i].ulUserParm = (ULONG) &bufferinfo[i]; bufferinfo[i].NextBuffer = &MixBuffers[i+1]; } bufferinfo[i-1].NextBuffer = &MixBuffers[0]; /* Create a semaphore to know when data has been played by the DART thread */ DosCreateEventSem(NULL,&dataplayed,0,FALSE); playingbuffer = &MixBuffers[0]; tobefilled = &MixBuffers[1]; playingframe = 0; nomoredata = TRUE; nobuffermode = FALSE; justflushed = FALSE; if(boostprio) { temp = alloca(strlen(boostprio)+1); strcpy(temp,boostprio); boostdelta = atoi(temp+1); *(temp+1) = 0; boostclass = atoi(temp); } if(boostclass > 4) boostdelta = 3; if(boostdelta > 31) boostdelta = 31; if(boostdelta < -31) boostdelta = -31; if(normalprio) { temp = alloca(strlen(normalprio)+1); strcpy(temp,normalprio); normaldelta = atoi(temp+1); *(temp+1) = 0; normalclass = atoi(temp); } if(normalclass > 4) normaldelta = 3; if(normaldelta > 31) normaldelta = 31; if(normaldelta < -31) normaldelta = -31; DosGetInfoBlocks(&mainthread,&ppib); /* ppib not needed, but makes some DOSCALLS.DLL crash */ DosSetPriority(PRTYS_THREAD,boostclass,boostdelta,mainthread->tib_ptib2->tib2_ultid); /* Write buffers to kick off the amp mixer. see DARTEvent() */ rc = mmp.pmixWrite( mmp.ulMixHandle, MixBuffers, ulMCIBuffers ); return maop.usDeviceID; }
int OpenDevice() { CHAR achBuffer[CCHMAXPATH] = ""; APIRET rc; MCI_AMP_OPEN_PARMS AmpOpenParms; MCI_CONNECTOR_PARMS ConnectorParms; MCI_AMP_SET_PARMS AmpSetParms ; MCI_GENERIC_PARMS GenericParms; int i; ULONG Action; ULONG Wrote; // Setup the open structure, pass the playlist and tell MCI_OPEN to use it memset(&AmpOpenParms,0,sizeof(AmpOpenParms)); AmpOpenParms.usDeviceID = ( USHORT ) 0; // AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX; AmpOpenParms.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, device); rc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, ( PVOID ) &AmpOpenParms, 0 ); if (ULONG_LOWD(rc) != MCIERR_SUCCESS) { mciGetErrorString( rc, (PSZ)achBuffer, sizeof( achBuffer)); cout << "Error #" << ULONG_LOWD(rc) << ": " << achBuffer << endl; goto Init_Err; } DeviceId = AmpOpenParms.usDeviceID; //Grab exclusive rights to device instance (NOT entire device) GenericParms.hwndCallback = 0; //Not needed, so set to 0 rc = mciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE, (PVOID)&GenericParms, 0); if (ULONG_LOWD(rc) != MCIERR_SUCCESS) { mciGetErrorString( rc, (PSZ)achBuffer, sizeof( achBuffer)); cout << "Error #" << ULONG_LOWD(rc) << ": " << achBuffer << endl; goto Init_Err; } /* Set the MixSetupParms data structure to match the loaded file. * This is a global that is used to setup the mixer. */ memset( &MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) ); MixSetupParms.ulBitsPerSample = RecSettings.bits; MixSetupParms.ulSamplesPerSec = RecSettings.rate; MixSetupParms.ulFormatTag = RecSettings.format; MixSetupParms.ulChannels = RecSettings.numchan; /* Setup the mixer for playback of wave data */ MixSetupParms.ulFormatMode = MCI_RECORD; MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; MixSetupParms.pmixEvent = MixHandler; rc = mciSendCommand( DeviceId, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT, ( PVOID ) &MixSetupParms, 0 ); if ( rc != MCIERR_SUCCESS ) { mciGetErrorString( rc, (PSZ)achBuffer, sizeof( achBuffer)); cout << "Error #" << hex << rc << ": " << achBuffer << endl; goto Init_Err; } /* Use the suggested buffer size provide by the mixer device * and the size of the audio file to calculate the required * number of Amp-Mixer buffers. */ ulNumBuffers = NUM_BUFFERS; /* * Set up the BufferParms data structure and allocate * device buffers from the Amp-Mixer */ MixSetupParms.ulBufferSize = ulBuffersize; BufferParms.ulNumBuffers = ulNumBuffers; BufferParms.ulBufferSize = MixSetupParms.ulBufferSize; BufferParms.pBufList = MixBuffers; for(i=0;i<NUM_BUFFERS;i++) { MixBuffers[i].ulUserParm = i; //nr of buffer (used in mixer.c) } rc = mciSendCommand( DeviceId, MCI_BUFFER, MCI_WAIT | MCI_ALLOCATE_MEMORY, ( PVOID ) &BufferParms, 0 ); if ( ULONG_LOWD( rc) != MCIERR_SUCCESS ) { goto Init_Err; } rc = wavfile.openWAV(filename, CREATE, RecSettings.rate, RecSettings.numchan, RecSettings.bits, RecSettings.format); if(rc) goto Init_Err; #if 0 rc = DosOpen(filename, /* file name from Open dialog */ &modin, /* file handle returned */ &Action, 0L, FILE_NORMAL, OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS, OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE, (PEAOP2)NULL); if(rc) goto Init_Err; //save settings to file DosWrite(modin, (char *)&RecSettings, sizeof(RecSettings), &Wrote); #endif /* Set the connector to 'line in' */ memset( &ConnectorParms, '\0', sizeof( MCI_CONNECTOR_PARMS ) ); ConnectorParms.ulConnectorType = MCI_LINE_IN_CONNECTOR; rc = mciSendCommand( DeviceId, MCI_CONNECTOR, MCI_WAIT | MCI_ENABLE_CONNECTOR | MCI_CONNECTOR_TYPE, ( PVOID ) &ConnectorParms, 0 ); /* Allow the user to hear what is being recorded * by turning the monitor on */ memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) ); AmpSetParms.ulItem = MCI_AMP_SET_MONITOR; rc = mciSendCommand( DeviceId, MCI_SET, MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM, ( PVOID ) &AmpSetParms, 0 ); return(TRUE); Init_Err: return(FALSE); }
ULONG ConnectToAmp( INSTANCE *ulpInstance, MMDRV_OPEN_PARMS *pDrvOpenParams, ULONG ulOpenFlags ) { ULONG ulDeviceTypeID; // device id of connected device ULONG ulrc; // return code variable // ULONG ulHoldError; USHORT usConnLength; // length of conn struct MCI_AMP_OPEN_PARMS MCIAmpOpenParms; // MCI AmpMixer Open Parameters DEFAULTCONNECTIONS2 DefCon; // MCI Connections Block // SPCB tempspcb; MMAUDIOHEADER mmaudioheader; VSD_AUDIOOPEN_PARMS vsdOpen; CONCB concb; /* Inform the amp how we wish to initialize the device */ memmove( &mmaudioheader, &ulpInstance->mmAudioHeader, sizeof( MMAUDIOHEADER )); vsdOpen.pHeader = ( PVOID) &mmaudioheader; vsdOpen.ulFlags = VSD_AUDIO_OPEN; vsdOpen.ulReserved2 = (ULONG) &concb; /***************************** * Obtain WaveAudio Device ID *****************************/ ulpInstance->usWaveDeviceID = pDrvOpenParams->usDeviceID; ulDeviceTypeID = MAKEULONG ( MCI_DEVTYPE_WAVEFORM_AUDIO, pDrvOpenParams->usDeviceOrd); /****************************************************** * Ensure that the INI file contains the right device id ******************************************************/ if ( pDrvOpenParams->usDeviceType != MCI_DEVTYPE_WAVEFORM_AUDIO ) { return ( MCIERR_INI_FILE ); } usConnLength = sizeof(DEFAULTCONNECTIONS2); ulrc = mciQueryDefaultConnections ( ulDeviceTypeID, &DefCon, &usConnLength); /****************************************************** * Ensure that the INI file says that we are connected * to an amp mixer. If it says that we are connected * to ourselves, return an error. ******************************************************/ if ( ULONG_LOWD( DefCon.dwDeviceTypeID2 ) == MCI_DEVTYPE_WAVEFORM_AUDIO ) { return ( MCIERR_INI_FILE ); } /****************************** * Open an AMP/MIXER Instance ******************************/ MCIAmpOpenParms.pszDeviceType = (PSZ) DefCon.dwDeviceTypeID2; MCIAmpOpenParms.hwndCallback = (ULONG) NULL; // 6421 --no need to retrive this information any more // we are truly device independent // GetPDDName (DefCon.dwDeviceTypeID2, szPDDName); // strcpy ( ulpInstance->szAudioDevName, szPDDName); /* Copy the name of the pdd + vsd dll to amp structure */ // strcpy ((PSZ) AMPMIX.szDeviceName, // ulpInstance->szAudioDevName); // strcpy ((PSZ) ulpInstance->StreamInfo.AudioDCB.szDevName, // ulpInstance->szAudioDevName); /******************************************* * The current amp/mixer uses an undocumented * structure. Pass this structure in on the * open also. ********************************************/ MCIAmpOpenParms.pDevDataPtr = (PVOID) &vsdOpen; /* Open what we are connected to--usually the amp */ ulrc = mciSendCommand (0, MCI_OPEN, MCI_OPEN_TYPE_ID| MCI_WAIT| ulOpenFlags, (PVOID) &MCIAmpOpenParms, 0); // CODEC change /*-------------------------------------------- * It is possible that the VSD may require a * best fit. Try with the best fit parameters. *-------------------------------------------*/ if (ulrc) { #ifndef CONNECTION if ( ulrc == MCIERR_UNSUPP_FORMAT_TAG ) { /* Open what we are connected to--usually the amp */ ulrc = mciSendCommand (0, MCI_OPEN, MCI_OPEN_TYPE_ID| MCI_WAIT| ulOpenFlags, (PVOID) &MCIAmpOpenParms, 0); } if ( ulrc ) #endif { return ( ulrc ); } ulpInstance->ulRealTimeTranslation = MMIO_REALTIME; memmove( &ulpInstance->mmAudioHeader, &mmaudioheader, sizeof( MMAUDIOHEADER ) ); } /* If the amp-mixer could not deal with the data type */ else { ulpInstance->ulRealTimeTranslation = MMIO_NONREALTIME; } // CODEC feature--removed functionality /* Remember the amp device id so that we can close it */ ulpInstance->usAmpDeviceID = MCIAmpOpenParms.usDeviceID; #ifndef CONNECTION ulrc = GetMixerInfo( ulpInstance, &concb ); if ( ulrc ) { /*----------------------------------------- * Ensure that the amp-mixer is CLOSED!!!!!! * Else an error will lock the device. *------------------------------------------*/ mciSendCommand ((WORD)ulpInstance->usAmpDeviceID, MCI_CLOSE, MCI_WAIT, 0, 0); } #endif return ( ulrc ); } /* ConnectToAmp */