diff --git a/lib-src/portaudio-v19/include/pa_win_ds.h b/lib-src/portaudio-v19/include/pa_win_ds.h index 5d3864168..f8197e531 100644 --- a/lib-src/portaudio-v19/include/pa_win_ds.h +++ b/lib-src/portaudio-v19/include/pa_win_ds.h @@ -87,6 +87,22 @@ typedef struct PaWinDirectSoundStreamInfo{ }PaWinDirectSoundStreamInfo; +/** Retrieve the GUID of the input device. + + @param stream The stream to query. + + @return A pointer to the GUID, or NULL if none. +*/ +LPGUID PaWinDS_GetStreamInputGUID( PaStream* s ); + +/** Retrieve the GUID of the output device. + + @param stream The stream to query. + + @return A pointer to the GUID, or NULL if none. +*/ +LPGUID PaWinDS_GetStreamOutputGUID( PaStream* s ); + #ifdef __cplusplus } diff --git a/lib-src/portaudio-v19/include/pa_win_wasapi.h b/lib-src/portaudio-v19/include/pa_win_wasapi.h index 9b827d1ea..a4416b121 100644 --- a/lib-src/portaudio-v19/include/pa_win_wasapi.h +++ b/lib-src/portaudio-v19/include/pa_win_wasapi.h @@ -548,6 +548,22 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput ); */ PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData ); +/** Returns Windows device ID for input stream + + @param pStream Pointer to PaStream to query. + + @return non-null value pointing to static device ID +*/ +const wchar_t *PaWasapi_GetInputDeviceID( PaStream *s ); + +/** Returns Windows device ID for output stream + + @param pStream Pointer to PaStream to query. + + @return non-null value pointing to static device ID +*/ +const wchar_t *PaWasapi_GetOutputDeviceID( PaStream *s ); + /* IMPORTANT: diff --git a/lib-src/portaudio-v19/include/portaudio.h b/lib-src/portaudio-v19/include/portaudio.h index 738080d43..ae1cbe280 100644 --- a/lib-src/portaudio-v19/include/portaudio.h +++ b/lib-src/portaudio-v19/include/portaudio.h @@ -1197,6 +1197,15 @@ signed long Pa_GetStreamReadAvailable( PaStream* stream ); signed long Pa_GetStreamWriteAvailable( PaStream* stream ); +/** Retrieve the host type handling an open stream. + + @return Returns a non-negative value representing the host API type + handling an open stream or, a PaErrorCode (which are always negative) + if PortAudio is not initialized or an error is encountered. +*/ +PaHostApiTypeId Pa_GetStreamHostApiType( PaStream* stream ); + + /* Miscellaneous utilities */ diff --git a/lib-src/portaudio-v19/src/common/pa_front.c b/lib-src/portaudio-v19/src/common/pa_front.c index 9d30f4837..b4b318692 100644 --- a/lib-src/portaudio-v19/src/common/pa_front.c +++ b/lib-src/portaudio-v19/src/common/pa_front.c @@ -1257,8 +1257,10 @@ PaError Pa_OpenStream( PaStream** stream, hostApiInputParametersPtr, hostApiOutputParametersPtr, sampleRate, framesPerBuffer, streamFlags, streamCallback, userData ); - if( result == paNoError ) + if( result == paNoError ) { AddOpenStream( *stream ); + PA_STREAM_REP(*stream)->hostApiType = hostApi->info.type; + } PA_LOGAPI(("Pa_OpenStream returned:\n" )); @@ -1770,6 +1772,32 @@ signed long Pa_GetStreamWriteAvailable( PaStream* stream ) return result; } +PaHostApiTypeId Pa_GetStreamHostApiType( PaStream* stream ) +{ + PaError error = PaUtil_ValidateStreamPointer( stream ); + PaHostApiTypeId result; + +#ifdef PA_LOG_API_CALLS + PaUtil_DebugPrint("Pa_GetStreamHostApiType called:\n" ); + PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream ); +#endif + + if( error == paNoError ) + { + result = PA_STREAM_REP(stream)->hostApiType; + } + else + { + result = (PaHostApiTypeId) error; + } + +#ifdef PA_LOG_API_CALLS + PaUtil_DebugPrint("Pa_GetStreamHostApiType returned:\n" ); + PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) ); +#endif + + return result; +} PaError Pa_GetSampleSize( PaSampleFormat format ) { diff --git a/lib-src/portaudio-v19/src/common/pa_stream.c b/lib-src/portaudio-v19/src/common/pa_stream.c index 03a0ee6ee..c4376f93b 100644 --- a/lib-src/portaudio-v19/src/common/pa_stream.c +++ b/lib-src/portaudio-v19/src/common/pa_stream.c @@ -93,6 +93,8 @@ void PaUtil_InitializeStreamRepresentation( PaUtilStreamRepresentation *streamRe streamRepresentation->streamInfo.inputLatency = 0.; streamRepresentation->streamInfo.outputLatency = 0.; streamRepresentation->streamInfo.sampleRate = 0.; + + streamRepresentation->hostApiType = 0; } diff --git a/lib-src/portaudio-v19/src/common/pa_stream.h b/lib-src/portaudio-v19/src/common/pa_stream.h index 678e2ad5e..70572c752 100644 --- a/lib-src/portaudio-v19/src/common/pa_stream.h +++ b/lib-src/portaudio-v19/src/common/pa_stream.h @@ -152,6 +152,7 @@ typedef struct PaUtilStreamRepresentation { PaStreamFinishedCallback *streamFinishedCallback; void *userData; PaStreamInfo streamInfo; + PaHostApiTypeId hostApiType; } PaUtilStreamRepresentation; diff --git a/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c b/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c index 584cde890..5d44ace39 100644 --- a/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c +++ b/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c @@ -621,6 +621,7 @@ typedef struct StreamDirection streamDir; snd_pcm_channel_area_t *channelAreas; /* Needed for channel adaption */ + int card; } PaAlsaStreamComponent; /* Implementation specific stream structure */ @@ -1874,6 +1875,7 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa PaError result = paNoError; PaSampleFormat userSampleFormat = params->sampleFormat, hostSampleFormat = paNoError; assert( params->channelCount > 0 ); + snd_pcm_info_t* pcmInfo; /* Make sure things have an initial value */ memset( self, 0, sizeof (PaAlsaStreamComponent) ); @@ -1902,6 +1904,9 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm ) ); self->nfds = alsa_snd_pcm_poll_descriptors_count( self->pcm ); + snd_pcm_info_alloca( &pcmInfo ); + self->card = snd_pcm_info_get_card( pcmInfo ); + PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( GetAvailableFormats( self->pcm ), userSampleFormat ) ); self->hostSampleFormat = hostSampleFormat; @@ -4605,9 +4610,7 @@ PaError PaAlsa_GetStreamInputCard( PaStream* s, int* card ) /* XXX: More descriptive error? */ PA_UNLESS( stream->capture.pcm, paDeviceUnavailable ); - alsa_snd_pcm_info_alloca( &pcmInfo ); - PA_ENSURE( alsa_snd_pcm_info( stream->capture.pcm, pcmInfo ) ); - *card = alsa_snd_pcm_info_get_card( pcmInfo ); + *card = stream->capture.card; error: return result; @@ -4624,9 +4627,7 @@ PaError PaAlsa_GetStreamOutputCard( PaStream* s, int* card ) /* XXX: More descriptive error? */ PA_UNLESS( stream->playback.pcm, paDeviceUnavailable ); - alsa_snd_pcm_info_alloca( &pcmInfo ); - PA_ENSURE( alsa_snd_pcm_info( stream->playback.pcm, pcmInfo ) ); - *card = alsa_snd_pcm_info_get_card( pcmInfo ); + *card = stream->capture.card; error: return result; diff --git a/lib-src/portaudio-v19/src/hostapi/dsound/pa_win_ds.c b/lib-src/portaudio-v19/src/hostapi/dsound/pa_win_ds.c index 204004d84..63e9984c4 100644 --- a/lib-src/portaudio-v19/src/hostapi/dsound/pa_win_ds.c +++ b/lib-src/portaudio-v19/src/hostapi/dsound/pa_win_ds.c @@ -257,6 +257,7 @@ typedef struct PaWinDsStream #endif /* Output */ + LPGUID pOutputGuid; LPDIRECTSOUND pDirectSound; LPDIRECTSOUNDBUFFER pDirectSoundPrimaryBuffer; LPDIRECTSOUNDBUFFER pDirectSoundOutputBuffer; @@ -272,6 +273,7 @@ typedef struct PaWinDsStream INT finalZeroBytesWritten; /* used to determine when we've flushed the whole buffer */ /* Input */ + LPGUID pInputGuid; LPDIRECTSOUNDCAPTURE pDirectSoundCapture; LPDIRECTSOUNDCAPTUREBUFFER pDirectSoundInputBuffer; INT inputFrameSizeBytes; @@ -1885,8 +1887,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaWinDsDeviceInfo *inputWinDsDeviceInfo, *outputWinDsDeviceInfo; PaDeviceInfo *inputDeviceInfo, *outputDeviceInfo; int inputChannelCount, outputChannelCount; - PaSampleFormat inputSampleFormat, outputSampleFormat; - PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; + PaSampleFormat inputSampleFormat = 0, outputSampleFormat = 0; + PaSampleFormat hostInputSampleFormat = 0, hostOutputSampleFormat = 0; int userRequestedHostInputBufferSizeFrames = 0; int userRequestedHostOutputBufferSizeFrames = 0; unsigned long suggestedInputLatencyFrames, suggestedOutputLatencyFrames; @@ -2177,6 +2179,13 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, goto error; } + /* Portmixer support - fill in the GUID of the output stream */ + stream->pOutputGuid = outputWinDsDeviceInfo->lpGUID; + if( stream->pOutputGuid == NULL ) + { + stream->pOutputGuid = (GUID *) &DSDEVID_DefaultPlayback; + } + /* Calculate value used in latency calculation to avoid real-time divides. */ stream->secondsPerHostByte = 1.0 / (stream->bufferProcessor.bytesPerHostOutputSample * @@ -2218,6 +2227,13 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, result = paBufferTooBig; goto error; } + + /* Portmixer support - store the GUID of the input stream */ + stream->pInputGuid = inputWinDsDeviceInfo->lpGUID; + if( stream->pInputGuid == NULL ) + { + stream->pInputGuid = (GUID *)&DSDEVID_DefaultCapture; + } } /* open/create the DirectSound buffers */ @@ -2261,6 +2277,12 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( outputParameters && !stream->pDirectSoundOutputBuffer ) { + stream->pOutputGuid = outputWinDsDeviceInfo->lpGUID; + if( stream->pOutputGuid == NULL ) + { + stream->pOutputGuid = (GUID *) &DSDEVID_DefaultPlayback; + } + hr = InitOutputBuffer( stream, (PaWinDsDeviceInfo*)hostApi->deviceInfos[outputParameters->device], hostOutputSampleFormat, @@ -3269,3 +3291,18 @@ static signed long GetStreamWriteAvailable( PaStream* s ) return 0; } +/***********************************************************************************/ +LPGUID PaWinDS_GetStreamInputGUID( PaStream* s ) +{ + PaWinDsStream *stream = (PaWinDsStream*)s; + + return stream->pInputGuid; +} + +/***********************************************************************************/ +LPGUID PaWinDS_GetStreamOutputGUID( PaStream* s ) +{ + PaWinDsStream *stream = (PaWinDsStream*)s; + + return stream->pOutputGuid; +} diff --git a/lib-src/portaudio-v19/src/hostapi/oss/pa_unix_oss.c b/lib-src/portaudio-v19/src/hostapi/oss/pa_unix_oss.c index 51e963048..f257d8039 100644 --- a/lib-src/portaudio-v19/src/hostapi/oss/pa_unix_oss.c +++ b/lib-src/portaudio-v19/src/hostapi/oss/pa_unix_oss.c @@ -2043,3 +2043,26 @@ error: #endif } +const char *PaOSS_GetStreamInputDevice( PaStream* s ) +{ + PaOssStream *stream = (PaOssStream*)s; + + if( stream->capture ) + { + return stream->capture->devName; + } + + return NULL; +} + +const char *PaOSS_GetStreamOutputDevice( PaStream* s ) +{ + PaOssStream *stream = (PaOssStream*)s; + + if( stream->playback ) + { + return stream->playback->devName; + } + + return NULL; +} diff --git a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c index 1d8f20070..93e1d612a 100644 --- a/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c +++ b/lib-src/portaudio-v19/src/hostapi/wasapi/pa_win_wasapi.c @@ -5283,6 +5283,32 @@ PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCa return paNoError; } +// ------------------------------------------------------------------------------------------ +const wchar_t *PaWasapi_GetInputDeviceID( PaStream *s ) +{ + PaWasapiStream *stream = (PaWasapiStream *)s; + if (stream == NULL) + return NULL; + + if (stream->in.params.device_info) + return stream->in.params.device_info->szDeviceID; + + return NULL; +} + +// ------------------------------------------------------------------------------------------ +const wchar_t *PaWasapi_GetOutputDeviceID( PaStream *s ) +{ + PaWasapiStream *stream = (PaWasapiStream *)s; + if (stream == NULL) + return NULL; + + if (stream->out.params.device_info) + return stream->out.params.device_info->szDeviceID; + + return NULL; +} + // ------------------------------------------------------------------------------------------ HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available) {