PaError PaHost_OpenStream( internalPortAudioStream *past ) { PaError result = paNoError; PaHostSoundControl *pahsc; unsigned int minNumBuffers; internalPortAudioDevice *pad; DBUG(("PaHost_OpenStream() called.\n" )); /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) malloc(sizeof(PaHostSoundControl)); if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; /* No device currently opened. */ pahsc->pahsc_InputHandle = BAD_DEVICE_ID; pahsc->pahsc_IsAudioThreadValid = 0; pahsc->pahsc_IsWatchDogThreadValid = 0; /* Allocate native buffers. */ pahsc->pahsc_BytesPerInputBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels * sizeof(short); if( past->past_NumInputChannels > 0) { pahsc->pahsc_NativeInputBuffer = (short *) malloc(pahsc->pahsc_BytesPerInputBuffer); if( pahsc->pahsc_NativeInputBuffer == NULL ) { result = paInsufficientMemory; goto error; } } pahsc->pahsc_BytesPerOutputBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels * sizeof(short); if( past->past_NumOutputChannels > 0) { pahsc->pahsc_NativeOutputBuffer = (short *) malloc(pahsc->pahsc_BytesPerOutputBuffer); if( pahsc->pahsc_NativeOutputBuffer == NULL ) { result = paInsufficientMemory; goto error; } } /* DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); */ minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; pahsc->pahsc_InverseMicrosPerBuffer = past->past_SampleRate / (1000000.0 * past->past_FramesPerUserBuffer); DBUG(("past_SampleRate = %g\n", past->past_SampleRate )); DBUG(("past_FramesPerUserBuffer = %d\n", past->past_FramesPerUserBuffer )); DBUG(("pahsc_InverseMicrosPerBuffer = %g\n", pahsc->pahsc_InverseMicrosPerBuffer )); /* ------------------------- OPEN DEVICE -----------------------*/ /* just output */ if (past->past_OutputDeviceID == past->past_InputDeviceID) { if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) ) { pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_RDWR\n", pad->pad_DeviceName )); /* dmazzoni: test it first in nonblocking mode to make sure the device is not busy */ pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDWR|O_NONBLOCK); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName )); result = paHostError; goto error; } close(pahsc->pahsc_InputHandle); pahsc->pahsc_OutputHandle = pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDWR); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_OutputHandle, past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumOutputChannels ); result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle, past->past_NumOutputChannels, (int)past->past_SampleRate ); } } else { if (past->past_NumOutputChannels > 0) { pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_WRONLY\n", pad->pad_DeviceName )); /* dmazzoni: test it first in nonblocking mode to make sure the device is not busy */ pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY|O_NONBLOCK); if(pahsc->pahsc_OutputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } close(pahsc->pahsc_OutputHandle); pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY); if(pahsc->pahsc_OutputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_OutputHandle, past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumOutputChannels ); result = Pa_SetupOutputDeviceFormat( pahsc->pahsc_OutputHandle, past->past_NumOutputChannels, (int)past->past_SampleRate ); } if (past->past_NumInputChannels > 0) { pad = Pa_GetInternalDevice( past->past_InputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_RDONLY\n", pad->pad_DeviceName )); /* dmazzoni: test it first in nonblocking mode to make sure the device is not busy */ pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY|O_NONBLOCK); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } close(pahsc->pahsc_InputHandle); pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_InputHandle, /* DH20010115 - was OutputHandle! */ past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumInputChannels ); result = Pa_SetupInputDeviceFormat( pahsc->pahsc_InputHandle, past->past_NumInputChannels, (int)past->past_SampleRate ); } } DBUG(("PaHost_OpenStream: SUCCESS - result = %d\n", result )); return result; error: ERR_RPT(("PaHost_OpenStream: ERROR - result = %d\n", result )); PaHost_CloseStream( past ); return result; }
PaError PaHost_OpenStream( internalPortAudioStream *past ) { HRESULT hr; PaError result = paNoError; PaHostSoundControl *pahsc; int numBytes, maxChannels; unsigned int minNumBuffers; internalPortAudioDevice *pad; DSoundWrapper *dsw; /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */ if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; pahsc->pahsc_TimerID = 0; dsw = &pahsc->pahsc_DSoundWrapper; DSW_Init( dsw ); /* Allocate native buffer. */ maxChannels = ( past->past_NumOutputChannels > past->past_NumInputChannels ) ? past->past_NumOutputChannels : past->past_NumInputChannels; pahsc->pahsc_BytesPerBuffer = past->past_FramesPerUserBuffer * maxChannels * sizeof(short); if( maxChannels > 0 ) { pahsc->pahsc_NativeBuffer = (short *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerBuffer); /* MEM */ if( pahsc->pahsc_NativeBuffer == NULL ) { result = paInsufficientMemory; goto error; } } else { result = paInvalidChannelCount; goto error; } DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; numBytes = pahsc->pahsc_BytesPerBuffer * past->past_NumUserBuffers; if( numBytes < DSBSIZE_MIN ) { result = paBufferTooSmall; goto error; } if( numBytes > DSBSIZE_MAX ) { result = paBufferTooBig; goto error; } pahsc->pahsc_FramesPerDSBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers; { int msecLatency = (int) ((pahsc->pahsc_FramesPerDSBuffer * 1000) / past->past_SampleRate); PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", pahsc->pahsc_FramesPerDSBuffer, msecLatency )); } /* ------------------ OUTPUT */ if( (past->past_OutputDeviceID >= 0) && (past->past_NumOutputChannels > 0) ) { DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID)); pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); /* If this fails, then try each output device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Output device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; i<Pa_CountDevices(); i++ ) { pad = Pa_GetInternalDevice( i ); if( pad->pad_Info.maxOutputChannels >= past->past_NumOutputChannels ) { DBUG(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); if( hr == DS_OK ) { ERR_RPT(("Using device '%s' instead.\n", pad->pad_Info.name )); break; } } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitOutputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumOutputChannels, numBytes ); DBUG(("DSW_InitOutputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; } past->past_FrameCount = pahsc->pahsc_DSoundWrapper.dsw_FramesWritten; } #if SUPPORT_AUDIO_CAPTURE /* ------------------ INPUT */ if( (past->past_InputDeviceID >= 0) && (past->past_NumInputChannels > 0) ) { pad = Pa_GetInternalDevice( past->past_InputDeviceID ); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); /* If this fails, then try each input device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Capture device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; i<Pa_CountDevices(); i++ ) { pad = Pa_GetInternalDevice( i ); if( pad->pad_Info.maxInputChannels >= past->past_NumInputChannels ) { PRINT(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr == DS_OK ) break; } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitInputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumInputChannels, numBytes ); DBUG(("DSW_InitInputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr)); result = paHostError; sPaHostError = hr; goto error; } } #endif /* SUPPORT_AUDIO_CAPTURE */ /* Calculate scalar used in CPULoad calculation. */ { LARGE_INTEGER frequency; if( QueryPerformanceFrequency( &frequency ) == 0 ) { pahsc->pahsc_InverseTicksPerUserBuffer = 0.0; } else { pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate / ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer ); DBUG(("pahsc_InverseTicksPerUserBuffer = %g\n", pahsc->pahsc_InverseTicksPerUserBuffer )); } } return result; error: PaHost_CloseStream( past ); return result; }