PortAudio: Update to v190600_20161030

This commit is contained in:
Michael Maltese 2017-01-20 11:35:17 -08:00
parent b05fc9d369
commit 3dc7d18775
63 changed files with 8243 additions and 9719 deletions

View File

@ -137,6 +137,8 @@ IF(WIN32)
SET(PA_PRIVATE_INCLUDES ${PA_PRIVATE_INCLUDES} ${PA_PLATFORM_INCLUDES})
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/os/win)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} winmm)
# Try to find ASIO SDK (assumes that portaudio and asiosdk folders are side-by-side, see
# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/WindowsASIOMSVC)
FIND_PACKAGE(ASIOSDK)
@ -156,7 +158,7 @@ IF(WIN32)
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_asio.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_ASIO_SOURCES})
SET(PA_NON_UNICODE_SOURCES ${PA_NON_UNICODE_SOURCES} ${PA_ASIOSDK_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} winmm ole32 uuid)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
ELSE()
# Set variables for DEF file expansion
SET(DEF_EXCLUDE_ASIO_SYMBOLS ";")
@ -195,6 +197,7 @@ IF(WIN32)
SOURCE_GROUP("hostapi\\wmme" FILES ${PA_WMME_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wmme.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WMME_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
ENDIF()
IF(MSVS)
@ -209,6 +212,7 @@ IF(WIN32)
SOURCE_GROUP("hostapi\\wasapi" FILES ${PA_WASAPI_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wasapi.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WASAPI_SOURCES})
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} ole32 uuid)
IF(NOT MSVC)
SET(PA_PRIVATE_INCLUDE_PATHS ${PA_PRIVATE_INCLUDE_PATHS} src/hostapi/wasapi/mingw-include)
ENDIF()
@ -222,8 +226,7 @@ IF(WIN32)
SOURCE_GROUP("hostapi\\wdmks" FILES ${PA_WDMKS_SOURCES})
SET(PA_PUBLIC_INCLUDES ${PA_PUBLIC_INCLUDES} include/pa_win_wdmks.h)
SET(PA_SOURCES ${PA_SOURCES} ${PA_WDMKS_SOURCES})
# If we use WDM/KS we need setupapi.lib
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} setupapi)
SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} setupapi ole32 uuid)
ENDIF()
OPTION(PA_USE_WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON)
@ -250,7 +253,7 @@ ELSE()
IF(APPLE)
# SET(CMAKE_MACOSX_RPATH 1)
SET(CMAKE_MACOSX_RPATH 1)
OPTION(PA_USE_COREAUDIO "Enable support for CoreAudio" ON)
IF(PA_USE_COREAUDIO)
SET(PA_COREAUDIO_SOURCES
@ -344,14 +347,14 @@ ENDIF()
ADD_LIBRARY(portaudio SHARED ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES} ${PA_EXTRA_SHARED_SOURCES})
SET_PROPERTY(TARGET portaudio APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS})
TARGET_INCLUDE_DIRECTORIES(portaudio PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
TARGET_INCLUDE_DIRECTORIES(portaudio PUBLIC include)
TARGET_INCLUDE_DIRECTORIES(portaudio BEFORE PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
TARGET_INCLUDE_DIRECTORIES(portaudio BEFORE PUBLIC include)
TARGET_LINK_LIBRARIES(portaudio ${PA_LIBRARY_DEPENDENCIES})
ADD_LIBRARY(portaudio_static STATIC ${PA_INCLUDES} ${PA_COMMON_INCLUDES} ${PA_SOURCES} ${PA_NON_UNICODE_SOURCES})
SET_PROPERTY(TARGET portaudio_static APPEND_STRING PROPERTY COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS})
TARGET_INCLUDE_DIRECTORIES(portaudio_static PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
TARGET_INCLUDE_DIRECTORIES(portaudio_static PUBLIC include)
TARGET_INCLUDE_DIRECTORIES(portaudio_static BEFORE PRIVATE ${PA_PRIVATE_INCLUDE_PATHS})
TARGET_INCLUDE_DIRECTORIES(portaudio_static BEFORE PUBLIC include)
TARGET_LINK_LIBRARIES(portaudio_static ${PA_LIBRARY_DEPENDENCIES})
IF(WIN32 AND MSVC)
@ -402,3 +405,4 @@ OPTION(PA_BUILD_EXAMPLES "Include example projects" OFF)
IF(PA_BUILD_EXAMPLES)
SUBDIRS(examples)
ENDIF()

View File

@ -1,53 +1,53 @@
; $Id: $
;
; !!! @GENERATED_MESSAGE@ !!!
EXPORTS
;
Pa_GetVersion @1
Pa_GetVersionText @2
Pa_GetErrorText @3
Pa_Initialize @4
Pa_Terminate @5
Pa_GetHostApiCount @6
Pa_GetDefaultHostApi @7
Pa_GetHostApiInfo @8
Pa_HostApiTypeIdToHostApiIndex @9
Pa_HostApiDeviceIndexToDeviceIndex @10
Pa_GetLastHostErrorInfo @11
Pa_GetDeviceCount @12
Pa_GetDefaultInputDevice @13
Pa_GetDefaultOutputDevice @14
Pa_GetDeviceInfo @15
Pa_IsFormatSupported @16
Pa_OpenStream @17
Pa_OpenDefaultStream @18
Pa_CloseStream @19
Pa_SetStreamFinishedCallback @20
Pa_StartStream @21
Pa_StopStream @22
Pa_AbortStream @23
Pa_IsStreamStopped @24
Pa_IsStreamActive @25
Pa_GetStreamInfo @26
Pa_GetStreamTime @27
Pa_GetStreamCpuLoad @28
Pa_ReadStream @29
Pa_WriteStream @30
Pa_GetStreamReadAvailable @31
Pa_GetStreamWriteAvailable @32
Pa_GetSampleSize @33
Pa_Sleep @34
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetAvailableBufferSizes @50
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_ShowControlPanel @51
@DEF_EXCLUDE_X86_PLAIN_CONVERTERS@PaUtil_InitializeX86PlainConverters @52
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetInputChannelName @53
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetOutputChannelName @54
PaUtil_SetDebugPrintFunction @55
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceDefaultFormat @56
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceRole @57
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityBoost @58
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityRevert @59
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetFramesPerHostBuffer @60
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackDescription @61
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackCount @62
; $Id: $
;
; !!! @GENERATED_MESSAGE@ !!!
EXPORTS
;
Pa_GetVersion @1
Pa_GetVersionText @2
Pa_GetErrorText @3
Pa_Initialize @4
Pa_Terminate @5
Pa_GetHostApiCount @6
Pa_GetDefaultHostApi @7
Pa_GetHostApiInfo @8
Pa_HostApiTypeIdToHostApiIndex @9
Pa_HostApiDeviceIndexToDeviceIndex @10
Pa_GetLastHostErrorInfo @11
Pa_GetDeviceCount @12
Pa_GetDefaultInputDevice @13
Pa_GetDefaultOutputDevice @14
Pa_GetDeviceInfo @15
Pa_IsFormatSupported @16
Pa_OpenStream @17
Pa_OpenDefaultStream @18
Pa_CloseStream @19
Pa_SetStreamFinishedCallback @20
Pa_StartStream @21
Pa_StopStream @22
Pa_AbortStream @23
Pa_IsStreamStopped @24
Pa_IsStreamActive @25
Pa_GetStreamInfo @26
Pa_GetStreamTime @27
Pa_GetStreamCpuLoad @28
Pa_ReadStream @29
Pa_WriteStream @30
Pa_GetStreamReadAvailable @31
Pa_GetStreamWriteAvailable @32
Pa_GetSampleSize @33
Pa_Sleep @34
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetAvailableBufferSizes @50
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_ShowControlPanel @51
@DEF_EXCLUDE_X86_PLAIN_CONVERTERS@PaUtil_InitializeX86PlainConverters @52
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetInputChannelName @53
@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetOutputChannelName @54
PaUtil_SetDebugPrintFunction @55
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceDefaultFormat @56
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceRole @57
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityBoost @58
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityRevert @59
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetFramesPerHostBuffer @60
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackDescription @61
@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackCount @62

View File

@ -1,7 +1,7 @@
#ifndef PA_ASIO_H
#define PA_ASIO_H
/*
* $Id: pa_asio.h 1667 2011-05-02 15:49:20Z rossb $
* $Id$
* PortAudio Portable Real-Time Audio Library
* ASIO specific extensions
*

View File

@ -2,7 +2,7 @@
#define PA_LINUX_ALSA_H
/*
* $Id: pa_linux_alsa.h 1597 2011-02-11 00:15:51Z dmitrykos $
* $Id$
* PortAudio Portable Real-Time Audio Library
* ALSA-specific extensions
*

View File

@ -46,7 +46,7 @@
#include "portaudio.h"
#include <AudioUnit/AudioUnit.h>
//#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioToolbox.h>
#ifdef __cplusplus
extern "C" {
@ -124,6 +124,19 @@ AudioDeviceID PaMacCore_GetStreamOutputDevice( PaStream* s );
*/
const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input );
/** Retrieve the range of legal native buffer sizes for the specificed device, in sample frames.
@param device The global index of the PortAudio device about which the query is being made.
@param minBufferSizeFrames A pointer to the location which will receive the minimum buffer size value.
@param maxBufferSizeFrames A pointer to the location which will receive the maximum buffer size value.
@see kAudioDevicePropertyBufferFrameSizeRange in the CoreAudio SDK.
*/
PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device,
long *minBufferSizeFrames, long *maxBufferSizeFrames );
/**
* Flags
*/

View File

@ -61,24 +61,21 @@ typedef struct PaWinDirectSoundStreamInfo{
PaHostApiTypeId hostApiType; /**< paDirectSound */
unsigned long version; /**< 2 */
unsigned long flags;
unsigned long flags; /**< enable other features of this struct */
/* low-level latency setting support
Control the size of host buffers in order to set latency. They will
be used instead of the generic parameters to Pa_OpenStream() if
flags contains the paWinDirectSoundUseLowLevelLatencyParameters
flag.
/**
low-level latency setting support
Sets the size of the DirectSound host buffer.
When flags contains the paWinDirectSoundUseLowLevelLatencyParameters
this size will be used instead of interpreting the generic latency
parameters to Pa_OpenStream(). If the flag is not set this value is ignored.
If PaWinDirectSoundStreamInfo structures with paWinDirectSoundUseLowLevelLatencyParameters
are supplied for both input and output in a full duplex stream, then the
input and output framesPerBuffer must be the same, or the larger of the
two must be a multiple of the smaller, otherwise a
paIncompatibleHostApiSpecificStreamInfo error will be returned from
Pa_OpenStream().
If the stream is a full duplex stream the implementation requires that
the values of framesPerBuffer for input and output match (if both are specified).
*/
unsigned long framesPerBuffer; /* NOT IMPLEMENTED see http://www.portaudio.com/trac/ticket/129 */
unsigned long framesPerBuffer;
/*
/**
support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinDirectSoundUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask

View File

@ -69,8 +69,8 @@ typedef enum PaWasapiFlags
method can only provide 15-20ms latency. */
paWinWasapiPolling = (1 << 3),
/* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority
is set to custom value. */
/* forces custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
is set to a custom value */
paWinWasapiThreadPriority = (1 << 4)
}
PaWasapiFlags;
@ -91,7 +91,7 @@ typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFra
void *outputBuffer, long outputFrames,
void *userData);
/* Device role */
/* Device role. */
typedef enum PaWasapiDeviceRole
{
eRoleRemoteNetworkDevice = 0,
@ -109,7 +109,7 @@ typedef enum PaWasapiDeviceRole
PaWasapiDeviceRole;
/* Jack connection type */
/* Jack connection type. */
typedef enum PaWasapiJackConnectionType
{
eJackConnTypeUnknown,
@ -128,10 +128,10 @@ typedef enum PaWasapiJackConnectionType
PaWasapiJackConnectionType;
/* Jack geometric location */
/* Jack geometric location. */
typedef enum PaWasapiJackGeoLocation
{
eJackGeoLocUnk = 0,
eJackGeoLocUnk = 0,
eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
eJackGeoLocFront,
eJackGeoLocLeft,
@ -151,7 +151,7 @@ typedef enum PaWasapiJackGeoLocation
PaWasapiJackGeoLocation;
/* Jack general location */
/* Jack general location. */
typedef enum PaWasapiJackGenLocation
{
eJackGenLocPrimaryBox = 0,
@ -162,7 +162,7 @@ typedef enum PaWasapiJackGenLocation
PaWasapiJackGenLocation;
/* Jack's type of port */
/* Jack's type of port. */
typedef enum PaWasapiJackPortConnection
{
eJackPortConnJack = 0,
@ -173,7 +173,7 @@ typedef enum PaWasapiJackPortConnection
PaWasapiJackPortConnection;
/* Thread priority */
/* Thread priority. */
typedef enum PaWasapiThreadPriority
{
eThreadPriorityNone = 0,
@ -202,6 +202,46 @@ typedef struct PaWasapiJackDescription
PaWasapiJackDescription;
/** Stream category.
Note:
- values are equal to WASAPI AUDIO_STREAM_CATEGORY enum
- supported since Windows 8.0, noop on earler versions
- values 1,2 are deprecated on Windows 10 and not included into enumeration
@version Available as of 19.6.0
*/
typedef enum PaWasapiStreamCategory
{
eAudioCategoryOther = 0,
eAudioCategoryCommunications = 3,
eAudioCategoryAlerts = 4,
eAudioCategorySoundEffects = 5,
eAudioCategoryGameEffects = 6,
eAudioCategoryGameMedia = 7,
eAudioCategoryGameChat = 8,
eAudioCategorySpeech = 9,
eAudioCategoryMovie = 10,
eAudioCategoryMedia = 11
}
PaWasapiStreamCategory;
/** Stream option.
Note:
- values are equal to WASAPI AUDCLNT_STREAMOPTIONS enum
- supported since Windows 8.1, noop on earler versions
@version Available as of 19.6.0
*/
typedef enum PaWasapiStreamOption
{
eStreamOptionNone = 0, //!< default
eStreamOptionRaw = 1, //!< bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1
eStreamOptionMatchFormat = 2 //!< force WASAPI Audio Engine into a stream format, supported since Windows 10
}
PaWasapiStreamOption;
/* Stream descriptor. */
typedef struct PaWasapiStreamInfo
{
@ -211,7 +251,7 @@ typedef struct PaWasapiStreamInfo
unsigned long flags; /**< collection of PaWasapiFlags */
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
/** Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinWasapiUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h. Will be used only if
@ -219,7 +259,7 @@ typedef struct PaWasapiStreamInfo
*/
PaWinWaveFormatChannelMask channelMask;
/* Delivers raw data to callback obtained from GetBuffer() methods skipping
/** Delivers raw data to callback obtained from GetBuffer() methods skipping
internal PortAudio processing inventory completely. userData parameter will
be the same that was passed to Pa_OpenStream method. Will be used only if
paWinWasapiRedirectHostProcessor flag is specified.
@ -227,7 +267,7 @@ typedef struct PaWasapiStreamInfo
PaWasapiHostProcessorCallback hostProcessorOutput;
PaWasapiHostProcessorCallback hostProcessorInput;
/* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
/** Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
is specified.
Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)
@ -235,6 +275,18 @@ typedef struct PaWasapiStreamInfo
to setup thread priority.
*/
PaWasapiThreadPriority threadPriority;
/** Stream category.
@see PaWasapiStreamCategory
@version Available as of 19.6.0
*/
PaWasapiStreamCategory streamCategory;
/** Stream option.
@see PaWasapiStreamOption
@version Available as of 19.6.0
*/
PaWasapiStreamOption streamOption;
}
PaWasapiStreamInfo;
@ -303,7 +355,7 @@ PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput
/** Get number of jacks associated with a WASAPI device. Use this method to determine if
there are any jacks associated with the provided WASAPI device. Not all audio devices
will support this capability. This is valid for both input and output devices.
will support this capability. This is valid for both input and output devices.
@param nDevice device index.
@param jcount Number of jacks is returned in this variable
@return Error code indicating success or failure
@ -314,9 +366,9 @@ PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
/** Get the jack description associated with a WASAPI device and jack number
Before this function is called, use PaWasapi_GetJackCount to determine the
number of jacks associated with device. If jcount is greater than zero, then
each jack from 0 to jcount can be queried with this function to get the jack
description.
number of jacks associated with device. If jcount is greater than zero, then
each jack from 0 to jcount can be queried with this function to get the jack
description.
@param nDevice device index.
@param jindex Which jack to return information
@param KSJACK_DESCRIPTION This structure filled in on success.
@ -347,7 +399,7 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ
This is the most powerful WASAPI implementation which provides glitch-free
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
3 ms for HD Audio class audio chips. For the Shared mode latency can not be
lower than 20 ms.
lower than 20 ms.
2) Poll-Driven:
Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven

View File

@ -0,0 +1,137 @@
#ifndef PA_WIN_WDMKS_H
#define PA_WIN_WDMKS_H
/*
* $Id$
* PortAudio Portable Real-Time Audio Library
* WDM/KS specific extensions
*
* Copyright (c) 1999-2007 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup public_header
@brief WDM Kernel Streaming-specific PortAudio API extension header file.
*/
#include "portaudio.h"
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/** Flags to indicate valid fields in PaWinWDMKSInfo.
@see PaWinWDMKSInfo
@version Available as of 19.5.0.
*/
typedef enum PaWinWDMKSFlags
{
/** Makes WDMKS use the supplied latency figures instead of relying on the frame size reported
by the WaveCyclic device. Use at own risk!
*/
paWinWDMKSOverrideFramesize = (1 << 0),
/** Makes WDMKS (output stream) use the given channelMask instead of the default.
@version Available as of 19.5.0.
*/
paWinWDMKSUseGivenChannelMask = (1 << 1),
} PaWinWDMKSFlags;
typedef struct PaWinWDMKSInfo{
unsigned long size; /**< sizeof(PaWinWDMKSInfo) */
PaHostApiTypeId hostApiType; /**< paWDMKS */
unsigned long version; /**< 1 */
/** Flags indicate which fields are valid.
@see PaWinWDMKSFlags
@version Available as of 19.5.0.
*/
unsigned long flags;
/** The number of packets to use for WaveCyclic devices, range is [2, 8]. Set to zero for default value of 2. */
unsigned noOfPackets;
/** If paWinWDMKSUseGivenChannelMask bit is set in flags, use this as channelMask instead of default.
@see PaWinWDMKSFlags
@version Available as of 19.5.0.
*/
unsigned channelMask;
} PaWinWDMKSInfo;
typedef enum PaWDMKSType
{
Type_kNotUsed,
Type_kWaveCyclic,
Type_kWaveRT,
Type_kCnt,
} PaWDMKSType;
typedef enum PaWDMKSSubType
{
SubType_kUnknown,
SubType_kNotification,
SubType_kPolled,
SubType_kCnt,
} PaWDMKSSubType;
typedef struct PaWinWDMKSDeviceInfo {
wchar_t filterPath[MAX_PATH]; /**< KS filter path in Unicode! */
wchar_t topologyPath[MAX_PATH]; /**< Topology filter path in Unicode! */
PaWDMKSType streamingType;
GUID deviceProductGuid; /**< The product GUID of the device (if supported) */
} PaWinWDMKSDeviceInfo;
typedef struct PaWDMKSDirectionSpecificStreamInfo
{
PaDeviceIndex device;
unsigned channels; /**< No of channels the device is opened with */
unsigned framesPerHostBuffer; /**< No of frames of the device buffer */
int endpointPinId; /**< Endpoint pin ID (on topology filter if topologyName is not empty) */
int muxNodeId; /**< Only valid for input */
PaWDMKSSubType streamingSubType; /**< Not known until device is opened for streaming */
} PaWDMKSDirectionSpecificStreamInfo;
typedef struct PaWDMKSSpecificStreamInfo {
PaWDMKSDirectionSpecificStreamInfo input;
PaWDMKSDirectionSpecificStreamInfo output;
} PaWDMKSSpecificStreamInfo;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PA_WIN_DS_H */

View File

@ -1,7 +1,7 @@
#ifndef PA_WIN_WMME_H
#define PA_WIN_WMME_H
/*
* $Id: pa_win_wmme.h 1592 2011-02-04 10:41:58Z rossb $
* $Id$
* PortAudio Portable Real-Time Audio Library
* MME specific extensions
*

View File

@ -1,7 +1,7 @@
#ifndef PORTAUDIO_H
#define PORTAUDIO_H
/*
* $Id: portaudio.h 1745 2011-08-25 17:44:01Z rossb $
* $Id$
* PortAudio Portable Real-Time Audio Library
* PortAudio API Header File
* Latest version available at: http://www.portaudio.com/
@ -50,18 +50,69 @@ extern "C"
{
#endif /* __cplusplus */
/** Retrieve the release number of the currently running PortAudio build,
eg 1900.
/** Retrieve the release number of the currently running PortAudio build.
For example, for version "19.5.1" this will return 0x00130501.
@see paMakeVersionNumber
*/
int Pa_GetVersion( void );
/** Retrieve a textual description of the current PortAudio build,
eg "PortAudio V19-devel 13 October 2002".
e.g. "PortAudio V19.5.0-devel, revision 1952M".
The format of the text may change in the future. Do not try to parse the
returned string.
@deprecated As of 19.5.0, use Pa_GetVersionInfo()->versionText instead.
*/
const char* Pa_GetVersionText( void );
/**
Generate a packed integer version number in the same format used
by Pa_GetVersion(). Use this to compare a specified version number with
the currently running version. For example:
@code
if( Pa_GetVersion() < paMakeVersionNumber(19,5,1) ) {}
@endcode
@see Pa_GetVersion, Pa_GetVersionInfo
@version Available as of 19.5.0.
*/
#define paMakeVersionNumber(major, minor, subminor) \
(((major)&0xFF)<<16 | ((minor)&0xFF)<<8 | ((subminor)&0xFF))
/**
A structure containing PortAudio API version information.
@see Pa_GetVersionInfo, paMakeVersionNumber
@version Available as of 19.5.0.
*/
typedef struct PaVersionInfo {
int versionMajor;
int versionMinor;
int versionSubMinor;
/**
This is currently the Git revision hash but may change in the future.
The versionControlRevision is updated by running a script before compiling the library.
If the update does not occur, this value may refer to an earlier revision.
*/
const char *versionControlRevision;
/** Version as a string, for example "PortAudio V19.5.0-devel, revision 1952M" */
const char *versionText;
} PaVersionInfo;
/** Retrieve version information for the currently running PortAudio build.
@return A pointer to an immutable PaVersionInfo structure.
@note This function can be called at any time. It does not require PortAudio
to be initialized. The structure pointed to is statically allocated. Do not
attempt to free it or modify it.
@see PaVersionInfo, paMakeVersionNumber
@version Available as of 19.5.0.
*/
const PaVersionInfo* Pa_GetVersionInfo();
/** Error codes returned by PortAudio functions.
Note that with the exception of paNoError, all PaErrorCodes are negative.
@ -900,7 +951,7 @@ PaError Pa_CloseStream( PaStream *stream );
(ie once a call to Pa_StopStream() will not block).
A stream will become inactive after the stream callback returns non-zero,
or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio
output, if the stream callback returns paComplete, or Pa_StopStream is called,
output, if the stream callback returns paComplete, or Pa_StopStream() is called,
the stream finished callback will not be called until all generated sample data
has been played.
@ -1021,7 +1072,7 @@ typedef struct PaStreamInfo
/** Retrieve a pointer to a PaStreamInfo structure containing information
about the specified stream.
@return A pointer to an immutable PaStreamInfo structure. If the stream
parameter invalid, or an error is encountered, the function returns NULL.
parameter is invalid, or an error is encountered, the function returns NULL.
@param stream A pointer to an open stream previously created with Pa_OpenStream.
@ -1098,7 +1149,7 @@ PaError Pa_ReadStream( PaStream* stream,
/** Write samples to an output stream. This function doesn't return until the
entire buffer has been consumed - this may involve waiting for the operating
entire buffer has been written - this may involve waiting for the operating
system to consume the data.
@param stream A pointer to an open stream previously created with Pa_OpenStream.

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_allocation.c 1097 2006-08-26 08:27:53Z rossb $
* $Id$
* Portable Audio I/O Library allocation group implementation
* memory allocation group for tracking allocation groups
*

View File

@ -1,7 +1,7 @@
#ifndef PA_ALLOCATION_H
#define PA_ALLOCATION_H
/*
* $Id: pa_allocation.h 1339 2008-02-15 07:50:33Z rossb $
* $Id$
* Portable Audio I/O Library allocation context header
* memory allocation context for tracking allocation groups
*

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_converters.c 1748 2011-09-01 22:08:32Z philburk $
* $Id$
* Portable Audio I/O Library sample conversion mechanism
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,7 +1,7 @@
#ifndef PA_CONVERTERS_H
#define PA_CONVERTERS_H
/*
* $Id: pa_converters.h 1097 2006-08-26 08:27:53Z rossb $
* $Id$
* Portable Audio I/O Library sample conversion mechanism
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_cpuload.c 1577 2011-02-01 13:03:45Z rossb $
* $Id$
* Portable Audio I/O Library CPU Load measurement functions
* Portable CPU load measurement facility.
*

View File

@ -1,7 +1,7 @@
#ifndef PA_CPULOAD_H
#define PA_CPULOAD_H
/*
* $Id: pa_cpuload.h 1097 2006-08-26 08:27:53Z rossb $
* $Id$
* Portable Audio I/O Library CPU Load measurement functions
* Portable CPU load measurement facility.
*

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_dither.c 1418 2009-10-12 21:00:53Z philburk $
* $Id$
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,7 +1,7 @@
#ifndef PA_DITHER_H
#define PA_DITHER_H
/*
* $Id: pa_dither.h 1418 2009-10-12 21:00:53Z philburk $
* $Id$
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,7 +1,7 @@
#ifndef PA_ENDIANNESS_H
#define PA_ENDIANNESS_H
/*
* $Id: pa_endianness.h 1324 2008-01-27 02:03:30Z bjornroche $
* $Id$
* Portable Audio I/O Library current platform endianness macros
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_front.c 1730 2011-08-18 03:43:51Z rossb $
* $Id$
* Portable Audio I/O Library Multi-Host API front end
* Validate function parameters and manage multiple host APIs.
*
@ -27,26 +27,26 @@
*/
/*
* The text above constitutes the entire PortAudio license; however,
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Implements PortAudio API functions defined in portaudio.h, checks
@brief Implements PortAudio API functions defined in portaudio.h, checks
some errors, delegates platform-specific behavior to host API implementations.
Implements the functions defined in the PortAudio API (portaudio.h),
validates some parameters and checks for state inconsistencies before
forwarding API requests to specific Host API implementations (via the
interface declared in pa_hostapi.h), and Streams (via the interface
Implements the functions defined in the PortAudio API (portaudio.h),
validates some parameters and checks for state inconsistencies before
forwarding API requests to specific Host API implementations (via the
interface declared in pa_hostapi.h), and Streams (via the interface
declared in pa_stream.h).
This file manages initialization and termination of Host API
@ -65,6 +65,7 @@
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h> /* needed for strtol() */
#include <assert.h> /* needed by PA_VALIDATE_ENDIANNESS */
#include "portaudio.h"
@ -76,25 +77,63 @@
#include "pa_trace.h" /* still usefull?*/
#include "pa_debugprint.h"
#ifndef PA_GIT_REVISION
#include "pa_gitrevision.h"
#endif
#define PA_VERSION_ 1899
#define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ " " __TIME__ ")"
/**
* This is incremented if we make incompatible API changes.
* This version scheme is based loosely on http://semver.org/
*/
#define paVersionMajor 19
/**
* This is incremented when we add functionality in a backwards-compatible manner.
* Or it is set to zero when paVersionMajor is incremented.
*/
#define paVersionMinor 6
/**
* This is incremented when we make backwards-compatible bug fixes.
* Or it is set to zero when paVersionMinor changes.
*/
#define paVersionSubMinor 0
/**
* This is a combination of paVersionMajor, paVersionMinor and paVersionSubMinor.
* It will always increase so that version numbers can be compared as integers to
* see which is later.
*/
#define paVersion paMakeVersionNumber(paVersionMajor, paVersionMinor, paVersionSubMinor)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define PA_VERSION_STRING_ TOSTRING(paVersionMajor) "." TOSTRING(paVersionMinor) "." TOSTRING(paVersionSubMinor)
#define PA_VERSION_TEXT_ "PortAudio V" PA_VERSION_STRING_ "-devel, revision " TOSTRING(PA_GIT_REVISION)
int Pa_GetVersion( void )
{
return PA_VERSION_;
return paVersion;
}
const char* Pa_GetVersionText( void )
{
return PA_VERSION_TEXT_;
}
static PaVersionInfo versionInfo_ = {
/*.versionMajor =*/ paVersionMajor,
/*.versionMinor =*/ paVersionMinor,
/*.versionSubMinor =*/ paVersionSubMinor,
/*.versionControlRevision =*/ TOSTRING(PA_GIT_REVISION),
/*.versionText =*/ PA_VERSION_TEXT_
};
const PaVersionInfo* Pa_GetVersionInfo()
{
return &versionInfo_;
}
#define PA_LAST_HOST_ERROR_TEXT_LENGTH_ 1024
@ -170,7 +209,7 @@ static PaError InitializeHostApis( void )
if( !hostApis_ )
{
result = paInsufficientMemory;
goto error;
goto error;
}
hostApisCount_ = 0;
@ -196,11 +235,11 @@ static PaError InitializeHostApis( void )
assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
/* the first successfully initialized host API with a default input *or*
/* the first successfully initialized host API with a default input *or*
output device is used as the default host API.
*/
if( (defaultHostApiIndex_ == -1) &&
( hostApi->info.defaultInputDevice != paNoDevice
( hostApi->info.defaultInputDevice != paNoDevice
|| hostApi->info.defaultOutputDevice != paNoDevice ) )
{
defaultHostApiIndex_ = hostApisCount_;
@ -238,7 +277,7 @@ error:
<device> belongs and returns it. if <hostSpecificDeviceIndex> is
non-null, the host specific device index is returned in it.
returns -1 if <device> is out of range.
*/
static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
{
@ -328,7 +367,7 @@ PaError Pa_Initialize( void )
{
PA_VALIDATE_TYPE_SIZES;
PA_VALIDATE_ENDIANNESS;
PaUtil_InitializeClock();
PaUtil_ResetTraceMessages();
@ -351,7 +390,8 @@ PaError Pa_Terminate( void )
if( PA_IS_INITIALISED_ )
{
if( --initializationCount_ == 0 )
// leave initializationCount_>0 so that Pa_CloseStream() can execute
if( initializationCount_ == 1 )
{
CloseOpenStreams();
@ -359,6 +399,7 @@ PaError Pa_Terminate( void )
PaUtil_DumpTraceMessages();
}
--initializationCount_;
result = paNoError;
}
else
@ -415,11 +456,11 @@ const char *Pa_GetErrorText( PaError errorCode )
case paCanNotWriteToAnInputOnlyStream: result = "Can't write to an input only stream"; break;
case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break;
case paBadBufferPtr: result = "Bad buffer pointer"; break;
default:
default:
if( errorCode > 0 )
result = "Invalid error code (value greater than zero)";
result = "Invalid error code (value greater than zero)";
else
result = "Invalid error code";
result = "Invalid error code";
break;
}
return result;
@ -430,7 +471,7 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
{
PaHostApiIndex result;
int i;
PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiTypeIdToHostApiIndex" );
PA_LOGAPI(("\tPaHostApiTypeId type: %d\n", type ));
@ -441,14 +482,14 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
else
{
result = paHostApiNotFound;
for( i=0; i < hostApisCount_; ++i )
{
if( hostApis_[i]->info.type == type )
{
result = i;
break;
}
}
}
}
@ -463,7 +504,7 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho
{
PaError result;
int i;
if( !PA_IS_INITIALISED_ )
{
result = paNotInitialized;
@ -471,7 +512,7 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho
else
{
result = paHostApiNotFound;
for( i=0; i < hostApisCount_; ++i )
{
if( hostApis_[i]->info.type == type )
@ -492,7 +533,7 @@ PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
{
PaError result;
PaDeviceIndex x;
x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
if( x < 0 || x >= hostApi->info.deviceCount )
@ -577,7 +618,7 @@ const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
else if( hostApi < 0 || hostApi >= hostApisCount_ )
{
info = NULL;
PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
PA_LOGAPI(("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n" ));
@ -686,7 +727,7 @@ PaDeviceIndex Pa_GetDefaultOutputDevice( void )
{
PaHostApiIndex hostApi;
PaDeviceIndex result;
PA_LOGAPI_ENTER( "Pa_GetDefaultOutputDevice" );
hostApi = Pa_GetDefaultHostApi();
@ -770,7 +811,7 @@ static int SampleFormatIsValid( PaSampleFormat format )
ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
conform to the expected values as described below. This function is
also designed to be used with the proposed Pa_IsFormatSupported() function.
There are basically two types of validation that could be performed:
Generic conformance validation, and device capability mismatch
validation. This function performs only generic conformance validation.
@ -779,21 +820,21 @@ static int SampleFormatIsValid( PaSampleFormat format )
combinations of parameters - for example, even if the sampleRate
seems ok, it might not be for a duplex stream - we have no way of
checking this in an API-neutral way, so we don't try.
On success the function returns PaNoError and fills in hostApi,
hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
the function returns an error code indicating the first encountered
parameter error.
If ValidateOpenStreamParameters() returns paNoError, the following
assertions are guaranteed to be true.
- at least one of inputParameters & outputParmeters is valid (not NULL)
- if inputParameters & outputParameters are both valid, that
inputParameters->device & outputParameters->device both use the same host api
PaDeviceIndex inputParameters->device
- is within range (0 to Pa_GetDeviceCount-1) Or:
- is paUseHostApiSpecificDeviceSpecification and
@ -803,30 +844,30 @@ static int SampleFormatIsValid( PaSampleFormat format )
int inputParameters->channelCount
- if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
- upper bound is NOT validated against device capabilities
PaSampleFormat inputParameters->sampleFormat
- is one of the sample formats defined in portaudio.h
void *inputParameters->hostApiSpecificStreamInfo
- if supplied its hostApi field matches the input device's host Api
PaDeviceIndex outputParmeters->device
- is within range (0 to Pa_GetDeviceCount-1)
int outputParmeters->channelCount
- if inputDevice is valid, channelCount is > 0
- upper bound is NOT validated against device capabilities
PaSampleFormat outputParmeters->sampleFormat
- is one of the sample formats defined in portaudio.h
void *outputParmeters->hostApiSpecificStreamInfo
- if supplied its hostApi field matches the output device's host Api
double sampleRate
- is not an 'absurd' rate (less than 1000. or greater than 200000.)
- is not an 'absurd' rate (less than 1000. or greater than 384000.)
- sampleRate is NOT validated against device capabilities
PaStreamFlags streamFlags
- unused platform neutral flags are zero
- paNeverDropInput is only used for full-duplex callback streams with
@ -953,7 +994,7 @@ static PaError ValidateOpenStreamParameters(
!= (*hostApi)->info.type )
return paIncompatibleHostApiSpecificStreamInfo;
}
}
}
if( (inputParameters != NULL) && (outputParameters != NULL) )
{
@ -962,10 +1003,10 @@ static PaError ValidateOpenStreamParameters(
return paBadIODeviceCombination;
}
}
/* Check for absurd sample rates. */
if( (sampleRate < 1000.0) || (sampleRate > 200000.0) )
if( (sampleRate < 1000.0) || (sampleRate > 384000.0) )
return paInvalidSampleRate;
if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 )
@ -985,7 +1026,7 @@ static PaError ValidateOpenStreamParameters(
if( framesPerBuffer != paFramesPerBufferUnspecified )
return paInvalidFlag;
}
return paNoError;
}
@ -1025,7 +1066,7 @@ PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
}
PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
#endif
@ -1048,7 +1089,7 @@ PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
return result;
}
if( inputParameters )
{
@ -1135,7 +1176,7 @@ PaError Pa_OpenStream( PaStream** stream,
PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
}
PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags ));
@ -1182,7 +1223,7 @@ PaError Pa_OpenStream( PaStream** stream,
PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
return result;
}
if( inputParameters )
{
@ -1256,8 +1297,8 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
{
hostApiInputParameters.device = Pa_GetDefaultInputDevice();
if( hostApiInputParameters.device == paNoDevice )
return paDeviceUnavailable;
return paDeviceUnavailable;
hostApiInputParameters.channelCount = inputChannelCount;
hostApiInputParameters.sampleFormat = sampleFormat;
/* defaultHighInputLatency is used below instead of
@ -1265,7 +1306,7 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
stream to work reliably than it is for it to work with the lowest
latency.
*/
hostApiInputParameters.suggestedLatency =
hostApiInputParameters.suggestedLatency =
Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
hostApiInputParametersPtr = &hostApiInputParameters;
@ -1279,7 +1320,7 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
{
hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
if( hostApiOutputParameters.device == paNoDevice )
return paDeviceUnavailable;
return paDeviceUnavailable;
hostApiOutputParameters.channelCount = outputChannelCount;
hostApiOutputParameters.sampleFormat = sampleFormat;
@ -1663,7 +1704,7 @@ PaError Pa_WriteStream( PaStream* stream,
else if( result == 1 )
{
result = paStreamIsStopped;
}
}
}
}

View File

@ -0,0 +1 @@
#define PA_GIT_REVISION 396fe4b6699ae929d3a685b3ef8a7e97396139a4

View File

@ -1,7 +1,7 @@
#ifndef PA_HOSTAPI_H
#define PA_HOSTAPI_H
/*
* $Id: pa_hostapi.h 1740 2011-08-25 07:17:48Z philburk $
* $Id$
* Portable Audio I/O Library
* host api representation
*
@ -264,7 +264,7 @@ typedef struct PaUtilHostApiRepresentation {
- if supplied its hostApi field matches the output device's host Api
double sampleRate
- is not an 'absurd' rate (less than 1000. or greater than 200000.)
- is not an 'absurd' rate (less than 1000. or greater than 384000.)
- sampleRate is NOT validated against device capabilities
PaStreamFlags streamFlags

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_process.c 1706 2011-07-21 18:44:58Z philburk $
* $Id$
* Portable Audio I/O Library
* streamCallback <-> host buffer processing adapter
*
@ -238,7 +238,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp,
bp->inputConverter =
PaUtil_SelectConverter( hostInputSampleFormat, userInputSampleFormat, tempInputStreamFlags );
bp->inputZeroer = PaUtil_SelectZeroer( hostInputSampleFormat );
bp->inputZeroer = PaUtil_SelectZeroer( userInputSampleFormat );
bp->userInputIsInterleaved = (userInputSampleFormat & paNonInterleaved)?0:1;
@ -743,8 +743,10 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp,
destSampleStrideSamples = bp->inputChannelCount;
destChannelStrideBytes = bp->bytesPerUserInputSample;
/* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved */
if( bp->userInputSampleFormatIsEqualToHost && bp->hostInputIsInterleaved && bp->hostInputChannels[0][0].data)
/* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved,
* or if num channels differs between the host (set in stride) and the user (eg with some Alsa hw:) */
if( bp->userInputSampleFormatIsEqualToHost && bp->hostInputIsInterleaved
&& bp->hostInputChannels[0][0].data && bp->inputChannelCount == hostInputChannels[0].stride )
{
userInput = hostInputChannels[0].data;
destBytePtr = (unsigned char *)hostInputChannels[0].data;
@ -832,8 +834,10 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp,
{
if( bp->userOutputIsInterleaved )
{
/* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved */
if( bp->userOutputSampleFormatIsEqualToHost && bp->hostOutputIsInterleaved )
/* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved,
* or if num channels differs between the host (set in stride) and the user (eg with some Alsa hw:) */
if( bp->userOutputSampleFormatIsEqualToHost && bp->hostOutputIsInterleaved
&& bp->outputChannelCount == hostOutputChannels[0].stride )
{
userOutput = hostOutputChannels[0].data;
skipOutputConvert = 1;
@ -1683,9 +1687,9 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp,
hostInputChannels[i].stride,
framesToCopy, &bp->ditherGenerator );
destBytePtr += destChannelStrideBytes; /* skip to next source channel */
destBytePtr += destChannelStrideBytes; /* skip to next dest channel */
/* advance dest ptr for next iteration */
/* advance source ptr for next iteration */
hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
}
@ -1715,7 +1719,7 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp,
destBytePtr += bp->bytesPerUserInputSample * framesToCopy;
nonInterleavedDestPtrs[i] = destBytePtr;
/* advance dest ptr for next iteration */
/* advance source ptr for next iteration */
hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
}

View File

@ -1,7 +1,7 @@
#ifndef PA_PROCESS_H
#define PA_PROCESS_H
/*
* $Id: pa_process.h 1668 2011-05-02 17:07:11Z rossb $
* $Id$
* Portable Audio I/O Library callback buffer processing adapters
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_ringbuffer.c 1738 2011-08-18 11:47:28Z rossb $
* $Id$
* Portable Audio I/O Library
* Ring Buffer utility.
*

View File

@ -1,7 +1,7 @@
#ifndef PA_RINGBUFFER_H
#define PA_RINGBUFFER_H
/*
* $Id: pa_ringbuffer.h 1734 2011-08-18 11:19:36Z rossb $
* $Id$
* Portable Audio I/O Library
* Ring Buffer utility.
*
@ -65,6 +65,9 @@
The memory area used to store the buffer elements must be allocated by
the client prior to calling PaUtil_InitializeRingBuffer() and must outlive
the use of the ring buffer.
@note The ring buffer functions are not normally exposed in the PortAudio libraries.
If you want to call them then you will need to add pa_ringbuffer.c to your application source code.
*/
#if defined(__APPLE__)

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_stream.c 1339 2008-02-15 07:50:33Z rossb $
* $Id$
* Portable Audio I/O Library
* stream interface
*

View File

@ -1,7 +1,7 @@
#ifndef PA_STREAM_H
#define PA_STREAM_H
/*
* $Id: pa_stream.h 1339 2008-02-15 07:50:33Z rossb $
* $Id$
* Portable Audio I/O Library
* stream interface
*

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_trace.c 1339 2008-02-15 07:50:33Z rossb $
* $Id$
* Portable Audio I/O Library Trace Facility
* Store trace information in real-time for later printing.
*
@ -46,12 +46,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "pa_trace.h"
#include "pa_util.h"
#include "pa_debugprint.h"
#if PA_TRACE_REALTIME_EVENTS
static char *traceTextArray[PA_MAX_TRACE_RECORDS];
static char const *traceTextArray[PA_MAX_TRACE_RECORDS];
static int traceIntArray[PA_MAX_TRACE_RECORDS];
static int traceIndex = 0;
static int traceBlock = 0;
@ -94,4 +98,141 @@ void PaUtil_AddTraceMessage( const char *msg, int data )
}
}
/************************************************************************/
/* High performance log alternative */
/************************************************************************/
typedef unsigned long long PaUint64;
typedef struct __PaHighPerformanceLog
{
unsigned magik;
int writePtr;
int readPtr;
int size;
double refTime;
char* data;
} PaHighPerformanceLog;
static const unsigned kMagik = 0xcafebabe;
#define USEC_PER_SEC (1000000ULL)
int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes )
{
PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog));
if (pLog == 0)
{
return paInsufficientMemory;
}
assert(phLog != 0);
*phLog = pLog;
pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes);
if (pLog->data == 0)
{
PaUtil_FreeMemory(pLog);
return paInsufficientMemory;
}
pLog->magik = kMagik;
pLog->size = maxSizeInBytes;
pLog->refTime = PaUtil_GetTime();
return paNoError;
}
void PaUtil_ResetHighSpeedLogTimeRef( LogHandle hLog )
{
PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
assert(pLog->magik == kMagik);
pLog->refTime = PaUtil_GetTime();
}
typedef struct __PaLogEntryHeader
{
int size;
double timeStamp;
} PaLogEntryHeader;
#ifdef __APPLE__
#define _vsnprintf vsnprintf
#define min(a,b) ((a)<(b)?(a):(b))
#endif
int PaUtil_AddHighSpeedLogMessage( LogHandle hLog, const char* fmt, ... )
{
va_list l;
int n = 0;
PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
if (pLog != 0)
{
PaLogEntryHeader* pHeader;
char* p;
int maxN;
assert(pLog->magik == kMagik);
pHeader = (PaLogEntryHeader*)( pLog->data + pLog->writePtr );
p = (char*)( pHeader + 1 );
maxN = pLog->size - pLog->writePtr - 2 * sizeof(PaLogEntryHeader);
pHeader->timeStamp = PaUtil_GetTime() - pLog->refTime;
if (maxN > 0)
{
if (maxN > 32)
{
va_start(l, fmt);
n = _vsnprintf(p, min(1024, maxN), fmt, l);
va_end(l);
}
else {
n = sprintf(p, "End of log...");
}
n = ((n + sizeof(unsigned)) & ~(sizeof(unsigned)-1)) + sizeof(PaLogEntryHeader);
pHeader->size = n;
#if 0
PaUtil_DebugPrint("%05u.%03u: %s\n", pHeader->timeStamp/1000, pHeader->timeStamp%1000, p);
#endif
pLog->writePtr += n;
}
}
return n;
}
void PaUtil_DumpHighSpeedLog( LogHandle hLog, const char* fileName )
{
FILE* f = (fileName != NULL) ? fopen(fileName, "w") : stdout;
unsigned localWritePtr;
PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
assert(pLog->magik == kMagik);
localWritePtr = pLog->writePtr;
while (pLog->readPtr != localWritePtr)
{
const PaLogEntryHeader* pHeader = (const PaLogEntryHeader*)( pLog->data + pLog->readPtr );
const char* p = (const char*)( pHeader + 1 );
const PaUint64 ts = (const PaUint64)( pHeader->timeStamp * USEC_PER_SEC );
assert(pHeader->size < (1024+sizeof(unsigned)+sizeof(PaLogEntryHeader)));
fprintf(f, "%05u.%03u: %s\n", (unsigned)(ts/1000), (unsigned)(ts%1000), p);
pLog->readPtr += pHeader->size;
}
if (f != stdout)
{
fclose(f);
}
}
void PaUtil_DiscardHighSpeedLog( LogHandle hLog )
{
PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
assert(pLog->magik == kMagik);
PaUtil_FreeMemory(pLog->data);
PaUtil_FreeMemory(pLog);
}
#else
/* This stub was added so that this file will generate a symbol.
* Otherwise linker/archiver programs will complain.
*/
int PaUtil_TraceStubToSatisfyLinker(void)
{
return 0;
}
#endif /* TRACE_REALTIME_EVENTS */

View File

@ -1,7 +1,7 @@
#ifndef PA_TRACE_H
#define PA_TRACE_H
/*
* $Id: pa_trace.h 1339 2008-02-15 07:50:33Z rossb $
* $Id$
* Portable Audio I/O Library Trace Facility
* Store trace information in real-time for later printing.
*
@ -84,13 +84,29 @@ extern "C"
void PaUtil_ResetTraceMessages();
void PaUtil_AddTraceMessage( const char *msg, int data );
void PaUtil_DumpTraceMessages();
/* Alternative interface */
typedef void* LogHandle;
int PaUtil_InitializeHighSpeedLog(LogHandle* phLog, unsigned maxSizeInBytes);
void PaUtil_ResetHighSpeedLogTimeRef(LogHandle hLog);
int PaUtil_AddHighSpeedLogMessage(LogHandle hLog, const char* fmt, ...);
void PaUtil_DumpHighSpeedLog(LogHandle hLog, const char* fileName);
void PaUtil_DiscardHighSpeedLog(LogHandle hLog);
#else
#define PaUtil_ResetTraceMessages() /* noop */
#define PaUtil_AddTraceMessage(msg,data) /* noop */
#define PaUtil_DumpTraceMessages() /* noop */
#define PaUtil_InitializeHighSpeedLog(phLog, maxSizeInBytes) (0)
#define PaUtil_ResetHighSpeedLogTimeRef(hLog)
#define PaUtil_AddHighSpeedLogMessage(...) (0)
#define PaUtil_DumpHighSpeedLog(hLog, fileName)
#define PaUtil_DiscardHighSpeedLog(hLog)
#endif

View File

@ -1,7 +1,7 @@
#ifndef PA_UTIL_H
#define PA_UTIL_H
/*
* $Id: pa_util.h 1584 2011-02-02 18:58:17Z rossb $
* $Id$
* Portable Audio I/O Library implementation utilities header
* common implementation utilities and interfaces
*

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_asio.cpp 1778 2011-11-10 13:59:53Z rossb $
* $Id$
* Portable Audio I/O Library for ASIO Drivers
*
* Author: Stephane Letz
@ -1019,6 +1019,149 @@ static ASIOSampleRate defaultSampleRateSearchOrder_[]
192000.0, 16000.0, 12000.0, 11025.0, 9600.0, 8000.0 };
static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asioHostApi,
const char *driverName, int driverIndex,
PaDeviceInfo *deviceInfo, PaAsioDeviceInfo *asioDeviceInfo )
{
PaError result = paNoError;
/* Due to the headless design of the ASIO API, drivers are free to write over data given to them (like M-Audio
drivers f.i.). This is an attempt to overcome that. */
union _tag_local {
PaAsioDriverInfo info;
char _padding[4096];
} paAsioDriver;
asioDeviceInfo->asioChannelInfos = 0; /* we check this below to handle error cleanup */
result = LoadAsioDriver( asioHostApi, driverName, &paAsioDriver.info, asioHostApi->systemSpecific );
if( result == paNoError )
{
PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", driverIndex,deviceInfo->name));
PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", driverIndex, paAsioDriver.info.inputChannelCount));
PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", driverIndex, paAsioDriver.info.outputChannelCount));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", driverIndex, paAsioDriver.info.bufferMinSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", driverIndex, paAsioDriver.info.bufferMaxSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", driverIndex, paAsioDriver.info.bufferPreferredSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", driverIndex, paAsioDriver.info.bufferGranularity));
deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount;
deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount;
deviceInfo->defaultSampleRate = 0.;
bool foundDefaultSampleRate = false;
for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
{
ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
{
deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
foundDefaultSampleRate = true;
break;
}
}
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", driverIndex, deviceInfo->defaultSampleRate));
if( foundDefaultSampleRate ){
/* calculate default latency values from bufferPreferredSize
for default low latency, and bufferMaxSize
for default high latency.
use the default sample rate to convert from samples to
seconds. Without knowing what sample rate the user will
use this is the best we can do.
*/
double defaultLowLatency =
paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
double defaultHighLatency =
paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate;
if( defaultHighLatency < defaultLowLatency )
defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */
deviceInfo->defaultHighInputLatency = defaultHighLatency;
deviceInfo->defaultHighOutputLatency = defaultHighLatency;
}else{
deviceInfo->defaultLowInputLatency = 0.;
deviceInfo->defaultLowOutputLatency = 0.;
deviceInfo->defaultHighInputLatency = 0.;
deviceInfo->defaultHighOutputLatency = 0.;
}
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowInputLatency = %f\n", driverIndex, deviceInfo->defaultLowInputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowOutputLatency = %f\n", driverIndex, deviceInfo->defaultLowOutputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", driverIndex, deviceInfo->defaultHighInputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", driverIndex, deviceInfo->defaultHighOutputLatency));
asioDeviceInfo->minBufferSize = paAsioDriver.info.bufferMinSize;
asioDeviceInfo->maxBufferSize = paAsioDriver.info.bufferMaxSize;
asioDeviceInfo->preferredBufferSize = paAsioDriver.info.bufferPreferredSize;
asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity;
asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory(
asioHostApi->allocations,
sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels
+ deviceInfo->maxOutputChannels) );
if( !asioDeviceInfo->asioChannelInfos )
{
result = paInsufficientMemory;
goto error_unload;
}
int a;
for( a=0; a < deviceInfo->maxInputChannels; ++a ){
asioDeviceInfo->asioChannelInfos[a].channel = a;
asioDeviceInfo->asioChannelInfos[a].isInput = ASIOTrue;
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[a] );
if( asioError != ASE_OK )
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
goto error_unload;
}
}
for( a=0; a < deviceInfo->maxOutputChannels; ++a ){
int b = deviceInfo->maxInputChannels + a;
asioDeviceInfo->asioChannelInfos[b].channel = a;
asioDeviceInfo->asioChannelInfos[b].isInput = ASIOFalse;
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[b] );
if( asioError != ASE_OK )
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
goto error_unload;
}
}
/* unload the driver */
UnloadAsioDriver();
}
return result;
error_unload:
UnloadAsioDriver();
if( asioDeviceInfo->asioChannelInfos ){
PaUtil_GroupFreeMemory( asioHostApi->allocations, asioDeviceInfo->asioChannelInfos );
asioDeviceInfo->asioChannelInfos = 0;
}
return result;
}
/* we look up IsDebuggerPresent at runtime incase it isn't present (on Win95 for example) */
typedef BOOL (WINAPI *IsDebuggerPresentPtr)(VOID);
IsDebuggerPresentPtr IsDebuggerPresent_ = 0;
@ -1031,8 +1174,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
PaAsioHostApiRepresentation *asioHostApi;
PaAsioDeviceInfo *deviceInfoArray;
char **names;
PaAsioDriverInfo paAsioDriverInfo;
asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) );
if( !asioHostApi )
{
@ -1040,6 +1181,8 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
goto error;
}
memset( asioHostApi, 0, sizeof(PaAsioHostApiRepresentation) ); /* ensure all fields are zeroed. especially asioHostApi->allocations */
/*
We initialize COM ourselves here and uninitialize it in Terminate().
This should be the only COM initialization needed in this module.
@ -1142,7 +1285,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
for( i=0; i < driverCount; ++i )
{
PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i]));
// Since portaudio opens ALL ASIO drivers, and no one else does that,
@ -1170,13 +1312,12 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
if( strcmp(names[i], "ASIO Digidesign Driver") == 0 )
{
PA_DEBUG(("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n"));
continue;
continue;
}
}
/* Attempt to load the asio driver... */
if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
/* Attempt to init device info from the asio driver... */
{
PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
@ -1185,119 +1326,17 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
deviceInfo->hostApi = hostApiIndex;
deviceInfo->name = names[i];
PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name));
PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriverInfo.inputChannelCount));
PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize));
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity));
deviceInfo->maxInputChannels = paAsioDriverInfo.inputChannelCount;
deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount;
deviceInfo->defaultSampleRate = 0.;
bool foundDefaultSampleRate = false;
for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
if( InitPaDeviceInfoFromAsioDriver( asioHostApi, names[i], i, deviceInfo, asioDeviceInfo ) == paNoError )
{
ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
{
deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
foundDefaultSampleRate = true;
break;
}
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
++(*hostApi)->info.deviceCount;
}
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", i, deviceInfo->defaultSampleRate));
if( foundDefaultSampleRate ){
/* calculate default latency values from bufferPreferredSize
for default low latency, and bufferMaxSize
for default high latency.
use the default sample rate to convert from samples to
seconds. Without knowing what sample rate the user will
use this is the best we can do.
*/
double defaultLowLatency =
paAsioDriverInfo.bufferPreferredSize / deviceInfo->defaultSampleRate;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
double defaultHighLatency =
paAsioDriverInfo.bufferMaxSize / deviceInfo->defaultSampleRate;
if( defaultHighLatency < defaultLowLatency )
defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */
deviceInfo->defaultHighInputLatency = defaultHighLatency;
deviceInfo->defaultHighOutputLatency = defaultHighLatency;
}else{
deviceInfo->defaultLowInputLatency = 0.;
deviceInfo->defaultLowOutputLatency = 0.;
deviceInfo->defaultHighInputLatency = 0.;
deviceInfo->defaultHighOutputLatency = 0.;
else
{
PA_DEBUG(("Skipping ASIO device:%s\n",names[i]));
continue;
}
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowInputLatency = %f\n", i, deviceInfo->defaultLowInputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowOutputLatency = %f\n", i, deviceInfo->defaultLowOutputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", i, deviceInfo->defaultHighInputLatency));
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", i, deviceInfo->defaultHighOutputLatency));
asioDeviceInfo->minBufferSize = paAsioDriverInfo.bufferMinSize;
asioDeviceInfo->maxBufferSize = paAsioDriverInfo.bufferMaxSize;
asioDeviceInfo->preferredBufferSize = paAsioDriverInfo.bufferPreferredSize;
asioDeviceInfo->bufferGranularity = paAsioDriverInfo.bufferGranularity;
asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory(
asioHostApi->allocations,
sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels
+ deviceInfo->maxOutputChannels) );
if( !asioDeviceInfo->asioChannelInfos )
{
result = paInsufficientMemory;
goto error_unload;
}
int a;
for( a=0; a < deviceInfo->maxInputChannels; ++a ){
asioDeviceInfo->asioChannelInfos[a].channel = a;
asioDeviceInfo->asioChannelInfos[a].isInput = ASIOTrue;
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[a] );
if( asioError != ASE_OK )
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
goto error_unload;
}
}
for( a=0; a < deviceInfo->maxOutputChannels; ++a ){
int b = deviceInfo->maxInputChannels + a;
asioDeviceInfo->asioChannelInfos[b].channel = a;
asioDeviceInfo->asioChannelInfos[b].isInput = ASIOFalse;
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[b] );
if( asioError != ASE_OK )
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
goto error_unload;
}
}
/* unload the driver */
UnloadAsioDriver();
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
++(*hostApi)->info.deviceCount;
}
}
}
@ -1331,9 +1370,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
return result;
error_unload:
UnloadAsioDriver();
error:
if( asioHostApi )
{
@ -1744,7 +1780,7 @@ static unsigned long SelectHostBufferSizeForSpecifiedUserFramesPerBuffer(
do {
if( (x % userFramesPerBuffer) == 0 )
{
/* any power-of-two multiple of userFramesPerBuffer is acceptable */
/* any multiple of userFramesPerBuffer is acceptable */
result = x;
if( result >= targetBufferingLatencyFrames )
break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */
@ -1767,7 +1803,7 @@ static unsigned long SelectHostBufferSizeForSpecifiedUserFramesPerBuffer(
do {
if( (x % userFramesPerBuffer) == 0 )
{
/* any power-of-two multiple of userFramesPerBuffer is acceptable */
/* any multiple of userFramesPerBuffer is acceptable */
result = x;
if( result >= targetBufferingLatencyFrames )
break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */
@ -2447,10 +2483,10 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor ,
inputChannelCount ,
inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
hostInputSampleFormat , /* Host format. */
(hostInputSampleFormat | paNonInterleaved), /* Host format. */
outputChannelCount ,
outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
hostOutputSampleFormat , /* Host format. */
(hostOutputSampleFormat | paNonInterleaved), /* Host format. */
sampleRate ,
streamFlags ,
framesPerBuffer , /* Frames per ring buffer block. */
@ -3046,7 +3082,7 @@ previousIndex = index;
paTimeInfo.outputBufferDacTime = paTimeInfo.currentTime + theAsioStream->streamRepresentation.streamInfo.outputLatency;
*/
/* Disabled! Stopping and re-starting the stream causes an input overflow / output undeflow. S.Fischer */
/* Disabled! Stopping and re-starting the stream causes an input overflow / output underflow. S.Fischer */
#if 0
// detect underflows by checking inter-callback time > 2 buffer period
static double previousTime = -1;
@ -3498,6 +3534,7 @@ static PaError IsStreamActive( PaStream *s )
static PaTime GetStreamTime( PaStream *s )
{
(void) s; /* unused parameter */
return (double)timeGetTime() * .001;
}

View File

@ -125,87 +125,114 @@ static bool ensureChannelNameSize( int size )
*/
const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input )
{
struct PaUtilHostApiRepresentation *hostApi;
PaError err;
OSStatus error;
err = PaUtil_GetHostApiRepresentation( &hostApi, paCoreAudio );
assert(err == paNoError);
if( err != paNoError )
return NULL;
PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
AudioDeviceID hostApiDevice = macCoreHostApi->devIds[device];
UInt32 size = 0;
error = AudioDeviceGetPropertyInfo( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelName,
&size,
NULL );
if( error ) {
//try the CFString
CFStringRef name;
bool isDeviceName = false;
size = sizeof( name );
error = AudioDeviceGetProperty( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelNameCFString,
&size,
&name );
if( error ) { //as a last-ditch effort, get the device name. Later we'll append the channel number.
size = sizeof( name );
error = AudioDeviceGetProperty( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyDeviceNameCFString,
&size,
&name );
if( error )
return NULL;
isDeviceName = true;
}
if( isDeviceName ) {
name = CFStringCreateWithFormat( NULL, NULL, CFSTR( "%@: %d"), name, channelIndex + 1 );
}
CFIndex length = CFStringGetLength(name);
while( ensureChannelNameSize( length * sizeof(UniChar) + 1 ) ) {
if( CFStringGetCString( name, channelName, channelNameSize, kCFStringEncodingUTF8 ) ) {
if( isDeviceName )
CFRelease( name );
return channelName;
}
if( length == 0 )
++length;
length *= 2;
}
if( isDeviceName )
CFRelease( name );
return NULL;
}
//continue with C string:
if( !ensureChannelNameSize( size ) )
return NULL;
error = AudioDeviceGetProperty( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelName,
&size,
channelName );
if( error ) {
ERR( error );
return NULL;
}
return channelName;
struct PaUtilHostApiRepresentation *hostApi;
PaError err;
OSStatus error;
err = PaUtil_GetHostApiRepresentation( &hostApi, paCoreAudio );
assert(err == paNoError);
if( err != paNoError )
return NULL;
PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
AudioDeviceID hostApiDevice = macCoreHostApi->devIds[device];
CFStringRef nameRef;
/* First try with CFString */
UInt32 size = sizeof(nameRef);
error = AudioDeviceGetProperty( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelNameCFString,
&size,
&nameRef );
if( error )
{
/* try the C String */
size = 0;
error = AudioDeviceGetPropertyInfo( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelName,
&size,
NULL);
if( !error )
{
if( !ensureChannelNameSize( size ) )
return NULL;
error = AudioDeviceGetProperty( hostApiDevice,
channelIndex + 1,
input,
kAudioDevicePropertyChannelName,
&size,
channelName );
if( !error )
return channelName;
}
/* as a last-ditch effort, we use the device name and append the channel number. */
nameRef = CFStringCreateWithFormat( NULL, NULL, CFSTR( "%s: %d"), hostApi->deviceInfos[device]->name, channelIndex + 1 );
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef), kCFStringEncodingUTF8);;
if( !ensureChannelNameSize( size ) )
{
CFRelease( nameRef );
return NULL;
}
CFStringGetCString( nameRef, channelName, size+1, kCFStringEncodingUTF8 );
CFRelease( nameRef );
}
else
{
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef), kCFStringEncodingUTF8);;
if( !ensureChannelNameSize( size ) )
{
CFRelease( nameRef );
return NULL;
}
CFStringGetCString( nameRef, channelName, size+1, kCFStringEncodingUTF8 );
CFRelease( nameRef );
}
return channelName;
}
PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device,
long *minBufferSizeFrames, long *maxBufferSizeFrames )
{
PaError result;
PaUtilHostApiRepresentation *hostApi;
result = PaUtil_GetHostApiRepresentation( &hostApi, paCoreAudio );
if( result == paNoError )
{
PaDeviceIndex hostApiDeviceIndex;
result = PaUtil_DeviceIndexToHostApiDeviceIndex( &hostApiDeviceIndex, device, hostApi );
if( result == paNoError )
{
PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
AudioDeviceID macCoreDeviceId = macCoreHostApi->devIds[hostApiDeviceIndex];
AudioValueRange audioRange;
UInt32 propSize = sizeof( audioRange );
// return the size range for the output scope unless we only have inputs
Boolean isInput = 0;
if( macCoreHostApi->inheritedHostApiRep.deviceInfos[hostApiDeviceIndex]->maxOutputChannels == 0 )
isInput = 1;
result = WARNING(AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) );
*minBufferSizeFrames = audioRange.mMinimum;
*maxBufferSizeFrames = audioRange.mMaximum;
}
}
return result;
}
AudioDeviceID PaMacCore_GetStreamInputDevice( PaStream* s )
@ -280,7 +307,7 @@ static PaError OpenAndSetupOneAudioUnit(
/* for setting errors. */
#define PA_AUHAL_SET_LAST_HOST_ERROR( errorCode, errorText ) \
PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
PaUtil_SetLastHostErrorInfo( paCoreAudio, errorCode, errorText )
/*
* Callback called when starting or stopping a stream.
@ -625,26 +652,46 @@ static PaError InitializeDeviceInfo( PaMacAUHAL *auhalHostApi,
Float64 sampleRate;
char *name;
PaError err = paNoError;
CFStringRef nameRef;
UInt32 propSize;
VVDBUG(("InitializeDeviceInfo(): macCoreDeviceId=%ld\n", macCoreDeviceId));
memset(deviceInfo, 0, sizeof(deviceInfo));
memset(deviceInfo, 0, sizeof(PaDeviceInfo));
deviceInfo->structVersion = 2;
deviceInfo->hostApi = hostApiIndex;
/* Get the device name. Fail if we can't get it. */
err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
/* Get the device name using CFString */
propSize = sizeof(nameRef);
err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceNameCFString, &propSize, &nameRef));
if (err)
return err;
{
/* Get the device name using c string. Fail if we can't get it. */
err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
if (err)
return err;
name = PaUtil_GroupAllocateMemory(auhalHostApi->allocations,propSize);
if ( !name )
return paInsufficientMemory;
err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name));
if (err)
return err;
name = PaUtil_GroupAllocateMemory(auhalHostApi->allocations,propSize+1);
if ( !name )
return paInsufficientMemory;
err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name));
if (err)
return err;
}
else
{
/* valid CFString so we just allocate a c string big enough to contain the data */
propSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef), kCFStringEncodingUTF8);
name = PaUtil_GroupAllocateMemory(auhalHostApi->allocations, propSize+1);
if ( !name )
{
CFRelease(nameRef);
return paInsufficientMemory;
}
CFStringGetCString(nameRef, name, propSize+1, kCFStringEncodingUTF8);
CFRelease(nameRef);
}
deviceInfo->name = name;
/* Try to get the default sample rate. Don't fail if we can't get this. */
@ -990,18 +1037,19 @@ static void UpdateTimeStampOffsets( PaMacCoreStream *stream )
}
/* ================================================================================= */
/* Query sample rate property. */
static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, AudioDeviceID deviceID, Boolean isInput )
/* can be used to update from nominal or actual sample rate */
static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, AudioDeviceID deviceID, Boolean isInput, AudioDevicePropertyID sampleRatePropertyID )
{
PaMacCoreDeviceProperties * deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties;
/* FIXME: not sure if this should be the sample rate of the output device or the output unit */
Float64 actualSampleRate = deviceProperties->sampleRate;
Float64 sampleRate = 0.0;
UInt32 propSize = sizeof(Float64);
OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, &propSize, &actualSampleRate);
if( (osErr == noErr) && (actualSampleRate > 1000.0) ) // avoid divide by zero if there's an error
OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, sampleRatePropertyID, &propSize, &sampleRate);
if( (osErr == noErr) && (sampleRate > 1000.0) ) /* avoid divide by zero if there's an error */
{
deviceProperties->sampleRate = actualSampleRate;
deviceProperties->samplePeriod = 1.0 / actualSampleRate;
deviceProperties->sampleRate = sampleRate;
deviceProperties->samplePeriod = 1.0 / sampleRate;
}
return osErr;
}
@ -1013,7 +1061,7 @@ static OSStatus AudioDevicePropertyActualSampleRateListenerProc( AudioDeviceID i
// Make sure the callback is operating on a stream that is still valid!
assert( stream->streamRepresentation.magic == PA_STREAM_MAGIC );
OSStatus osErr = UpdateSampleRateFromDeviceProperty( stream, inDevice, isInput );
OSStatus osErr = UpdateSampleRateFromDeviceProperty( stream, inDevice, isInput, kAudioDevicePropertyActualSampleRate );
if( osErr == noErr )
{
UpdateTimeStampOffsets( stream );
@ -1077,9 +1125,6 @@ static OSStatus SetupDevicePropertyListeners( PaMacCoreStream *stream, AudioDevi
OSStatus osErr = noErr;
PaMacCoreDeviceProperties *deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties;
// Start with the current values for the device properties.
UpdateSampleRateFromDeviceProperty( stream, deviceID, isInput );
if( (osErr = QueryUInt32DeviceProperty( deviceID, isInput,
kAudioDevicePropertyLatency, &deviceProperties->deviceLatency )) != noErr ) return osErr;
if( (osErr = QueryUInt32DeviceProperty( deviceID, isInput,
@ -1598,12 +1643,19 @@ static UInt32 CalculateOptimalBufferSize( PaMacAUHAL *auhalHostApi,
resultBufferSizeFrames = MAX( resultBufferSizeFrames, (UInt32) variableLatencyFrames );
}
// can't have zero frames. code to round up to next user buffer requires non-zero
resultBufferSizeFrames = MAX( resultBufferSizeFrames, 1 );
if( requestedFramesPerBuffer != paFramesPerBufferUnspecified )
{
// make host buffer the next highest integer multiple of user frames per buffer
UInt32 n = (resultBufferSizeFrames + requestedFramesPerBuffer - 1) / requestedFramesPerBuffer;
resultBufferSizeFrames = n * requestedFramesPerBuffer;
// FIXME: really we should be searching for a multiple of requestedFramesPerBuffer
// that is >= suggested latency and also fits within device buffer min/max
}else{
VDBUG( ("Block Size unspecified. Based on Latency, the user wants a Block Size near: %ld.\n",
resultBufferSizeFrames ) );
@ -1737,25 +1789,16 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
do is initialize everything so that if we fail, we know what hasn't
been touched.
*/
stream->inputAudioBufferList.mBuffers[0].mData = NULL;
stream->inputRingBuffer.buffer = NULL;
bzero( &stream->blio, sizeof( PaMacBlio ) );
/*
bzero( stream, sizeof( PaMacCoreStream ) );
/*
stream->blio.inputRingBuffer.buffer = NULL;
stream->blio.outputRingBuffer.buffer = NULL;
stream->blio.inputSampleFormat = inputParameters?inputParameters->sampleFormat:0;
stream->blio.inputSampleSize = computeSampleSizeFromFormat(stream->blio.inputSampleFormat);
stream->blio.outputSampleFormat=outputParameters?outputParameters->sampleFormat:0;
stream->blio.outputSampleSize = computeSampleSizeFromFormat(stream->blio.outputSampleFormat);
*/
stream->inputSRConverter = NULL;
stream->inputUnit = NULL;
stream->outputUnit = NULL;
stream->inputFramesPerBuffer = 0;
stream->outputFramesPerBuffer = 0;
stream->bufferProcessorIsInitialized = FALSE;
stream->timingInformationMutexIsInitialized = 0;
*/
/* assert( streamCallback ) ; */ /* only callback mode is implemented */
if( streamCallback )
@ -1878,14 +1921,13 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/*
* If input and output devs are different or we are doing SR conversion,
* we also need a
* ring buffer to store inpt data while waiting for output
* data.
* we also need a ring buffer to store input data while waiting for
* output data.
*/
if( (stream->outputUnit && (stream->inputUnit != stream->outputUnit))
|| stream->inputSRConverter )
{
/* May want the ringSize ot initial position in
/* May want the ringSize or initial position in
ring buffer to depend somewhat on sample rate change */
void *data;
@ -1908,7 +1950,15 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
/* now we can initialize the ring buffer */
PaUtil_InitializeRingBuffer( &stream->inputRingBuffer, szfl*inputParameters->channelCount, ringSize, data ) ;
result = PaUtil_InitializeRingBuffer( &stream->inputRingBuffer, szfl*inputParameters->channelCount, ringSize, data );
if( result != 0 )
{
/* The only reason this should fail is if ringSize is not a power of 2, which we do not anticipate happening. */
result = paUnanticipatedHostError;
free(data);
goto error;
}
/* advance the read point a little, so we are reading from the
middle of the buffer */
if( stream->outputUnit )
@ -1930,12 +1980,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->outputFramesPerBuffer,
sampleRate );
result = initializeBlioRingBuffers( &stream->blio,
inputParameters?inputParameters->sampleFormat:0 ,
outputParameters?outputParameters->sampleFormat:0 ,
MAX(stream->inputFramesPerBuffer,stream->outputFramesPerBuffer),
inputParameters ? inputParameters->sampleFormat : 0,
outputParameters ? outputParameters->sampleFormat : 0,
ringSize,
inputParameters?inputChannelCount:0 ,
outputParameters?outputChannelCount:0 ) ;
inputParameters ? inputChannelCount : 0,
outputParameters ? outputChannelCount : 0 ) ;
if( result != paNoError )
goto error;
@ -1993,53 +2042,48 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
stream->sampleRate = sampleRate;
stream->outDeviceSampleRate = 0;
if( stream->outputUnit ) {
Float64 rate;
UInt32 size = sizeof( rate );
result = ERR( AudioDeviceGetProperty( stream->outputDevice,
0,
FALSE,
kAudioDevicePropertyNominalSampleRate,
&size, &rate ) );
if( result )
goto error;
stream->outDeviceSampleRate = rate;
}
stream->inDeviceSampleRate = 0;
if( stream->inputUnit ) {
Float64 rate;
UInt32 size = sizeof( rate );
result = ERR( AudioDeviceGetProperty( stream->inputDevice,
0,
TRUE,
kAudioDevicePropertyNominalSampleRate,
&size, &rate ) );
if( result )
goto error;
stream->inDeviceSampleRate = rate;
}
stream->sampleRate = sampleRate;
stream->userInChan = inputChannelCount;
stream->userOutChan = outputChannelCount;
// Setup property listeners for timestamp and latency calculations.
pthread_mutex_init( &stream->timingInformationMutex, NULL );
stream->timingInformationMutexIsInitialized = 1;
InitializeDeviceProperties( &stream->inputProperties );
InitializeDeviceProperties( &stream->outputProperties );
InitializeDeviceProperties( &stream->inputProperties ); // zeros the struct. doesn't actually init it to useful values
InitializeDeviceProperties( &stream->outputProperties ); // zeros the struct. doesn't actually init it to useful values
if( stream->outputUnit )
{
Boolean isInput = FALSE;
// Start with the current values for the device properties.
// Init with nominal sample rate. Use actual sample rate where available
result = ERR( UpdateSampleRateFromDeviceProperty(
stream, stream->outputDevice, isInput, kAudioDevicePropertyNominalSampleRate ) );
if( result )
goto error; /* fail if we can't even get a nominal device sample rate */
UpdateSampleRateFromDeviceProperty( stream, stream->outputDevice, isInput, kAudioDevicePropertyActualSampleRate );
SetupDevicePropertyListeners( stream, stream->outputDevice, isInput );
}
if( stream->inputUnit )
{
Boolean isInput = TRUE;
// as above
result = ERR( UpdateSampleRateFromDeviceProperty(
stream, stream->inputDevice, isInput, kAudioDevicePropertyNominalSampleRate ) );
if( result )
goto error;
UpdateSampleRateFromDeviceProperty( stream, stream->inputDevice, isInput, kAudioDevicePropertyActualSampleRate );
SetupDevicePropertyListeners( stream, stream->inputDevice, isInput );
}
UpdateTimeStampOffsets( stream );
// Setup copies to be used by audio callback.
// Setup timestamp copies to be used by audio callback.
stream->timestampOffsetCombined_ioProcCopy = stream->timestampOffsetCombined;
stream->timestampOffsetInputDevice_ioProcCopy = stream->timestampOffsetInputDevice;
stream->timestampOffsetOutputDevice_ioProcCopy = stream->timestampOffsetOutputDevice;
@ -2113,11 +2157,11 @@ static OSStatus AudioIOProc( void *inRefCon,
const bool isRender = inBusNumber == OUTPUT_ELEMENT;
int callbackResult = paContinue ;
double hostTimeStampInPaTime = HOST_TIME_TO_PA_TIME(inTimeStamp->mHostTime);
VVDBUG(("AudioIOProc()\n"));
PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
/* -----------------------------------------------------------------*\
This output may be useful for debugging,
But printing durring the callback is a bad enough idea that
@ -2218,7 +2262,8 @@ static OSStatus AudioIOProc( void *inRefCon,
*
*/
OSStatus err = 0;
unsigned long frames;
unsigned long frames;
long bytesPerFrame = sizeof( float ) * ioData->mBuffers[0].mNumberChannels;
/* -- start processing -- */
PaUtil_BeginBufferProcessing( &(stream->bufferProcessor),
@ -2229,8 +2274,8 @@ static OSStatus AudioIOProc( void *inRefCon,
/* -- compute frames. do some checks -- */
assert( ioData->mNumberBuffers == 1 );
assert( ioData->mBuffers[0].mNumberChannels == stream->userOutChan );
frames = ioData->mBuffers[0].mDataByteSize;
frames /= sizeof( float ) * ioData->mBuffers[0].mNumberChannels;
frames = ioData->mBuffers[0].mDataByteSize / bytesPerFrame;
/* -- copy and process input data -- */
err= AudioUnitRender(stream->inputUnit,
ioActionFlags,
@ -2238,9 +2283,10 @@ static OSStatus AudioIOProc( void *inRefCon,
INPUT_ELEMENT,
inNumberFrames,
&stream->inputAudioBufferList );
/* FEEDBACK: I'm not sure what to do when this call fails. There's nothing in the PA API to
* do about failures in the callback system. */
assert( !err );
if(err != noErr)
{
goto stop_stream;
}
PaUtil_SetInputFrameCount( &(stream->bufferProcessor), frames );
PaUtil_SetInterleavedInputChannels( &(stream->bufferProcessor),
@ -2268,7 +2314,8 @@ static OSStatus AudioIOProc( void *inRefCon,
* and into the PA buffer processor. If sample rate conversion
* is required on input, that is done here as well.
*/
unsigned long frames;
unsigned long frames;
long bytesPerFrame = sizeof( float ) * ioData->mBuffers[0].mNumberChannels;
/* Sometimes, when stopping a duplex stream we get erroneous
xrun flags, so if this is our last run, clear the flags. */
@ -2290,8 +2337,7 @@ static OSStatus AudioIOProc( void *inRefCon,
/* -- Copy and process output data -- */
assert( ioData->mNumberBuffers == 1 );
frames = ioData->mBuffers[0].mDataByteSize;
frames /= sizeof( float ) * ioData->mBuffers[0].mNumberChannels;
frames = ioData->mBuffers[0].mDataByteSize / bytesPerFrame;
assert( ioData->mBuffers[0].mNumberChannels == stream->userOutChan );
PaUtil_SetOutputFrameCount( &(stream->bufferProcessor), frames );
PaUtil_SetInterleavedOutputChannels( &(stream->bufferProcessor),
@ -2305,6 +2351,8 @@ static OSStatus AudioIOProc( void *inRefCon,
/* Here, we read the data out of the ring buffer, through the
audio converter. */
int inChan = stream->inputAudioBufferList.mBuffers[0].mNumberChannels;
long bytesPerFrame = flsz * inChan;
if( stream->inputSRConverter )
{
OSStatus err;
@ -2318,14 +2366,22 @@ static OSStatus AudioIOProc( void *inRefCon,
&size,
(void *)&data );
if( err == RING_BUFFER_EMPTY )
{ /*the ring buffer callback underflowed */
{ /* the ring buffer callback underflowed */
err = 0;
bzero( ((char *)data) + size, sizeof(data)-size );
stream->xrunFlags |= paInputUnderflow;
/* The ring buffer can underflow normally when the stream is stopping.
* So only report an error if the stream is active. */
if( stream->state == ACTIVE )
{
stream->xrunFlags |= paInputUnderflow;
}
}
ERR( err );
assert( !err );
if(err != noErr)
{
goto stop_stream;
}
PaUtil_SetInputFrameCount( &(stream->bufferProcessor), frames );
PaUtil_SetInterleavedInputChannels( &(stream->bufferProcessor),
0,
@ -2342,7 +2398,7 @@ static OSStatus AudioIOProc( void *inRefCon,
AudioConverter would otherwise handle for us. */
void *data1, *data2;
ring_buffer_size_t size1, size2;
PaUtil_GetRingBufferReadRegions( &stream->inputRingBuffer,
ring_buffer_size_t framesReadable = PaUtil_GetRingBufferReadRegions( &stream->inputRingBuffer,
frames,
&data1, &size1,
&data2, &size2 );
@ -2357,14 +2413,21 @@ static OSStatus AudioIOProc( void *inRefCon,
PaUtil_EndBufferProcessing( &(stream->bufferProcessor),
&callbackResult );
PaUtil_AdvanceRingBufferReadIndex(&stream->inputRingBuffer, size1 );
} else if( size1 + size2 < frames ) {
} else if( framesReadable < frames ) {
long sizeBytes1 = size1 * bytesPerFrame;
long sizeBytes2 = size2 * bytesPerFrame;
/*we underflowed. take what data we can, zero the rest.*/
unsigned char data[frames*inChan*flsz];
if( size1 )
memcpy( data, data1, size1 );
if( size2 )
memcpy( data+size1, data2, size2 );
bzero( data+size1+size2, frames*flsz*inChan - size1 - size2 );
unsigned char data[ frames * bytesPerFrame ];
if( size1 > 0 )
{
memcpy( data, data1, sizeBytes1 );
}
if( size2 > 0 )
{
memcpy( data+sizeBytes1, data2, sizeBytes2 );
}
bzero( data+sizeBytes1+sizeBytes2, (frames*bytesPerFrame) - sizeBytes1 - sizeBytes2 );
PaUtil_SetInputFrameCount( &(stream->bufferProcessor), frames );
PaUtil_SetInterleavedInputChannels( &(stream->bufferProcessor),
@ -2375,7 +2438,7 @@ static OSStatus AudioIOProc( void *inRefCon,
PaUtil_EndBufferProcessing( &(stream->bufferProcessor),
&callbackResult );
PaUtil_AdvanceRingBufferReadIndex( &stream->inputRingBuffer,
size1+size2 );
framesReadable );
/* flag underflow */
stream->xrunFlags |= paInputUnderflow;
} else {
@ -2393,7 +2456,7 @@ static OSStatus AudioIOProc( void *inRefCon,
framesProcessed =
PaUtil_EndBufferProcessing( &(stream->bufferProcessor),
&callbackResult );
PaUtil_AdvanceRingBufferReadIndex(&stream->inputRingBuffer, size1+size2 );
PaUtil_AdvanceRingBufferReadIndex(&stream->inputRingBuffer, framesReadable );
}
}
} else {
@ -2424,20 +2487,23 @@ static OSStatus AudioIOProc( void *inRefCon,
if( err == -10874 )
inNumberFrames /= 2;
} while( err == -10874 && inNumberFrames > 1 );
/* FEEDBACK: I'm not sure what to do when this call fails */
ERR( err );
assert( !err );
if(err != noErr)
{
goto stop_stream;
}
if( stream->inputSRConverter || stream->outputUnit )
{
/* If this is duplex or we use a converter, put the data
into the ring buffer. */
long bytesIn, bytesOut;
bytesIn = sizeof( float ) * inNumberFrames * chan;
bytesOut = PaUtil_WriteRingBuffer( &stream->inputRingBuffer,
ring_buffer_size_t framesWritten = PaUtil_WriteRingBuffer( &stream->inputRingBuffer,
stream->inputAudioBufferList.mBuffers[0].mData,
inNumberFrames );
if( bytesIn != bytesOut )
stream->xrunFlags |= paInputOverflow ;
if( framesWritten != inNumberFrames )
{
stream->xrunFlags |= paInputOverflow ;
}
}
else
{
@ -2469,11 +2535,11 @@ static OSStatus AudioIOProc( void *inRefCon,
* chunks, and let the BufferProcessor deal with the rest.
*
*/
/*This might be too big or small depending on SR conversion*/
/* This might be too big or small depending on SR conversion. */
float data[ chan * inNumberFrames ];
OSStatus err;
do
{ /*Run the buffer processor until we are out of data*/
{ /* Run the buffer processor until we are out of data. */
UInt32 size;
long f;
@ -2486,7 +2552,11 @@ static OSStatus AudioIOProc( void *inRefCon,
(void *)data );
if( err != RING_BUFFER_EMPTY )
ERR( err );
assert( err == 0 || err == RING_BUFFER_EMPTY );
if( err != noErr && err != RING_BUFFER_EMPTY )
{
goto stop_stream;
}
f = size / ( chan * sizeof(float) );
PaUtil_SetInputFrameCount( &(stream->bufferProcessor), f );
@ -2509,24 +2579,24 @@ static OSStatus AudioIOProc( void *inRefCon,
}
}
switch( callbackResult )
{
case paContinue: break;
case paComplete:
case paAbort:
stream->state = CALLBACK_STOPPED ;
if( stream->outputUnit )
AudioOutputUnitStop(stream->outputUnit);
if( stream->inputUnit )
AudioOutputUnitStop(stream->inputUnit);
break;
}
// Should we return successfully or fall through to stopping the stream?
if( callbackResult == paContinue )
{
PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
return noErr;
}
PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
return noErr;
stop_stream:
stream->state = CALLBACK_STOPPED ;
if( stream->outputUnit )
AudioOutputUnitStop(stream->outputUnit);
if( stream->inputUnit )
AudioOutputUnitStop(stream->inputUnit);
PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
return noErr;
}
/*
When CloseStream() is called, the multi-api layer ensures that
the stream has already been stopped or aborted.
@ -2654,18 +2724,10 @@ static ComponentResult BlockWhileAudioUnitIsRunning( AudioUnit audioUnit, AudioU
return noErr;
}
static PaError StopStream( PaStream *s )
static PaError FinishStoppingStream( PaMacCoreStream *stream )
{
PaMacCoreStream *stream = (PaMacCoreStream*)s;
OSStatus result = noErr;
PaError paErr;
VVDBUG(("StopStream()\n"));
VDBUG( ("Waiting for BLIO.\n") );
waitUntilBlioWriteBufferIsFlushed( &stream->blio );
VDBUG( ( "Stopping stream.\n" ) );
stream->state = STOPPING;
#define ERR_WRAP(mac_err) do { result = mac_err ; if ( result != noErr ) return ERR(result) ; } while(0)
/* -- stop and reset -- */
@ -2717,12 +2779,34 @@ static PaError StopStream( PaStream *s )
#undef ERR_WRAP
}
/* Block until buffer is empty then stop the stream. */
static PaError StopStream( PaStream *s )
{
PaError paErr;
PaMacCoreStream *stream = (PaMacCoreStream*)s;
VVDBUG(("StopStream()\n"));
/* Tell WriteStream to stop filling the buffer. */
stream->state = STOPPING;
if( stream->userOutChan > 0 ) /* Does this stream do output? */
{
size_t maxHostFrames = MAX( stream->inputFramesPerBuffer, stream->outputFramesPerBuffer );
VDBUG( ("Waiting for write buffer to be drained.\n") );
paErr = waitUntilBlioWriteBufferIsEmpty( &stream->blio, stream->sampleRate,
maxHostFrames );
VDBUG( ( "waitUntilBlioWriteBufferIsEmpty returned %d\n", paErr ) );
}
return FinishStoppingStream( stream );
}
/* Immediately stop the stream. */
static PaError AbortStream( PaStream *s )
{
VVDBUG(("AbortStream()->StopStream()\n"));
VDBUG( ( "Aborting stream.\n" ) );
/* We have nothing faster than StopStream. */
return StopStream(s);
PaMacCoreStream *stream = (PaMacCoreStream*)s;
VDBUG( ( "AbortStream()\n" ) );
stream->state = STOPPING;
return FinishStoppingStream( stream );
}

View File

@ -108,14 +108,16 @@ static size_t computeSampleSizeFromFormatPow2( PaSampleFormat format )
*
*/
/* This should be called with the relevant info when initializing a stream for
callback. */
/**
* This should be called with the relevant info when initializing a stream for callback.
*
* @param ringBufferSizeInFrames must be a power of 2
*/
PaError initializeBlioRingBuffers(
PaMacBlio *blio,
PaSampleFormat inputSampleFormat,
PaSampleFormat outputSampleFormat,
size_t framesPerBuffer,
long ringBufferSize,
long ringBufferSizeInFrames,
int inChan,
int outChan )
{
@ -126,20 +128,19 @@ PaError initializeBlioRingBuffers(
/* zeroify things */
bzero( blio, sizeof( PaMacBlio ) );
/* this is redundant, but the buffers are used to check
if the bufffers have been initialized, so we do it explicitly. */
if the buffers have been initialized, so we do it explicitly. */
blio->inputRingBuffer.buffer = NULL;
blio->outputRingBuffer.buffer = NULL;
/* initialize simple data */
blio->ringBufferFrames = ringBufferSize;
blio->ringBufferFrames = ringBufferSizeInFrames;
blio->inputSampleFormat = inputSampleFormat;
blio->inputSampleSizeActual = computeSampleSizeFromFormat(inputSampleFormat);
blio->inputSampleSizePow2 = computeSampleSizeFromFormatPow2(inputSampleFormat);
blio->inputSampleSizePow2 = computeSampleSizeFromFormatPow2(inputSampleFormat); // FIXME: WHY?
blio->outputSampleFormat = outputSampleFormat;
blio->outputSampleSizeActual = computeSampleSizeFromFormat(outputSampleFormat);
blio->outputSampleSizePow2 = computeSampleSizeFromFormatPow2(outputSampleFormat);
blio->framesPerBuffer = framesPerBuffer;
blio->inChan = inChan;
blio->outChan = outChan;
blio->statusFlags = 0;
@ -163,7 +164,7 @@ PaError initializeBlioRingBuffers(
result = UNIX_ERR( pthread_cond_init( &(blio->outputCond), NULL ) );
#endif
if( inChan ) {
data = calloc( ringBufferSize, blio->inputSampleSizePow2*inChan );
data = calloc( ringBufferSizeInFrames, blio->inputSampleSizePow2 * inChan );
if( !data )
{
result = paInsufficientMemory;
@ -172,12 +173,13 @@ PaError initializeBlioRingBuffers(
err = PaUtil_InitializeRingBuffer(
&blio->inputRingBuffer,
1, ringBufferSize*blio->inputSampleSizePow2*inChan,
blio->inputSampleSizePow2 * inChan,
ringBufferSizeInFrames,
data );
assert( !err );
}
if( outChan ) {
data = calloc( ringBufferSize, blio->outputSampleSizePow2*outChan );
data = calloc( ringBufferSizeInFrames, blio->outputSampleSizePow2 * outChan );
if( !data )
{
result = paInsufficientMemory;
@ -186,7 +188,8 @@ PaError initializeBlioRingBuffers(
err = PaUtil_InitializeRingBuffer(
&blio->outputRingBuffer,
1, ringBufferSize*blio->outputSampleSizePow2*outChan,
blio->outputSampleSizePow2 * outChan,
ringBufferSizeInFrames,
data );
assert( !err );
}
@ -266,12 +269,11 @@ PaError resetBlioRingBuffers( PaMacBlio *blio )
#endif
blio->statusFlags = 0;
if( blio->outputRingBuffer.buffer ) {
PaUtil_FlushRingBuffer( &blio->outputRingBuffer );
bzero( blio->outputRingBuffer.buffer,
blio->outputRingBuffer.bufferSize );
/* Advance buffer */
PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->ringBufferFrames*blio->outputSampleSizeActual*blio->outChan );
//PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize );
PaUtil_FlushRingBuffer( &blio->outputRingBuffer );
/* Fill the buffer with zeros. */
bzero( blio->outputRingBuffer.buffer,
blio->outputRingBuffer.bufferSize * blio->outputRingBuffer.elementSizeBytes );
PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->ringBufferFrames );
/* Update isOutputFull. */
#ifdef PA_MAC__BLIO_MUTEX
@ -280,16 +282,14 @@ PaError resetBlioRingBuffers( PaMacBlio *blio )
goto error;
#endif
/*
printf( "------%d\n" , blio->framesPerBuffer );
printf( "------%d\n" , blio->outChan );
printf( "------%d\n" , blio->outputSampleSize );
printf( "------%d\n" , blio->framesPerBuffer*blio->outChan*blio->outputSampleSize );
*/
}
if( blio->inputRingBuffer.buffer ) {
PaUtil_FlushRingBuffer( &blio->inputRingBuffer );
bzero( blio->inputRingBuffer.buffer,
blio->inputRingBuffer.bufferSize );
blio->inputRingBuffer.bufferSize * blio->inputRingBuffer.elementSizeBytes );
/* Update isInputEmpty. */
#ifdef PA_MAC__BLIO_MUTEX
result = blioSetIsInputEmpty( blio, true );
@ -344,29 +344,32 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
void *userData )
{
PaMacBlio *blio = (PaMacBlio*)userData;
long avail;
long toRead;
long toWrite;
long read;
long written;
ring_buffer_size_t framesAvailable;
ring_buffer_size_t framesToTransfer;
ring_buffer_size_t framesTransferred;
/* set flags returned by OS: */
OSAtomicOr32( statusFlags, &blio->statusFlags ) ;
/* --- Handle Input Buffer --- */
if( blio->inChan ) {
avail = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );
framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );
/* check for underflow */
if( avail < frameCount * blio->inputSampleSizeActual * blio->inChan )
OSAtomicOr32( paInputOverflow, &blio->statusFlags );
if( framesAvailable < frameCount )
{
OSAtomicOr32( paInputOverflow, &blio->statusFlags );
framesToTransfer = framesAvailable;
}
else
{
framesToTransfer = (ring_buffer_size_t)frameCount;
}
toRead = MIN( avail, frameCount * blio->inputSampleSizeActual * blio->inChan );
/* copy the data */
/* Copy the data from the audio input to the application ring buffer. */
/*printf( "reading %d\n", toRead );*/
read = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, toRead );
assert( toRead == read );
framesTransferred = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, framesToTransfer );
assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX
/* Priority inversion. See notes below. */
blioSetIsInputEmpty( blio, false );
@ -376,21 +379,31 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
/* --- Handle Output Buffer --- */
if( blio->outChan ) {
avail = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
/* check for underflow */
if( avail < frameCount * blio->outputSampleSizeActual * blio->outChan )
OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );
if( framesAvailable < frameCount )
{
/* zero out the end of the output buffer that we do not have data for */
framesToTransfer = framesAvailable;
toWrite = MIN( avail, frameCount * blio->outputSampleSizeActual * blio->outChan );
size_t bytesPerFrame = blio->outputSampleSizeActual * blio->outChan;
size_t offsetInBytes = framesToTransfer * bytesPerFrame;
size_t countInBytes = (frameCount - framesToTransfer) * bytesPerFrame;
bzero( ((char *)output) + offsetInBytes, countInBytes );
OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );
framesToTransfer = framesAvailable;
}
else
{
framesToTransfer = (ring_buffer_size_t)frameCount;
}
if( toWrite != frameCount * blio->outputSampleSizeActual * blio->outChan )
bzero( ((char *)output)+toWrite,
frameCount * blio->outputSampleSizeActual * blio->outChan - toWrite );
/* copy the data */
/*printf( "writing %d\n", toWrite );*/
written = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, toWrite );
assert( toWrite == written );
framesTransferred = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, framesToTransfer );
assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX
/* We have a priority inversion here. However, we will only have to
wait if this was true and is now false, which means we've got
@ -405,24 +418,25 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
PaError ReadStream( PaStream* stream,
void *buffer,
unsigned long frames )
unsigned long framesRequested )
{
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
char *cbuf = (char *) buffer;
PaError ret = paNoError;
VVDBUG(("ReadStream()\n"));
while( frames > 0 ) {
long avail;
long toRead;
while( framesRequested > 0 ) {
ring_buffer_size_t framesAvailable;
ring_buffer_size_t framesToTransfer;
ring_buffer_size_t framesTransferred;
do {
avail = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
/*
printf( "Read Buffer is %%%g full: %ld of %ld.\n",
100 * (float)avail / (float) blio->inputRingBuffer.bufferSize,
avail, blio->inputRingBuffer.bufferSize );
framesAvailable, blio->inputRingBuffer.bufferSize );
*/
if( avail == 0 ) {
if( framesAvailable == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX
/**block when empty*/
ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) );
@ -440,14 +454,13 @@ PaError ReadStream( PaStream* stream,
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif
}
} while( avail == 0 );
toRead = MIN( avail, frames * blio->inputSampleSizeActual * blio->inChan );
toRead -= toRead % blio->inputSampleSizeActual * blio->inChan ;
PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, toRead );
cbuf += toRead;
frames -= toRead / ( blio->inputSampleSizeActual * blio->inChan );
} while( framesAvailable == 0 );
framesToTransfer = (ring_buffer_size_t) MIN( framesAvailable, framesRequested );
framesTransferred = PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, framesToTransfer );
cbuf += framesTransferred * blio->inputSampleSizeActual * blio->inChan;
framesRequested -= framesTransferred;
if( toRead == avail ) {
if( framesToTransfer == framesAvailable ) {
#ifdef PA_MAC_BLIO_MUTEX
/* we just emptied the buffer, so we need to mark it as empty. */
ret = blioSetIsInputEmpty( blio, true );
@ -456,8 +469,10 @@ PaError ReadStream( PaStream* stream,
/* of course, in the meantime, the callback may have put some sats
in, so
so check for that, too, to avoid a race condition. */
/* FIXME - this does not seem to fix any race condition. */
if( PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) ) {
blioSetIsInputEmpty( blio, false );
/* FIXME - why check? ret has not been set? */
if( ret )
return ret;
}
@ -467,6 +482,7 @@ PaError ReadStream( PaStream* stream,
/* Report either paNoError or paInputOverflowed. */
/* may also want to report other errors, but this is non-standard. */
/* FIXME should not clobber ret, use if(blio->statusFlags & paInputOverflow) */
ret = blio->statusFlags & paInputOverflow;
/* report underflow only once: */
@ -481,25 +497,27 @@ PaError ReadStream( PaStream* stream,
PaError WriteStream( PaStream* stream,
const void *buffer,
unsigned long frames )
unsigned long framesRequested )
{
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
PaMacCoreStream *macStream = (PaMacCoreStream*)stream;
PaMacBlio *blio = &macStream->blio;
char *cbuf = (char *) buffer;
PaError ret = paNoError;
VVDBUG(("WriteStream()\n"));
while( frames > 0 ) {
long avail = 0;
long toWrite;
while( framesRequested > 0 && macStream->state != STOPPING ) {
ring_buffer_size_t framesAvailable;
ring_buffer_size_t framesToTransfer;
ring_buffer_size_t framesTransferred;
do {
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
/*
printf( "Write Buffer is %%%g full: %ld of %ld.\n",
100 - 100 * (float)avail / (float) blio->outputRingBuffer.bufferSize,
avail, blio->outputRingBuffer.bufferSize );
framesAvailable, blio->outputRingBuffer.bufferSize );
*/
if( avail == 0 ) {
if( framesAvailable == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX
/*block while full*/
ret = UNIX_ERR( pthread_mutex_lock( &blio->outputMutex ) );
@ -517,16 +535,20 @@ PaError WriteStream( PaStream* stream,
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif
}
} while( avail == 0 );
} while( framesAvailable == 0 && macStream->state != STOPPING );
toWrite = MIN( avail, frames * blio->outputSampleSizeActual * blio->outChan );
toWrite -= toWrite % blio->outputSampleSizeActual * blio->outChan ;
PaUtil_WriteRingBuffer( &blio->outputRingBuffer, (void *)cbuf, toWrite );
cbuf += toWrite;
frames -= toWrite / ( blio->outputSampleSizeActual * blio->outChan );
if( macStream->state == STOPPING )
{
break;
}
framesToTransfer = MIN( framesAvailable, framesRequested );
framesTransferred = PaUtil_WriteRingBuffer( &blio->outputRingBuffer, (void *)cbuf, framesToTransfer );
cbuf += framesTransferred * blio->outputSampleSizeActual * blio->outChan;
framesRequested -= framesTransferred;
#ifdef PA_MAC_BLIO_MUTEX
if( toWrite == avail ) {
if( framesToTransfer == framesAvailable ) {
/* we just filled up the buffer, so we need to mark it as filled. */
ret = blioSetIsOutputFull( blio, true );
if( ret )
@ -535,6 +557,7 @@ PaError WriteStream( PaStream* stream,
so check for that, too, to avoid a race condition. */
if( PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ) ) {
blioSetIsOutputFull( blio, false );
/* FIXME remove or review this code, does not fix race, ret not set! */
if( ret )
return ret;
}
@ -542,42 +565,65 @@ PaError WriteStream( PaStream* stream,
#endif
}
/* Report either paNoError or paOutputUnderflowed. */
/* may also want to report other errors, but this is non-standard. */
ret = blio->statusFlags & paOutputUnderflow;
if ( macStream->state == STOPPING )
{
ret = paInternalError;
}
else if (ret == paNoError )
{
/* Test for underflow. */
ret = blio->statusFlags & paOutputUnderflow;
/* report underflow only once: */
if( ret ) {
OSAtomicAnd32( (uint32_t)(~paOutputUnderflow), &blio->statusFlags );
ret = paOutputUnderflowed;
/* report underflow only once: */
if( ret )
{
OSAtomicAnd32( (uint32_t)(~paOutputUnderflow), &blio->statusFlags );
ret = paOutputUnderflowed;
}
}
return ret;
}
/*
*
* Wait until the data in the buffer has finished playing.
*/
void waitUntilBlioWriteBufferIsFlushed( PaMacBlio *blio )
PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate,
size_t framesPerBuffer )
{
PaError result = paNoError;
if( blio->outputRingBuffer.buffer ) {
long avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
while( avail != blio->outputRingBuffer.bufferSize ) {
if( avail == 0 )
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
}
}
}
ring_buffer_size_t framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
/* Calculate when we should give up waiting. To be safe wait for two extra periods. */
PaTime now = PaUtil_GetTime();
PaTime startTime = now;
PaTime timeoutTime = startTime + (framesLeft + (2 * framesPerBuffer)) / sampleRate;
long msecPerBuffer = 1 + (long)( 1000.0 * framesPerBuffer / sampleRate);
while( framesLeft > 0 && now < timeoutTime ) {
VDBUG(( "waitUntilBlioWriteBufferIsFlushed: framesLeft = %d, framesPerBuffer = %ld\n",
framesLeft, framesPerBuffer ));
Pa_Sleep( msecPerBuffer );
framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
now = PaUtil_GetTime();
}
if( framesLeft > 0 )
{
VDBUG(( "waitUntilBlioWriteBufferIsFlushed: TIMED OUT - framesLeft = %d\n", framesLeft ));
result = paTimedOut;
}
}
return result;
}
signed long GetStreamReadAvailable( PaStream* stream )
{
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
VVDBUG(("GetStreamReadAvailable()\n"));
return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer )
/ ( blio->inputSampleSizeActual * blio->inChan );
return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
}
@ -586,7 +632,6 @@ signed long GetStreamWriteAvailable( PaStream* stream )
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
VVDBUG(("GetStreamWriteAvailable()\n"));
return PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer )
/ ( blio->outputSampleSizeActual * blio->outChan );
return PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
}

View File

@ -64,7 +64,7 @@
#include "pa_mac_core_utilities.h"
/*
* Number of miliseconds to busy wait whil waiting for data in blocking calls.
* Number of milliseconds to busy wait while waiting for data in blocking calls.
*/
#define PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL (5)
/*
@ -79,7 +79,7 @@
typedef struct {
PaUtilRingBuffer inputRingBuffer;
PaUtilRingBuffer outputRingBuffer;
size_t ringBufferFrames;
ring_buffer_size_t ringBufferFrames;
PaSampleFormat inputSampleFormat;
size_t inputSampleSizeActual;
size_t inputSampleSizePow2;
@ -87,8 +87,6 @@ typedef struct {
size_t outputSampleSizeActual;
size_t outputSampleSizePow2;
size_t framesPerBuffer;
int inChan;
int outChan;
@ -117,8 +115,7 @@ PaError initializeBlioRingBuffers(
PaMacBlio *blio,
PaSampleFormat inputSampleFormat,
PaSampleFormat outputSampleFormat,
size_t framesPerBuffer,
long ringBufferSize,
long ringBufferSizeInFrames,
int inChan,
int outChan );
PaError destroyBlioRingBuffers( PaMacBlio *blio );
@ -131,6 +128,7 @@ int BlioCallback(
PaStreamCallbackFlags statusFlags,
void *userData );
void waitUntilBlioWriteBufferIsFlushed( PaMacBlio *blio );
PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate,
size_t framesPerBuffer );
#endif /*PA_MAC_CORE_BLOCKING_H_*/

View File

@ -120,7 +120,11 @@ typedef struct PaMacCoreDeviceProperties
UInt32 bufferFrameSize;
// UInt32 streamLatency; // Seems to be the same as deviceLatency!?
UInt32 deviceLatency;
/* Current device sample rate. May change! */
/* Current device sample rate. May change!
These are initialized to the nominal device sample rate,
and updated with the actual sample rate, when/where available.
Note that these are the *device* sample rates, prior to any required
SR conversion. */
Float64 sampleRate;
Float64 samplePeriod; // reciprocal
}
@ -166,10 +170,6 @@ typedef struct PaMacCoreStream
ACTIVE = 3 /* The stream is active and running. */
} state;
double sampleRate;
//these may be different from the stream sample rate due to SR conversion:
double outDeviceSampleRate;
double inDeviceSampleRate;
PaMacCoreDeviceProperties inputProperties;
PaMacCoreDeviceProperties outputProperties;

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_mac_core_old.c 1083 2006-08-23 07:30:49Z rossb $
* $Id$
* pa_mac_core.c
* Implementation of PortAudio for Mac OS X CoreAudio
*

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_win_ds.c 1779 2011-11-10 14:51:15Z rossb $
* $Id$
* Portable Audio I/O Library DirectSound implementation
*
* Authors: Phil Burk, Robert Marsanyi & Ross Bencina
@ -152,6 +152,13 @@ PA_THREAD_FUNC ProcessingThreadProc( void *pArg );
#define PA_DS_WIN_WDM_DEFAULT_LATENCY_ (.120)
/* we allow the polling period to range between 1 and 100ms.
prior to August 2011 we limited the minimum polling period to 10ms.
*/
#define PA_DS_MINIMUM_POLLING_PERIOD_SECONDS (0.001) /* 1ms */
#define PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS (0.100) /* 100ms */
#define PA_DS_POLLING_JITTER_SECONDS (0.001) /* 1ms */
#define SECONDS_PER_MSEC (0.001)
#define MSECS_PER_SECOND (1000)
@ -201,9 +208,9 @@ static signed long GetStreamWriteAvailable( PaStream* stream );
PaUtil_SetLastHostErrorInfo( paDirectSound, hr, "DirectSound error" )
/************************************************* DX Prototypes **********/
static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,
LPCTSTR lpszDesc,
LPCTSTR lpszDrvName,
static BOOL CALLBACK CollectGUIDsProcW(LPGUID lpGUID,
LPCWSTR lpszDesc,
LPCWSTR lpszDrvName,
LPVOID lpContext );
/************************************************************************************/
@ -311,30 +318,43 @@ typedef struct PaWinDsStream
*/
static double PaWinDS_GetMinSystemLatencySeconds( void )
{
/*
NOTE: GetVersionEx() is deprecated as of Windows 8.1 and can not be used to reliably detect
versions of Windows higher than Windows 8 (due to manifest requirements for reporting higher versions).
Microsoft recommends switching to VerifyVersionInfo (available on Win 2k and later), however GetVersionEx
is is faster, for now we just disable the deprecation warning.
See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
See: http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe
*/
#pragma warning (disable : 4996) /* use of GetVersionEx */
double minLatencySeconds;
/* Set minimal latency based on whether NT or other OS.
* NT has higher latency.
*/
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof( osvi );
GetVersionEx( &osvi );
osvi.dwOSVersionInfoSize = sizeof( osvi );
GetVersionEx( &osvi );
DBUG(("PA - PlatformId = 0x%x\n", osvi.dwPlatformId ));
DBUG(("PA - MajorVersion = 0x%x\n", osvi.dwMajorVersion ));
DBUG(("PA - MinorVersion = 0x%x\n", osvi.dwMinorVersion ));
/* Check for NT */
if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) )
{
minLatencySeconds = PA_DS_WIN_NT_DEFAULT_LATENCY_;
}
else if(osvi.dwMajorVersion >= 5)
{
minLatencySeconds = PA_DS_WIN_WDM_DEFAULT_LATENCY_;
}
else
{
minLatencySeconds = PA_DS_WIN_9X_DEFAULT_LATENCY_;
}
if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) )
{
minLatencySeconds = PA_DS_WIN_NT_DEFAULT_LATENCY_;
}
else if(osvi.dwMajorVersion >= 5)
{
minLatencySeconds = PA_DS_WIN_WDM_DEFAULT_LATENCY_;
}
else
{
minLatencySeconds = PA_DS_WIN_9X_DEFAULT_LATENCY_;
}
return minLatencySeconds;
#pragma warning (default : 4996)
}
@ -360,7 +380,7 @@ static double PaWinDs_GetMinLatencySeconds( double sampleRate )
double minLatencySeconds = 0;
/* Let user determine minimal latency by setting environment variable. */
hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );
hresult = GetEnvironmentVariableA( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );
if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )
{
minLatencySeconds = atoi( envbuf ) * SECONDS_PER_MSEC;
@ -378,20 +398,35 @@ static double PaWinDs_GetMinLatencySeconds( double sampleRate )
/************************************************************************************
** Duplicate the input string using the allocations allocator.
** Duplicate and convert the input string using the group allocations allocator.
** A NULL string is converted to a zero length string.
** If memory cannot be allocated, NULL is returned.
**/
static char *DuplicateDeviceNameString( PaUtilAllocationGroup *allocations, const char* src )
static char *DuplicateDeviceNameString( PaUtilAllocationGroup *allocations, const wchar_t* src )
{
char *result = 0;
if( src != NULL )
{
size_t len = strlen(src);
#if !defined(_UNICODE) && !defined(UNICODE)
size_t len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
result = (char*)PaUtil_GroupAllocateMemory( allocations, (long)(len + 1) );
if( result )
memcpy( (void *) result, src, len+1 );
if( result ) {
if (WideCharToMultiByte(CP_ACP, 0, src, -1, result, (int)len, NULL, NULL) == 0) {
result = 0;
}
}
#else
size_t len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
result = (char*)PaUtil_GroupAllocateMemory( allocations, (long)(len + 1) );
if( result ) {
if (WideCharToMultiByte(CP_UTF8, 0, src, -1, result, (int)len, NULL, NULL) == 0) {
result = 0;
}
}
#endif
}
else
{
@ -473,7 +508,7 @@ static PaError ExpandDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidV
else
{
newItems[i].lpGUID = &newItems[i].guid;
memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) );;
memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) );
}
newItems[i].pnpInterface = guidVector->items[i].pnpInterface;
}
@ -506,9 +541,9 @@ static PaError TerminateDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *gu
/************************************************************************************
** Collect preliminary device information during DirectSound enumeration
*/
static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,
LPCTSTR lpszDesc,
LPCTSTR lpszDrvName,
static BOOL CALLBACK CollectGUIDsProcW(LPGUID lpGUID,
LPCWSTR lpszDesc,
LPCWSTR lpszDrvName,
LPVOID lpContext )
{
DSDeviceNameAndGUIDVector *namesAndGUIDs = (DSDeviceNameAndGUIDVector*)lpContext;
@ -574,29 +609,38 @@ static BOOL CALLBACK KsPropertySetEnumerateCallback( PDSPROPERTY_DIRECTSOUNDDEVI
int i;
DSDeviceNamesAndGUIDs *deviceNamesAndGUIDs = (DSDeviceNamesAndGUIDs*)context;
if( data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER )
/*
Apparently data->Interface can be NULL in some cases.
Possibly virtual devices without hardware.
So we check for NULLs now. See mailing list message November 10, 2012:
"[Portaudio] portaudio initialization crash in KsPropertySetEnumerateCallback(pa_win_ds.c)"
*/
if( data->Interface )
{
for( i=0; i < deviceNamesAndGUIDs->outputNamesAndGUIDs.count; ++i )
if( data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER )
{
if( deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].lpGUID
&& memcmp( &data->DeviceId, deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].lpGUID, sizeof(GUID) ) == 0 )
for( i=0; i < deviceNamesAndGUIDs->outputNamesAndGUIDs.count; ++i )
{
deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].pnpInterface =
if( deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].lpGUID
&& memcmp( &data->DeviceId, deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].lpGUID, sizeof(GUID) ) == 0 )
{
deviceNamesAndGUIDs->outputNamesAndGUIDs.items[i].pnpInterface =
(char*)DuplicateWCharString( deviceNamesAndGUIDs->winDsHostApi->allocations, data->Interface );
break;
break;
}
}
}
}
else if( data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE )
{
for( i=0; i < deviceNamesAndGUIDs->inputNamesAndGUIDs.count; ++i )
else if( data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE )
{
if( deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].lpGUID
&& memcmp( &data->DeviceId, deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].lpGUID, sizeof(GUID) ) == 0 )
for( i=0; i < deviceNamesAndGUIDs->inputNamesAndGUIDs.count; ++i )
{
deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].pnpInterface =
if( deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].lpGUID
&& memcmp( &data->DeviceId, deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].lpGUID, sizeof(GUID) ) == 0 )
{
deviceNamesAndGUIDs->inputNamesAndGUIDs.items[i].pnpInterface =
(char*)DuplicateWCharString( deviceNamesAndGUIDs->winDsHostApi->allocations, data->Interface );
break;
break;
}
}
}
}
@ -922,7 +966,7 @@ static PaError AddOutputDeviceInfoFromDirectSound(
}
else
{
deviceInfo->defaultSampleRate = caps.dwMaxSecondarySampleRate;
deviceInfo->defaultSampleRate = caps.dwMaxSecondarySampleRate;
}
}
else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) )
@ -1160,6 +1204,8 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
goto error;
}
memset( winDsHostApi, 0, sizeof(PaWinDsHostApiRepresentation) ); /* ensure all fields are zeroed. especially winDsHostApi->allocations */
result = PaWinUtil_CoInitialize( paDirectSound, &winDsHostApi->comInitializationResult );
if( result != paNoError )
{
@ -1193,9 +1239,9 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
if( result != paNoError )
goto error;
paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.inputNamesAndGUIDs );
paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW( (LPDSENUMCALLBACKW)CollectGUIDsProcW, (void *)&deviceNamesAndGUIDs.inputNamesAndGUIDs );
paWinDsDSoundEntryPoints.DirectSoundEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.outputNamesAndGUIDs );
paWinDsDSoundEntryPoints.DirectSoundEnumerateW( (LPDSENUMCALLBACKW)CollectGUIDsProcW, (void *)&deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( deviceNamesAndGUIDs.inputNamesAndGUIDs.enumerationError != paNoError )
{
@ -1299,7 +1345,7 @@ error:
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs );
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs );
Terminate( winDsHostApi );
Terminate( (struct PaUtilHostApiRepresentation *)winDsHostApi );
return result;
}
@ -1329,16 +1375,23 @@ static PaError ValidateWinDirectSoundSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinDirectSoundStreamInfo *streamInfo )
{
if( streamInfo )
{
if( streamInfo->size != sizeof( PaWinDirectSoundStreamInfo )
|| streamInfo->version != 2 )
{
return paIncompatibleHostApiSpecificStreamInfo;
}
}
if( streamInfo )
{
if( streamInfo->size != sizeof( PaWinDirectSoundStreamInfo )
|| streamInfo->version != 2 )
{
return paIncompatibleHostApiSpecificStreamInfo;
}
return paNoError;
if( streamInfo->flags & paWinDirectSoundUseLowLevelLatencyParameters )
{
if( streamInfo->framesPerBuffer <= 0 )
return paIncompatibleHostApiSpecificStreamInfo;
}
}
return paNoError;
}
/***********************************************************************************/
@ -1375,8 +1428,8 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
/* validate inputStreamInfo */
inputStreamInfo = (PaWinDirectSoundStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinDirectSoundSpecificStreamInfo( inputParameters, inputStreamInfo );
if( result != paNoError ) return result;
result = ValidateWinDirectSoundSpecificStreamInfo( inputParameters, inputStreamInfo );
if( result != paNoError ) return result;
}
else
{
@ -1404,8 +1457,8 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
/* validate outputStreamInfo */
outputStreamInfo = (PaWinDirectSoundStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinDirectSoundSpecificStreamInfo( outputParameters, outputStreamInfo );
if( result != paNoError ) return result;
result = ValidateWinDirectSoundSpecificStreamInfo( outputParameters, outputStreamInfo );
if( result != paNoError ) return result;
}
else
{
@ -1541,7 +1594,13 @@ static HRESULT InitFullDuplexInputOutputBuffers( PaWinDsStream *stream,
#endif /* PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE */
static HRESULT InitInputBuffer( PaWinDsStream *stream, PaWinDsDeviceInfo *device, PaSampleFormat sampleFormat, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer, PaWinWaveFormatChannelMask channelMask )
static HRESULT InitInputBuffer( PaWinDsStream *stream,
PaWinDsDeviceInfo *device,
PaSampleFormat sampleFormat,
unsigned long nFrameRate,
WORD nChannels,
int bytesPerBuffer,
PaWinWaveFormatChannelMask channelMask )
{
DSCBUFFERDESC captureDesc;
PaWinWaveFormat waveFormat;
@ -1582,7 +1641,10 @@ static HRESULT InitInputBuffer( PaWinDsStream *stream, PaWinDsDeviceInfo *device
}
static HRESULT InitOutputBuffer( PaWinDsStream *stream, PaWinDsDeviceInfo *device, PaSampleFormat sampleFormat, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer, PaWinWaveFormatChannelMask channelMask )
static HRESULT InitOutputBuffer( PaWinDsStream *stream, PaWinDsDeviceInfo *device,
PaSampleFormat sampleFormat, unsigned long nFrameRate,
WORD nChannels, int bytesPerBuffer,
PaWinWaveFormatChannelMask channelMask )
{
HRESULT result;
HWND hWnd;
@ -1680,12 +1742,9 @@ static void CalculateBufferSettings( unsigned long *hostBufferSizeFrames,
unsigned long suggestedOutputLatencyFrames,
double sampleRate, unsigned long userFramesPerBuffer )
{
/* we allow the polling period to range between 1 and 100ms.
prior to August 2011 we limited the minimum polling period to 10ms.
*/
unsigned long minimumPollingPeriodFrames = sampleRate / 1000; /* 1ms */
unsigned long maximumPollingPeriodFrames = sampleRate / 10; /* 100ms */
unsigned long pollingJitterFrames = sampleRate / 1000; /* 1ms */
unsigned long minimumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS);
unsigned long maximumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS);
unsigned long pollingJitterFrames = (unsigned long)(sampleRate * PA_DS_POLLING_JITTER_SECONDS);
if( userFramesPerBuffer == paFramesPerBufferUnspecified )
{
@ -1747,6 +1806,23 @@ static void CalculateBufferSettings( unsigned long *hostBufferSizeFrames,
}
static void CalculatePollingPeriodFrames( unsigned long hostBufferSizeFrames,
unsigned long *pollingPeriodFrames,
double sampleRate, unsigned long userFramesPerBuffer )
{
unsigned long minimumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS);
unsigned long maximumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS);
unsigned long pollingJitterFrames = (unsigned long)(sampleRate * PA_DS_POLLING_JITTER_SECONDS);
*pollingPeriodFrames = max( max(1, userFramesPerBuffer / 4), hostBufferSizeFrames / 16 );
if( *pollingPeriodFrames > maximumPollingPeriodFrames )
{
*pollingPeriodFrames = maximumPollingPeriodFrames;
}
}
static void SetStreamInfoLatencies( PaWinDsStream *stream,
unsigned long userFramesPerBuffer,
unsigned long pollingPeriodFrames,
@ -1808,6 +1884,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
int inputChannelCount, outputChannelCount;
PaSampleFormat inputSampleFormat, outputSampleFormat;
PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
int userRequestedHostInputBufferSizeFrames = 0;
int userRequestedHostOutputBufferSizeFrames = 0;
unsigned long suggestedInputLatencyFrames, suggestedOutputLatencyFrames;
PaWinDirectSoundStreamInfo *inputStreamInfo, *outputStreamInfo;
PaWinWaveFormatChannelMask inputChannelMask, outputChannelMask;
@ -1837,8 +1915,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate hostApiSpecificStreamInfo */
inputStreamInfo = (PaWinDirectSoundStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinDirectSoundSpecificStreamInfo( inputParameters, inputStreamInfo );
if( result != paNoError ) return result;
result = ValidateWinDirectSoundSpecificStreamInfo( inputParameters, inputStreamInfo );
if( result != paNoError ) return result;
if( inputStreamInfo && inputStreamInfo->flags & paWinDirectSoundUseLowLevelLatencyParameters )
userRequestedHostInputBufferSizeFrames = inputStreamInfo->framesPerBuffer;
if( inputStreamInfo && inputStreamInfo->flags & paWinDirectSoundUseChannelMask )
inputChannelMask = inputStreamInfo->channelMask;
@ -1848,7 +1929,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
else
{
inputChannelCount = 0;
inputSampleFormat = 0;
inputSampleFormat = 0;
suggestedInputLatencyFrames = 0;
}
@ -1874,8 +1955,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate hostApiSpecificStreamInfo */
outputStreamInfo = (PaWinDirectSoundStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinDirectSoundSpecificStreamInfo( outputParameters, outputStreamInfo );
if( result != paNoError ) return result;
result = ValidateWinDirectSoundSpecificStreamInfo( outputParameters, outputStreamInfo );
if( result != paNoError ) return result;
if( outputStreamInfo && outputStreamInfo->flags & paWinDirectSoundUseLowLevelLatencyParameters )
userRequestedHostOutputBufferSizeFrames = outputStreamInfo->framesPerBuffer;
if( outputStreamInfo && outputStreamInfo->flags & paWinDirectSoundUseChannelMask )
outputChannelMask = outputStreamInfo->channelMask;
@ -1885,10 +1969,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
else
{
outputChannelCount = 0;
outputSampleFormat = 0;
outputSampleFormat = 0;
suggestedOutputLatencyFrames = 0;
}
/*
If low level host buffer size is specified for both input and output
the current code requires the sizes to match.
*/
if( (userRequestedHostInputBufferSizeFrames > 0 && userRequestedHostOutputBufferSizeFrames > 0)
&& userRequestedHostInputBufferSizeFrames != userRequestedHostOutputBufferSizeFrames )
return paIncompatibleHostApiSpecificStreamInfo;
/*
IMPLEMENT ME:
@ -1956,10 +2050,10 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
hostInputSampleFormat =
PaUtil_SelectClosestAvailableFormat( nativeInputFormats, inputParameters->sampleFormat );
}
else
{
hostInputSampleFormat = 0;
}
else
{
hostInputSampleFormat = 0;
}
if( outputParameters )
{
@ -1971,9 +2065,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PaUtil_SelectClosestAvailableFormat( nativeOutputFormats, outputParameters->sampleFormat );
}
else
{
hostOutputSampleFormat = 0;
}
{
hostOutputSampleFormat = 0;
}
result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
inputChannelCount, inputSampleFormat, hostInputSampleFormat,
@ -2016,7 +2110,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
#endif
#ifndef PA_WIN_DS_USE_WMME_TIMER
stream->processingThreadCompleted = CreateEvent( NULL, /* bManualReset = */ TRUE, /* bInitialState = */ FALSE, NULL );
stream->processingThreadCompleted = CreateEvent( NULL, /* bManualReset = */ TRUE, /* bInitialState = */ FALSE, NULL );
if( stream->processingThreadCompleted == NULL )
{
result = paUnanticipatedHostError;
@ -2027,14 +2121,34 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* set up i/o parameters */
CalculateBufferSettings( &stream->hostBufferSizeFrames, &pollingPeriodFrames,
/* isFullDuplex = */ (inputParameters && outputParameters),
suggestedInputLatencyFrames,
suggestedOutputLatencyFrames,
sampleRate, framesPerBuffer );
if( userRequestedHostInputBufferSizeFrames > 0 || userRequestedHostOutputBufferSizeFrames > 0 )
{
/* use low level parameters */
/* since we use the same host buffer size for input and output
we choose the highest user specified value.
*/
stream->hostBufferSizeFrames = max( userRequestedHostInputBufferSizeFrames, userRequestedHostOutputBufferSizeFrames );
CalculatePollingPeriodFrames(
stream->hostBufferSizeFrames, &pollingPeriodFrames,
sampleRate, framesPerBuffer );
}
else
{
CalculateBufferSettings( &stream->hostBufferSizeFrames, &pollingPeriodFrames,
/* isFullDuplex = */ (inputParameters && outputParameters),
suggestedInputLatencyFrames,
suggestedOutputLatencyFrames,
sampleRate, framesPerBuffer );
}
stream->pollingPeriodSeconds = pollingPeriodFrames / sampleRate;
DBUG(("DirectSound host buffer size frames: %d, polling period seconds: %f, @ sr: %f\n",
stream->hostBufferSizeFrames, stream->pollingPeriodSeconds, sampleRate ));
/* ------------------ OUTPUT */
if( outputParameters )
{
@ -2396,6 +2510,8 @@ static int TimeSlice( PaWinDsStream *stream )
framesToXfer = numOutFramesReady = bytesEmpty / stream->outputFrameSizeBytes;
/* Check for underflow */
/* FIXME QueryOutputSpace should not adjust underflow count as a side effect.
A query function should be a const operator on the stream and return a flag on underflow. */
if( stream->outputUnderflowCount != previousUnderflowCount )
stream->callbackFlags |= paOutputUnderflow;
@ -2460,8 +2576,8 @@ static int TimeSlice( PaWinDsStream *stream )
if( stream->bufferProcessor.outputChannelCount > 0 )
{
/*
We don't currently add outputLatency here because it appears to produce worse
results than non adding it. Need to do more testing to verify this.
We don't currently add outputLatency here because it appears to produce worse
results than not adding it. Need to do more testing to verify this.
*/
/* timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency; */
timeInfo.outputBufferDacTime = timeInfo.currentTime;
@ -2649,12 +2765,10 @@ static void CALLBACK WaitableTimerAPCProc(
PA_THREAD_FUNC ProcessingThreadProc( void *pArg )
{
PaWinDsStream *stream = (PaWinDsStream *)pArg;
MMRESULT mmResult;
HANDLE hWaitableTimer;
LARGE_INTEGER dueTime;
int timerPeriodMs;
timerPeriodMs = stream->pollingPeriodSeconds * MSECS_PER_SECOND;
timerPeriodMs = (int)(stream->pollingPeriodSeconds * MSECS_PER_SECOND);
if( timerPeriodMs < 1 )
timerPeriodMs = 1;
@ -2712,7 +2826,7 @@ static PaError CloseStream( PaStream* s )
#endif
#ifndef PA_WIN_DS_USE_WMME_TIMER
CloseHandle( stream->processingThreadCompleted );
CloseHandle( stream->processingThreadCompleted );
#endif
// Cleanup the sound buffers
@ -2810,7 +2924,7 @@ static PaError StartStream( PaStream *s )
ResetEvent( stream->processingCompleted );
#ifndef PA_WIN_DS_USE_WMME_TIMER
ResetEvent( stream->processingThreadCompleted );
ResetEvent( stream->processingThreadCompleted );
#endif
if( stream->bufferProcessor.inputChannelCount > 0 )
@ -2878,7 +2992,7 @@ static PaError StartStream( PaStream *s )
if( stream->streamRepresentation.streamCallback )
{
TIMECAPS timecaps;
int timerPeriodMs = stream->pollingPeriodSeconds * MSECS_PER_SECOND;
int timerPeriodMs = (int)(stream->pollingPeriodSeconds * MSECS_PER_SECOND);
if( timerPeriodMs < 1 )
timerPeriodMs = 1;
@ -2889,10 +3003,10 @@ static PaError StartStream( PaStream *s )
we're using an MM timer callback via timeSetEvent or not.
*/
assert( stream->systemTimerResolutionPeriodMs == 0 );
if( timeGetDevCaps( &timecaps, sizeof(TIMECAPS) == MMSYSERR_NOERROR && timecaps.wPeriodMin > 0 ) )
if( timeGetDevCaps( &timecaps, sizeof(TIMECAPS) ) == MMSYSERR_NOERROR && timecaps.wPeriodMin > 0 )
{
/* aim for resolution 4 times higher than polling rate */
stream->systemTimerResolutionPeriodMs = (stream->pollingPeriodSeconds * MSECS_PER_SECOND) / 4;
stream->systemTimerResolutionPeriodMs = (UINT)((stream->pollingPeriodSeconds * MSECS_PER_SECOND) * .25);
if( stream->systemTimerResolutionPeriodMs < timecaps.wPeriodMin )
stream->systemTimerResolutionPeriodMs = timecaps.wPeriodMin;
if( stream->systemTimerResolutionPeriodMs > timecaps.wPeriodMax )
@ -2920,9 +3034,9 @@ static PaError StartStream( PaStream *s )
goto error;
}
#else
/* Create processing thread which calls TimerCallback */
/* Create processing thread which calls TimerCallback */
stream->processingThread = CREATE_THREAD( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId );
stream->processingThread = CREATE_THREAD( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId );
if( !stream->processingThread )
{
result = paUnanticipatedHostError;
@ -2992,8 +3106,8 @@ static PaError StopStream( PaStream *s )
#else
if( stream->processingThread )
{
if( WaitForSingleObject( stream->processingThreadCompleted, 30*100 ) == WAIT_TIMEOUT )
return paUnanticipatedHostError;
if( WaitForSingleObject( stream->processingThreadCompleted, 30*100 ) == WAIT_TIMEOUT )
return paUnanticipatedHostError;
#ifdef CLOSE_THREAD_HANDLE
CloseHandle( stream->processingThread ); /* Delete thread. */

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_jack.c 1668 2011-05-02 17:07:11Z rossb $
* $Id$
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* JACK Implementation by Joshua Haberman
@ -232,6 +232,10 @@ typedef struct PaJackStream
}
PaJackStream;
/* In calls to jack_get_ports() this filter expression is used instead of ""
* to prevent any other types (eg Midi ports etc) being listed */
#define JACK_PORT_TYPE_FILTER "audio"
#define TRUE 1
#define FALSE 0
@ -492,7 +496,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
* according to the client_name:port_name convention (which is
* enforced by jackd)
* A: If jack_get_ports returns NULL, there's nothing for us to do */
UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", "", 0 )) && jack_ports[0], paNoError );
UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
/* Find number of ports */
while( jack_ports[numPorts] )
++numPorts;
@ -583,7 +587,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
/* ... what are your output ports (that we could input from)? */
clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
NULL, JackPortIsOutput);
JACK_PORT_TYPE_FILTER, JackPortIsOutput);
curDevInfo->maxInputChannels = 0;
curDevInfo->defaultLowInputLatency = 0.;
curDevInfo->defaultHighInputLatency = 0.;
@ -604,7 +608,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
/* ... what are your input ports (that we could output to)? */
clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
NULL, JackPortIsInput);
JACK_PORT_TYPE_FILTER, JackPortIsInput);
curDevInfo->maxOutputChannels = 0;
curDevInfo->defaultLowOutputLatency = 0.;
curDevInfo->defaultHighOutputLatency = 0.;
@ -1235,7 +1239,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* Get output ports of our capture device */
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
NULL, JackPortIsOutput ), paUnanticipatedHostError );
JACK_PORT_TYPE_FILTER, JackPortIsOutput ), paUnanticipatedHostError );
for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
{
if( (stream->remote_output_ports[i] = jack_port_by_name(
@ -1259,7 +1263,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* Get input ports of our playback device */
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
NULL, JackPortIsInput ), paUnanticipatedHostError );
JACK_PORT_TYPE_FILTER, JackPortIsInput ), paUnanticipatedHostError );
for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )
{
if( (stream->remote_input_ports[i] = jack_port_by_name(

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_unix_oss.c 1668 2011-05-02 17:07:11Z rossb $
* $Id$
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* OSS implementation by:
@ -318,6 +318,13 @@ error:
return result;
}
static int CalcHigherLogTwo( int n )
{
int log2 = 0;
while( (1<<log2) < n ) log2++;
return log2;
}
static PaError QueryDirection( const char *deviceName, StreamMode mode, double *defaultSampleRate, int *maxChannelCount,
double *defaultLowLatency, double *defaultHighLatency )
{
@ -327,6 +334,8 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
int devHandle = -1;
int sr;
*maxChannelCount = 0; /* Default value in case this fails */
int temp, frgmt;
unsigned long fragFrames;
if ( (devHandle = open( deviceName, (mode == StreamMode_In ? O_RDONLY : O_WRONLY) | O_NONBLOCK )) < 0 )
{
@ -354,7 +363,7 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
maxNumChannels = 0;
for( numChannels = 1; numChannels <= 16; numChannels++ )
{
int temp = numChannels;
temp = numChannels;
if( ioctl( devHandle, SNDCTL_DSP_CHANNELS, &temp ) < 0 )
{
busy = EAGAIN == errno || EBUSY == errno;
@ -401,8 +410,8 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
* to a supported number of channels. SG20011005 */
{
/* use most reasonable default value */
int temp = PA_MIN( maxNumChannels, 2 );
ENSURE_( ioctl( devHandle, SNDCTL_DSP_CHANNELS, &temp ), paUnanticipatedHostError );
numChannels = PA_MIN( maxNumChannels, 2 );
ENSURE_( ioctl( devHandle, SNDCTL_DSP_CHANNELS, &numChannels ), paUnanticipatedHostError );
}
/* Get supported sample rate closest to 44100 Hz */
@ -415,9 +424,21 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
}
*maxChannelCount = maxNumChannels;
/* TODO */
*defaultLowLatency = 512. / *defaultSampleRate;
*defaultHighLatency = 2048. / *defaultSampleRate;
/* Attempt to set low latency with 4 frags-per-buffer, 128 frames-per-frag (total buffer 512 frames)
* since the ioctl sets bytes, multiply by numChannels, and base on 2 bytes-per-sample, */
fragFrames = 128;
frgmt = (4 << 16) + (CalcHigherLogTwo( fragFrames * numChannels * 2 ) & 0xffff);
ENSURE_( ioctl( devHandle, SNDCTL_DSP_SETFRAGMENT, &frgmt ), paUnanticipatedHostError );
/* Use the value set by the ioctl to give the latency achieved */
fragFrames = pow( 2, frgmt & 0xffff ) / (numChannels * 2);
*defaultLowLatency = ((frgmt >> 16) - 1) * fragFrames / *defaultSampleRate;
/* Cannot now try setting a high latency (device would need closing and opening again). Make
* high-latency 4 times the low unless the fragFrames are significantly more than requested 128 */
temp = (fragFrames < 256) ? 4 : (fragFrames < 512) ? 2 : 1;
*defaultHighLatency = temp * *defaultLowLatency;
error:
if( devHandle >= 0 )
@ -962,13 +983,6 @@ static unsigned long PaOssStreamComponent_BufferSize( PaOssStreamComponent *comp
return PaOssStreamComponent_FrameSize( component ) * component->hostFrames * component->numBufs;
}
static int CalcHigherLogTwo( int n )
{
int log2 = 0;
while( (1<<log2) < n ) log2++;
return log2;
}
/** Configure stream component device parameters.
*/
static PaError PaOssStreamComponent_Configure( PaOssStreamComponent *component, double sampleRate, unsigned long
@ -995,8 +1009,9 @@ static PaError PaOssStreamComponent_Configure( PaOssStreamComponent *component,
*/
if( framesPerBuffer == paFramesPerBufferUnspecified )
{
bufSz = (unsigned long)(component->latency * sampleRate);
fragSz = bufSz / 4;
/* Aim for 4 fragments in the complete buffer; the latency comes from 3 of these */
fragSz = (unsigned long)(component->latency * sampleRate / 3);
bufSz = fragSz * 4;
}
else
{

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_hostapi_skeleton.c 1668 2011-05-02 17:07:11Z rossb $
* $Id$
* Portable Audio I/O Library skeleton implementation
* demonstrates how to use the common functions to implement support
* for a host API

View File

@ -1,94 +0,0 @@
//
// AudioSessionTypes.h -- Copyright Microsoft Corporation, All Rights Reserved.
//
// Description: Type definitions used by the audio session manager RPC/COM interfaces
//
#pragma once
#ifndef __AUDIOSESSIONTYPES__
#define __AUDIOSESSIONTYPES__
#if defined(__midl)
#define MIDL_SIZE_IS(x) [size_is(x)]
#define MIDL_STRING [string]
#define MIDL_ANYSIZE_ARRAY
#else // !defined(__midl)
#define MIDL_SIZE_IS(x)
#define MIDL_STRING
#define MIDL_ANYSIZE_ARRAY ANYSIZE_ARRAY
#endif // defined(__midl)
//-------------------------------------------------------------------------
// Description: AudioClient share mode
//
// AUDCLNT_SHAREMODE_SHARED - The device will be opened in shared mode and use the
// WAS format.
// AUDCLNT_SHAREMODE_EXCLUSIVE - The device will be opened in exclusive mode and use the
// application specified format.
//
typedef enum _AUDCLNT_SHAREMODE
{
AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_SHAREMODE_EXCLUSIVE
} AUDCLNT_SHAREMODE;
//-------------------------------------------------------------------------
// Description: AudioClient stream flags
//
// Can be a combination of AUDCLNT_STREAMFLAGS and AUDCLNT_SYSFXFLAGS:
//
// AUDCLNT_STREAMFLAGS (this group of flags uses the high word, w/exception of high-bit which is reserved, 0x7FFF0000):
//
// AUDCLNT_STREAMFLAGS_CROSSPROCESS - Audio policy control for this stream will be shared with
// with other process sessions that use the same audio session
// GUID.
// AUDCLNT_STREAMFLAGS_LOOPBACK - Initializes a renderer endpoint for a loopback audio application.
// In this mode, a capture stream will be opened on the specified
// renderer endpoint. Shared mode and a renderer endpoint is required.
// Otherwise the IAudioClient::Initialize call will fail. If the
// initialize is successful, a capture stream will be available
// from the IAudioClient object.
//
// AUDCLNT_STREAMFLAGS_EVENTCALLBACK - An exclusive mode client will supply an event handle that will be
// signaled when an IRP completes (or a waveRT buffer completes) telling
// it to fill the next buffer
//
// AUDCLNT_STREAMFLAGS_NOPERSIST - Session state will not be persisted
//
// AUDCLNT_SYSFXFLAGS (these flags use low word 0x0000FFFF):
//
// none defined currently
//
#define AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
#define AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
#define AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
#define AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
//-------------------------------------------------------------------------
// Description: Device share mode - sharing mode for the audio device.
//
// DeviceShared - The device can be shared with other processes.
// DeviceExclusive - The device will only be used by this process.
//
typedef enum _DeviceShareMode
{
DeviceShared,
DeviceExclusive
} DeviceShareMode;
//-------------------------------------------------------------------------
// Description: AudioSession State.
//
// AudioSessionStateInactive - The session has no active audio streams.
// AudioSessionStateActive - The session has active audio streams.
// AudioSessionStateExpired - The session is dormant.
typedef enum _AudioSessionState
{
AudioSessionStateInactive = 0,
AudioSessionStateActive = 1,
AudioSessionStateExpired = 2
} AudioSessionState;
#endif

View File

@ -1,186 +0,0 @@
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
devpkey.h
Abstract:
Defines property keys for the Plug and Play Device Property API.
Author:
Jim Cavalaris (jamesca) 10-14-2003
Environment:
User-mode only.
Revision History:
14-October-2003 jamesca
Creation and initial implementation.
20-June-2006 dougb
Copied Jim's version replaced "DEFINE_DEVPROPKEY(DEVPKEY_" with "DEFINE_PROPERTYKEY(PKEY_"
--*/
//#include <devpropdef.h>
//
// _NAME
//
DEFINE_PROPERTYKEY(PKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING
//
// Device properties
// These PKEYs correspond to the old setupapi SPDRP_XXX properties
//
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Service, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Class, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 9); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ClassGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 10); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_Driver, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 11); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ConfigFlags, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 12); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_LocationInfo, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 15); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_PDOName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 16); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Capabilities, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 17); // DEVPROP_TYPE_UNINT32
DEFINE_PROPERTYKEY(PKEY_Device_UINumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 18); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_UpperFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 19); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_LowerFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 20); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_BusTypeGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 21); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_LegacyBusType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 22); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_BusNumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 23); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_EnumeratorName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 24); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Security, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
DEFINE_PROPERTYKEY(PKEY_Device_SecuritySDS, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DevType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 27); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Exclusive, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 28); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Characteristics, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 29); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Address, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 30); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_UINumberDescFormat, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 31); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_PowerData, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 32); // DEVPROP_TYPE_BINARY
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicy, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 33); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyDefault, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 34); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyOverride, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 35); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_InstallState, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 36); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_LocationPaths, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 37); // DEVPROP_TYPE_STRING_LIST
//
// Device properties
// These PKEYs correspond to a device's status and problem code
//
DEFINE_PROPERTYKEY(PKEY_Device_DevNodeStatus, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 2); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_ProblemCode, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 3); // DEVPROP_TYPE_UINT32
//
// Device properties
// These PKEYs correspond to device relations
//
DEFINE_PROPERTYKEY(PKEY_Device_EjectionRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 4); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_RemovalRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 5); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_PowerRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 6); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_BusRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 7); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Parent, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 8); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Children, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 9); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Siblings, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 10); // DEVPROP_TYPE_STRING_LIST
//
// Other Device properties
//
DEFINE_PROPERTYKEY(PKEY_Device_Reported, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 2); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_Legacy, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 3); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Numa_Proximity_Domain, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 1); // DEVPROP_TYPE_UINT32
//
// Device driver properties
//
DEFINE_PROPERTYKEY(PKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); // DEVPROP_TYPE_FILETIME
DEFINE_PROPERTYKEY(PKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverDesc, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfPath, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSection, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSectionExt, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 7); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_MatchingDeviceId, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 8); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 9); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverPropPageProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 10); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverCoInstallers, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 11); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerTags, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 12); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerExceptions, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 13); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverRank, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 14); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_DriverLogoLevel, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 15); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_NoConnectSound, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 17); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_GenericDriverInstalled, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 18); // DEVPROP_TYPE_BOOLEAN
//
// Device properties that were set by the driver package that was installed
// on the device.
//
DEFINE_PROPERTYKEY(PKEY_DrvPkg_Model, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_VendorWebSite, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_DetailedDescription, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_DocumentationLink, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_Icon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 6); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DrvPkg_BrandingIcon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 7); // DEVPROP_TYPE_STRING_LIST
//
// Device setup class properties
// These PKEYs correspond to the old setupapi SPCRP_XXX properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_UpperFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 19); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DeviceClass_LowerFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 20); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Security, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
DEFINE_PROPERTYKEY(PKEY_DeviceClass_SecuritySDS, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_DevType, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 27); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Exclusive, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 28); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Characteristics, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 29); // DEVPROP_TYPE_UINT32
//
// Device setup class properties
// These PKEYs correspond to registry values under the device class GUID key
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Name, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassName, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Icon, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassInstaller, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_PropPageProvider, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoInstallClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 7); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoDisplayClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 8); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_SilentInstall, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 9); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoUseClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 10); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_DefaultService, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 11); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_IconPath, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 12); // DEVPROP_TYPE_STRING_LIST
//
// Other Device setup class properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassCoInstallers, 0x713d1703, 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c, 2); // DEVPROP_TYPE_STRING_LIST
//
// Device interface properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Enabled, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 3); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_ClassGuid, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 4); // DEVPROP_TYPE_GUID
//
// Device interface class properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceInterfaceClass_DefaultInterface, 0x14c83a99, 0x0b3f, 0x44b7, 0xbe, 0x4c, 0xa1, 0x78, 0xd3, 0x99, 0x05, 0x64, 2); // DEVPROP_TYPE_STRING

View File

@ -417,6 +417,12 @@ DEFINE_GUIDSTRUCT("6994AD04-93EF-11D0-A3CC-00A0C9223196",KSCATEGORY_AUDIO);
DEFINE_GUIDSTRUCT("6994AD05-93EF-11D0-A3CC-00A0C9223196",KSCATEGORY_VIDEO);
#define KSCATEGORY_VIDEO DEFINE_GUIDNAMED(KSCATEGORY_VIDEO)
/* Added for Vista and later */
#define STATIC_KSCATEGORY_REALTIME \
0xEB115FFCL, 0x10C8, 0x4964, 0x83, 0x1D, 0x6D, 0xCB, 0x02, 0xE6, 0xF2, 0x3F
DEFINE_GUIDSTRUCT("EB115FFC-10C8-4964-831D-6DCB02E6F23F", KSCATEGORY_REALTIME);
#define KSCATEGORY_REALTIME DEFINE_GUIDNAMED(KSCATEGORY_REALTIME)
#define STATIC_KSCATEGORY_TEXT \
0x6994AD06L,0x93EF,0x11D0,0xA3,0xCC,0x00,0xA0,0xC9,0x22,0x31,0x96
DEFINE_GUIDSTRUCT("6994AD06-93EF-11D0-A3CC-00A0C9223196",KSCATEGORY_TEXT);
@ -979,7 +985,15 @@ DEFINE_GUIDSTRUCT("A855A48C-2F78-4729-9051-1968746B9EEF",KSPROPSETID_RtAudio);
#define KSPROPSETID_RtAudio DEFINE_GUIDNAMED(KSPROPSETID_RtAudio)
typedef enum {
KSPROPERTY_RTAUDIO_GETPOSITIONFUNCTION
KSPROPERTY_RTAUDIO_GETPOSITIONFUNCTION,
/* Added for Vista and later */
KSPROPERTY_RTAUDIO_BUFFER,
KSPROPERTY_RTAUDIO_HWLATENCY,
KSPROPERTY_RTAUDIO_POSITIONREGISTER,
KSPROPERTY_RTAUDIO_CLOCKREGISTER,
KSPROPERTY_RTAUDIO_BUFFER_WITH_NOTIFICATION,
KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT,
KSPROPERTY_RTAUDIO_UNREGISTER_NOTIFICATION_EVENT
} KSPROPERTY_RTAUDIO;
#define STATIC_KSPROPSETID_DrmAudioStream \
@ -4547,5 +4561,50 @@ typedef struct _tagKSJACK_DESCRIPTION2
DWORD JackCapabilities;
} KSJACK_DESCRIPTION2, *PKSJACK_DESCRIPTION2;
/* Additional structs for Windows Vista and later */
typedef struct _tagKSRTAUDIO_BUFFER_PROPERTY {
KSPROPERTY Property;
PVOID BaseAddress;
ULONG RequestedBufferSize;
} KSRTAUDIO_BUFFER_PROPERTY, *PKSRTAUDIO_BUFFER_PROPERTY;
typedef struct _tagKSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION {
KSPROPERTY Property;
PVOID BaseAddress;
ULONG RequestedBufferSize;
ULONG NotificationCount;
} KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION, *PKSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION;
typedef struct _tagKSRTAUDIO_BUFFER {
PVOID BufferAddress;
ULONG ActualBufferSize;
BOOL CallMemoryBarrier;
} KSRTAUDIO_BUFFER, *PKSRTAUDIO_BUFFER;
typedef struct _tagKSRTAUDIO_HWLATENCY {
ULONG FifoSize;
ULONG ChipsetDelay;
ULONG CodecDelay;
} KSRTAUDIO_HWLATENCY, *PKSRTAUDIO_HWLATENCY;
typedef struct _tagKSRTAUDIO_HWREGISTER_PROPERTY {
KSPROPERTY Property;
PVOID BaseAddress;
} KSRTAUDIO_HWREGISTER_PROPERTY, *PKSRTAUDIO_HWREGISTER_PROPERTY;
typedef struct _tagKSRTAUDIO_HWREGISTER {
PVOID Register;
ULONG Width;
ULONGLONG Numerator;
ULONGLONG Denominator;
ULONG Accuracy;
} KSRTAUDIO_HWREGISTER, *PKSRTAUDIO_HWREGISTER;
typedef struct _tagKSRTAUDIO_NOTIFICATION_EVENT_PROPERTY {
KSPROPERTY Property;
HANDLE NotificationEvent;
} KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY, *PKSRTAUDIO_NOTIFICATION_EVENT_PROPERTY;
#endif /* _KSMEDIA_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,225 +0,0 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
sdkddkver.h
Abstract:
Master include file for versioning windows SDK/DDK.
*/
#ifndef _INC_SDKDDKVER
#define _INC_SDKDDKVER
#pragma once
//
// _WIN32_WINNT version constants
//
#define _WIN32_WINNT_NT4 0x0400
#define _WIN32_WINNT_WIN2K 0x0500
#define _WIN32_WINNT_WINXP 0x0501
#define _WIN32_WINNT_WS03 0x0502
#define _WIN32_WINNT_LONGHORN 0x0600
//
// _WIN32_IE_ version constants
//
#define _WIN32_IE_IE20 0x0200
#define _WIN32_IE_IE30 0x0300
#define _WIN32_IE_IE302 0x0302
#define _WIN32_IE_IE40 0x0400
#define _WIN32_IE_IE401 0x0401
#define _WIN32_IE_IE50 0x0500
#define _WIN32_IE_IE501 0x0501
#define _WIN32_IE_IE55 0x0550
#define _WIN32_IE_IE60 0x0600
#define _WIN32_IE_IE60SP1 0x0601
#define _WIN32_IE_IE60SP2 0x0603
#define _WIN32_IE_IE70 0x0700
//
// IE <-> OS version mapping
//
// NT4 supports IE versions 2.0 -> 6.0 SP1
#define _WIN32_IE_NT4 _WIN32_IE_IE20
#define _WIN32_IE_NT4SP1 _WIN32_IE_IE20
#define _WIN32_IE_NT4SP2 _WIN32_IE_IE20
#define _WIN32_IE_NT4SP3 _WIN32_IE_IE302
#define _WIN32_IE_NT4SP4 _WIN32_IE_IE401
#define _WIN32_IE_NT4SP5 _WIN32_IE_IE401
#define _WIN32_IE_NT4SP6 _WIN32_IE_IE50
// Win98 supports IE versions 4.01 -> 6.0 SP1
#define _WIN32_IE_WIN98 _WIN32_IE_IE401
// Win98SE supports IE versions 5.0 -> 6.0 SP1
#define _WIN32_IE_WIN98SE _WIN32_IE_IE50
// WinME supports IE versions 5.5 -> 6.0 SP1
#define _WIN32_IE_WINME _WIN32_IE_IE55
// Win2k supports IE versions 5.01 -> 6.0 SP1
#define _WIN32_IE_WIN2K _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP1 _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP2 _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP3 _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP4 _WIN32_IE_IE501
#define _WIN32_IE_XP _WIN32_IE_IE60
#define _WIN32_IE_XPSP1 _WIN32_IE_IE60SP1
#define _WIN32_IE_XPSP2 _WIN32_IE_IE60SP2
#define _WIN32_IE_WS03 0x0602
#define _WIN32_IE_WS03SP1 _WIN32_IE_IE60SP2
#define _WIN32_IE_LONGHORN _WIN32_IE_IE70
//
// NTDDI version constants
//
#define NTDDI_WIN2K 0x05000000
#define NTDDI_WIN2KSP1 0x05000100
#define NTDDI_WIN2KSP2 0x05000200
#define NTDDI_WIN2KSP3 0x05000300
#define NTDDI_WIN2KSP4 0x05000400
#define NTDDI_WINXP 0x05010000
#define NTDDI_WINXPSP1 0x05010100
#define NTDDI_WINXPSP2 0x05010200
#define NTDDI_WS03 0x05020000
#define NTDDI_WS03SP1 0x05020100
#define NTDDI_LONGHORN 0x06000000
//
// masks for version macros
//
#define OSVERSION_MASK 0xFFFF0000
#define SPVERSION_MASK 0x0000FF00
#define SUBVERSION_MASK 0x000000FF
//
// macros to extract various version fields from the NTDDI version
//
#define OSVER(Version) ((Version) & OSVERSION_MASK)
#define SPVER(Version) (((Version) & SPVERSION_MASK) >> 8)
#define SUBVER(Version) (((Version) & SUBVERSION_MASK) )
#if defined(DECLSPEC_DEPRECATED_DDK)
// deprecate in 2k or later
#if (NTDDI_VERSION >= NTDDI_WIN2K)
#define DECLSPEC_DEPRECATED_DDK_WIN2K DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WIN2K
#endif
// deprecate in XP or later
#if (NTDDI_VERSION >= NTDDI_WINXP)
#define DECLSPEC_DEPRECATED_DDK_WINXP DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WINXP
#endif
// deprecate in WS03 or later
#if (NTDDI_VERSION >= NTDDI_WS03)
#define DECLSPEC_DEPRECATED_DDK_WIN2003 DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WIN2003
#endif
// deprecate in WS03 or later
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
#define DECLSPEC_DEPRECATED_DDK_LONGHORN DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_LONGHORN
#endif
#endif // defined(DECLSPEC_DEPRECATED_DDK)
//
// if versions aren't already defined, default to most current
//
#define NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
#define NTDDI_VERSION_FROM_WIN32_WINNT(ver) NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
#define _WIN32_WINNT 0x0600
#endif
#ifndef NTDDI_VERSION
#ifdef _WIN32_WINNT
// set NTDDI_VERSION based on _WIN32_WINNT
#define NTDDI_VERSION NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#else
#define NTDDI_VERSION 0x06000000
#endif
#endif
#ifndef WINVER
#ifdef _WIN32_WINNT
// set WINVER based on _WIN32_WINNT
#define WINVER _WIN32_WINNT
#else
#define WINVER 0x0600
#endif
#endif
#ifndef _WIN32_IE
#ifdef _WIN32_WINNT
// set _WIN32_IE based on _WIN32_WINNT
#if (_WIN32_WINNT <= _WIN32_WINNT_NT4)
#define _WIN32_IE _WIN32_IE_IE50
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
#define _WIN32_IE _WIN32_IE_IE501
#elif (_WIN32_WINNT <= _WIN32_WINNT_WINXP)
#define _WIN32_IE _WIN32_IE_IE60
#elif (_WIN32_WINNT <= _WIN32_WINNT_WS03)
#define _WIN32_IE 0x0602
#else
#define _WIN32_IE 0x0700
#endif
#else
#define _WIN32_IE 0x0700
#endif
#endif
//
// Sanity check for compatible versions
//
#if defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(RC_INVOKED)
#if (defined(WINVER) && (WINVER < 0x0400) && (_WIN32_WINNT > 0x0400))
#error WINVER setting conflicts with _WIN32_WINNT setting
#endif
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WIN2K) && (_WIN32_WINNT != _WIN32_WINNT_WIN2K))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WINXP) && (_WIN32_WINNT != _WIN32_WINNT_WINXP))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WS03) && (_WIN32_WINNT != _WIN32_WINNT_WS03))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_LONGHORN) && (_WIN32_WINNT != _WIN32_WINNT_LONGHORN))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif
#if ((_WIN32_WINNT < _WIN32_WINNT_WIN2K) && (_WIN32_IE > _WIN32_IE_IE60SP1))
#error _WIN32_WINNT settings conflicts with _WIN32_IE setting
#endif
#endif // defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(_WINRESRC_)
#endif // !_INC_SDKDDKVER

View File

@ -1,468 +0,0 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 7.00.0499 */
/* Compiler settings for shtypes.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 500
#endif
/* verify that the <rpcsal.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCSAL_H_VERSION__
#define __REQUIRED_RPCSAL_H_VERSION__ 100
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef __shtypes_h__
#define __shtypes_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
/* header files for imported files */
#include "wtypes.h"
#ifdef __cplusplus
extern "C"{
#endif
/* interface __MIDL_itf_shtypes_0000_0000 */
/* [local] */
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//--------------------------------------------------------------------------
//===========================================================================
//
// Object identifiers in the explorer's name space (ItemID and IDList)
//
// All the items that the user can browse with the explorer (such as files,
// directories, servers, work-groups, etc.) has an identifier which is unique
// among items within the parent folder. Those identifiers are called item
// IDs (SHITEMID). Since all its parent folders have their own item IDs,
// any items can be uniquely identified by a list of item IDs, which is called
// an ID list (ITEMIDLIST).
//
// ID lists are almost always allocated by the task allocator (see some
// description below as well as OLE 2.0 SDK) and may be passed across
// some of shell interfaces (such as IShellFolder). Each item ID in an ID list
// is only meaningful to its parent folder (which has generated it), and all
// the clients must treat it as an opaque binary data except the first two
// bytes, which indicates the size of the item ID.
//
// When a shell extension -- which implements the IShellFolder interace --
// generates an item ID, it may put any information in it, not only the data
// with that it needs to identifies the item, but also some additional
// information, which would help implementing some other functions efficiently.
// For example, the shell's IShellFolder implementation of file system items
// stores the primary (long) name of a file or a directory as the item
// identifier, but it also stores its alternative (short) name, size and date
// etc.
//
// When an ID list is passed to one of shell APIs (such as SHGetPathFromIDList),
// it is always an absolute path -- relative from the root of the name space,
// which is the desktop folder. When an ID list is passed to one of IShellFolder
// member function, it is always a relative path from the folder (unless it
// is explicitly specified).
//
//===========================================================================
//
// SHITEMID -- Item ID (mkid)
// USHORT cb; // Size of the ID (including cb itself)
// BYTE abID[]; // The item ID (variable length)
//
#include <pshpack1.h>
typedef struct _SHITEMID
{
USHORT cb;
BYTE abID[ 1 ];
} SHITEMID;
#include <poppack.h>
#if defined(_M_IX86)
#define __unaligned
#endif // __unaligned
typedef SHITEMID __unaligned *LPSHITEMID;
typedef const SHITEMID __unaligned *LPCSHITEMID;
//
// ITEMIDLIST -- List if item IDs (combined with 0-terminator)
//
#include <pshpack1.h>
typedef struct _ITEMIDLIST
{
SHITEMID mkid;
} ITEMIDLIST;
#if defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus)
typedef struct _ITEMIDLIST_RELATIVE : ITEMIDLIST {} ITEMIDLIST_RELATIVE;
typedef struct _ITEMID_CHILD : ITEMIDLIST_RELATIVE {} ITEMID_CHILD;
typedef struct _ITEMIDLIST_ABSOLUTE : ITEMIDLIST_RELATIVE {} ITEMIDLIST_ABSOLUTE;
#else // !(defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus))
typedef ITEMIDLIST ITEMIDLIST_RELATIVE;
typedef ITEMIDLIST ITEMID_CHILD;
typedef ITEMIDLIST ITEMIDLIST_ABSOLUTE;
#endif // defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus)
#include <poppack.h>
typedef /* [unique] */ __RPC_unique_pointer BYTE_BLOB *wirePIDL;
typedef /* [wire_marshal] */ ITEMIDLIST __unaligned *LPITEMIDLIST;
typedef /* [wire_marshal] */ const ITEMIDLIST __unaligned *LPCITEMIDLIST;
#if defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus)
typedef /* [wire_marshal] */ ITEMIDLIST_ABSOLUTE *PIDLIST_ABSOLUTE;
typedef /* [wire_marshal] */ const ITEMIDLIST_ABSOLUTE *PCIDLIST_ABSOLUTE;
typedef /* [wire_marshal] */ const ITEMIDLIST_ABSOLUTE __unaligned *PCUIDLIST_ABSOLUTE;
typedef /* [wire_marshal] */ ITEMIDLIST_RELATIVE *PIDLIST_RELATIVE;
typedef /* [wire_marshal] */ const ITEMIDLIST_RELATIVE *PCIDLIST_RELATIVE;
typedef /* [wire_marshal] */ ITEMIDLIST_RELATIVE __unaligned *PUIDLIST_RELATIVE;
typedef /* [wire_marshal] */ const ITEMIDLIST_RELATIVE __unaligned *PCUIDLIST_RELATIVE;
typedef /* [wire_marshal] */ ITEMID_CHILD *PITEMID_CHILD;
typedef /* [wire_marshal] */ const ITEMID_CHILD *PCITEMID_CHILD;
typedef /* [wire_marshal] */ ITEMID_CHILD __unaligned *PUITEMID_CHILD;
typedef /* [wire_marshal] */ const ITEMID_CHILD __unaligned *PCUITEMID_CHILD;
typedef const PCUITEMID_CHILD *PCUITEMID_CHILD_ARRAY;
typedef const PCUIDLIST_RELATIVE *PCUIDLIST_RELATIVE_ARRAY;
typedef const PCIDLIST_ABSOLUTE *PCIDLIST_ABSOLUTE_ARRAY;
typedef const PCUIDLIST_ABSOLUTE *PCUIDLIST_ABSOLUTE_ARRAY;
#else // !(defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus))
#define PIDLIST_ABSOLUTE LPITEMIDLIST
#define PCIDLIST_ABSOLUTE LPCITEMIDLIST
#define PCUIDLIST_ABSOLUTE LPCITEMIDLIST
#define PIDLIST_RELATIVE LPITEMIDLIST
#define PCIDLIST_RELATIVE LPCITEMIDLIST
#define PUIDLIST_RELATIVE LPITEMIDLIST
#define PCUIDLIST_RELATIVE LPCITEMIDLIST
#define PITEMID_CHILD LPITEMIDLIST
#define PCITEMID_CHILD LPCITEMIDLIST
#define PUITEMID_CHILD LPITEMIDLIST
#define PCUITEMID_CHILD LPCITEMIDLIST
#define PCUITEMID_CHILD_ARRAY LPCITEMIDLIST *
#define PCUIDLIST_RELATIVE_ARRAY LPCITEMIDLIST *
#define PCIDLIST_ABSOLUTE_ARRAY LPCITEMIDLIST *
#define PCUIDLIST_ABSOLUTE_ARRAY LPCITEMIDLIST *
#endif // defined(STRICT_TYPED_ITEMIDS) && defined(__cplusplus)
#ifdef MIDL_PASS
typedef struct _WIN32_FIND_DATAA
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
CHAR cFileName[ 260 ];
CHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATAA;
typedef struct _WIN32_FIND_DATAA *PWIN32_FIND_DATAA;
typedef struct _WIN32_FIND_DATAA *LPWIN32_FIND_DATAA;
typedef struct _WIN32_FIND_DATAW
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
WCHAR cFileName[ 260 ];
WCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATAW;
typedef struct _WIN32_FIND_DATAW *PWIN32_FIND_DATAW;
typedef struct _WIN32_FIND_DATAW *LPWIN32_FIND_DATAW;
#endif // MIDL_PASS
//-------------------------------------------------------------------------
//
// struct STRRET
//
// structure for returning strings from IShellFolder member functions
//
//-------------------------------------------------------------------------
//
// uType indicate which union member to use
// STRRET_WSTR Use STRRET.pOleStr must be freed by caller of GetDisplayNameOf
// STRRET_OFFSET Use STRRET.uOffset Offset into SHITEMID for ANSI string
// STRRET_CSTR Use STRRET.cStr ANSI Buffer
//
typedef /* [v1_enum] */
enum tagSTRRET_TYPE
{ STRRET_WSTR = 0,
STRRET_OFFSET = 0x1,
STRRET_CSTR = 0x2
} STRRET_TYPE;
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(push)
#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */
#pragma once
#endif
#include <pshpack8.h>
typedef struct _STRRET
{
UINT uType;
union
{
LPWSTR pOleStr;
UINT uOffset;
char cStr[ 260 ];
} DUMMYUNIONNAME;
} STRRET;
#include <poppack.h>
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(pop)
#endif
typedef STRRET *LPSTRRET;
//-------------------------------------------------------------------------
//
// struct SHELLDETAILS
//
// structure for returning strings from IShellDetails
//
//-------------------------------------------------------------------------
//
// fmt; // LVCFMT_* value (header only)
// cxChar; // Number of 'average' characters (header only)
// str; // String information
//
#include <pshpack1.h>
typedef struct _SHELLDETAILS
{
int fmt;
int cxChar;
STRRET str;
} SHELLDETAILS;
typedef struct _SHELLDETAILS *LPSHELLDETAILS;
#include <poppack.h>
#if (_WIN32_IE >= _WIN32_IE_IE60SP2)
typedef /* [v1_enum] */
enum tagPERCEIVED
{ PERCEIVED_TYPE_FIRST = -3,
PERCEIVED_TYPE_CUSTOM = -3,
PERCEIVED_TYPE_UNSPECIFIED = -2,
PERCEIVED_TYPE_FOLDER = -1,
PERCEIVED_TYPE_UNKNOWN = 0,
PERCEIVED_TYPE_TEXT = 1,
PERCEIVED_TYPE_IMAGE = 2,
PERCEIVED_TYPE_AUDIO = 3,
PERCEIVED_TYPE_VIDEO = 4,
PERCEIVED_TYPE_COMPRESSED = 5,
PERCEIVED_TYPE_DOCUMENT = 6,
PERCEIVED_TYPE_SYSTEM = 7,
PERCEIVED_TYPE_APPLICATION = 8,
PERCEIVED_TYPE_GAMEMEDIA = 9,
PERCEIVED_TYPE_CONTACTS = 10,
PERCEIVED_TYPE_LAST = 10
} PERCEIVED;
#define PERCEIVEDFLAG_UNDEFINED 0x0000
#define PERCEIVEDFLAG_SOFTCODED 0x0001
#define PERCEIVEDFLAG_HARDCODED 0x0002
#define PERCEIVEDFLAG_NATIVESUPPORT 0x0004
#define PERCEIVEDFLAG_GDIPLUS 0x0010
#define PERCEIVEDFLAG_WMSDK 0x0020
#define PERCEIVEDFLAG_ZIPFOLDER 0x0040
typedef DWORD PERCEIVEDFLAG;
#endif // _WIN32_IE_IE60SP2
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
typedef struct _COMDLG_FILTERSPEC
{
LPCWSTR pszName;
LPCWSTR pszSpec;
} COMDLG_FILTERSPEC;
typedef struct tagMACHINE_ID
{
char szName[ 16 ];
} MACHINE_ID;
typedef struct tagDOMAIN_RELATIVE_OBJECTID
{
GUID guidVolume;
GUID guidObject;
} DOMAIN_RELATIVE_OBJECTID;
typedef GUID KNOWNFOLDERID;
#if 0
typedef KNOWNFOLDERID *REFKNOWNFOLDERID;
#endif // 0
#ifdef __cplusplus
#define REFKNOWNFOLDERID const KNOWNFOLDERID &
#else // !__cplusplus
#define REFKNOWNFOLDERID const KNOWNFOLDERID * __MIDL_CONST
#endif // __cplusplus
#endif // NTDDI_LONGHORN
typedef GUID FOLDERTYPEID;
#if 0
typedef FOLDERTYPEID *REFFOLDERTYPEID;
#endif // 0
#ifdef __cplusplus
#define REFFOLDERTYPEID const FOLDERTYPEID &
#else // !__cplusplus
#define REFFOLDERTYPEID const FOLDERTYPEID * __MIDL_CONST
#endif // __cplusplus
typedef GUID TASKOWNERID;
#if 0
typedef TASKOWNERID *REFTASKOWNERID;
#endif // 0
#ifdef __cplusplus
#define REFTASKOWNERID const TASKOWNERID &
#else // !__cplusplus
#define REFTASKOWNERID const TASKOWNERID * __MIDL_CONST
#endif // __cplusplus
#ifndef LF_FACESIZE
typedef struct tagLOGFONTA
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
CHAR lfFaceName[ 32 ];
} LOGFONTA;
typedef struct tagLOGFONTW
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
WCHAR lfFaceName[ 32 ];
} LOGFONTW;
typedef LOGFONTA LOGFONT;
#endif // LF_FACESIZE
typedef /* [v1_enum] */
enum tagSHCOLSTATE
{ SHCOLSTATE_TYPE_STR = 0x1,
SHCOLSTATE_TYPE_INT = 0x2,
SHCOLSTATE_TYPE_DATE = 0x3,
SHCOLSTATE_TYPEMASK = 0xf,
SHCOLSTATE_ONBYDEFAULT = 0x10,
SHCOLSTATE_SLOW = 0x20,
SHCOLSTATE_EXTENDED = 0x40,
SHCOLSTATE_SECONDARYUI = 0x80,
SHCOLSTATE_HIDDEN = 0x100,
SHCOLSTATE_PREFER_VARCMP = 0x200,
SHCOLSTATE_PREFER_FMTCMP = 0x400,
SHCOLSTATE_NOSORTBYFOLDERNESS = 0x800,
SHCOLSTATE_VIEWONLY = 0x10000,
SHCOLSTATE_BATCHREAD = 0x20000,
SHCOLSTATE_NO_GROUPBY = 0x40000,
SHCOLSTATE_FIXED_WIDTH = 0x1000,
SHCOLSTATE_NODPISCALE = 0x2000,
SHCOLSTATE_FIXED_RATIO = 0x4000,
SHCOLSTATE_DISPLAYMASK = 0xf000
} SHCOLSTATE;
typedef DWORD SHCOLSTATEF;
typedef PROPERTYKEY SHCOLUMNID;
typedef const SHCOLUMNID *LPCSHCOLUMNID;
extern RPC_IF_HANDLE __MIDL_itf_shtypes_0000_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_shtypes_0000_0000_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -2,24 +2,21 @@
* WASAPI API *
**************
----------------------------------------
Microsoft Visual Studio 2005SP1/2008/10
----------------------------------------
No specific actions are needed to compile WASAPI API under Visual Studio.
-------------------------------------------
Microsoft Visual Studio 2005 SP1 and higher
-------------------------------------------
No specific action is required to compile WASAPI API under Visual Studio.
You are only required to install min. Windows Vista SDK (v6.0A) prior
compilation.
the compilation. To compile with WASAPI specific functionality for Windows 8
and higher the min. Windows 8 SDK is required.
----------------------------------------
MinGW (GCC 32-bit)/ MinGW64 (GCC 64-bit)
MinGW (GCC 32/64-bit)
----------------------------------------
To compile under MinGW you are required to include 'mingw-include' directory
To compile with MinGW you are required to include 'mingw-include' directory
which contains necessary files with WASAPI API. These files are modified
in order to be compiled by MinGW compiler. These files are taken from
Windows Vista SDK (v6.0A). MinGW compilation is tested and proved to be
fully working under 32-bit and 64-bit modes.
MinGW (32-bit) tested: gcc version 4.4.0 (GCC)
MinGW64 (64-bit) tested: gcc version 4.4.4 20100226 (prerelease) (GCC)
PortAudio
/Dmitry Kostjuchenko/
04.03.2010
for the compatibility with MinGW compiler. These files are taken from
the Windows Vista SDK (v6.0A). MinGW compilation is tested and proved to be
fully working.
MinGW (32-bit) tested min. version: gcc version 4.4.0 (GCC)
MinGW64 (64-bit) tested min. version: gcc version 4.4.4 20100226 (prerelease) (GCC)

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,15 @@ Notes about WDM-KS host API
Status history
--------------
16th January 2011:
Added support for WaveRT device API (Vista and later) for even lesser
latency support.
10th November 2005:
Made following changes:
* OpenStream: Try all PaSampleFormats internally if the the chosen
format is not supported natively. This fixed several problems
with soundcards that soundcards that did not take kindly to
using 24-bit 3-byte formats.
with soundcards that did not take kindly to using 24-bit 3-byte formats.
* OpenStream: Make the minimum framesPerHostIBuffer (and framesPerHostOBuffer)
the default frameSize for the playback/recording pin.
* ProcessingThread: Added a switch to only call PaUtil_EndBufferProcessing
@ -71,7 +74,7 @@ In PortAudio terms, this means having a stream Open on a WDMKS device.
Usage
-----
To add the WDMKS backend to your program which is already using
PortAudio, you must undefine PA_NO_WDMKS from your build file,
PortAudio, you must define PA_USE_WDMKS=1 in your build file,
and include the pa_win_wdmks\pa_win_wdmks.c into your build.
The file should compile in both C and C++.
You will need a DirectX SDK installed on your system for the
@ -79,4 +82,4 @@ ks.h and ksmedia.h header files.
You will need to link to the system "setupapi" library.
Note that if you use MinGW, you will get more warnings from
the DX header files when using GCC(C), and still a few warnings
with G++(CPP).
with G++(CPP).

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_win_wmme.c 1739 2011-08-25 07:15:31Z rossb $
* $Id$
* pa_win_wmme.c
* Implementation of PortAudio for Windows MultiMedia Extensions (WMME)
*
@ -62,7 +62,7 @@
*/
/** @file
@ingroup hostapi_src
@ingroup hostapi_src
@brief Win32 host API implementation for the Windows MultiMedia Extensions (WMME) audio API.
*/
@ -86,6 +86,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <windows.h>
#include <mmsystem.h>
@ -201,31 +202,52 @@
static const char constInputMapperSuffix_[] = " - Input";
static const char constOutputMapperSuffix_[] = " - Output";
/*
copies TCHAR string to explicit char string
*/
char *StrTCpyToC(char *to, const TCHAR *from)
/********************************************************************/
/* Copy null-terminated TCHAR string to explicit char string using UTF8 encoding */
static char *CopyTCharStringToUtf8CString(char *destination, size_t destLengthBytes, const TCHAR *source)
{
#if !defined(_UNICODE) && !defined(UNICODE)
return strcpy(to, from);
return strcpy(destination, source);
#else
int count = wcslen(from);
if (count != 0)
if (WideCharToMultiByte(CP_ACP, 0, from, count, to, count, NULL, NULL) == 0)
return NULL;
return to;
/* The cbMultiByte parameter ["destLengthBytes" below] is:
"""
Size, in bytes, of the buffer indicated by lpMultiByteStr ["destination" below].
If this parameter is set to 0, the function returns the required buffer
size for lpMultiByteStr and makes no use of the output parameter itself.
"""
Source: WideCharToMultiByte at MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx
*/
int intDestLengthBytes; /* cbMultiByte */
/* intDestLengthBytes is an int, destLengthBytes is a size_t. Ensure that we don't overflow
intDestLengthBytes by only using at most INT_MAX bytes of destination buffer.
*/
if (destLengthBytes < INT_MAX)
{
#pragma warning (disable : 4267) /* "conversion from 'size_t' to 'int', possible loss of data" */
intDestLengthBytes = (int)destLengthBytes; /* destLengthBytes is guaranteed < INT_MAX here */
#pragma warning (default : 4267)
}
else
{
intDestLengthBytes = INT_MAX;
}
if (WideCharToMultiByte(CP_UTF8, 0, source, -1, destination, /*cbMultiByte=*/intDestLengthBytes, NULL, NULL) == 0)
return NULL;
return destination;
#endif
}
/*
returns length of TCHAR string
*/
size_t StrTLen(const TCHAR *str)
/* returns required length (in bytes) of destination buffer when
converting TCHAR string to UTF8 bytes, not including the terminating null. */
static size_t TCharStringLen(const TCHAR *str)
{
#if !defined(_UNICODE) && !defined(UNICODE)
return strlen(str);
return strlen(str);
#else
return wcslen(str);
return WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
#endif
}
@ -450,7 +472,7 @@ static PaDeviceIndex GetEnvDefaultDeviceID( char *envName )
#ifndef WIN32_PLATFORM_PSPC /* no GetEnvironmentVariable on PocketPC */
/* Let user determine default device by setting environment variable. */
hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE_ );
hresult = GetEnvironmentVariableA( envName, envbuf, PA_ENV_BUF_SIZE_ );
if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE_) )
{
recommendedIndex = atoi( envbuf );
@ -491,7 +513,7 @@ static UINT LocalDeviceIndexToWinMmeDeviceId( PaWinMmeHostApiRepresentation *hos
{
assert( device >= 0 && device < hostApi->inputDeviceCount + hostApi->outputDeviceCount );
return hostApi->winMmeDeviceIds[ device ];
return hostApi->winMmeDeviceIds[ device ];
}
@ -686,6 +708,7 @@ static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeH
MMRESULT mmresult;
WAVEINCAPS wic;
PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
size_t len;
*success = 0;
@ -705,29 +728,35 @@ static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeH
return paNoError;
}
/* NOTE: the WAVEOUTCAPS.szPname is a null-terminated array of 32 characters,
so we are limited to displaying only the first 31 characters of the device name. */
if( winMmeInputDeviceId == WAVE_MAPPER )
{
len = TCharStringLen( wic.szPname ) + 1 + sizeof(constInputMapperSuffix_);
/* Append I/O suffix to WAVE_MAPPER device. */
deviceName = (char *)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations, StrTLen( wic.szPname ) + 1 + sizeof(constInputMapperSuffix_) );
deviceName = (char*)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations,
(long)len );
if( !deviceName )
{
result = paInsufficientMemory;
goto error;
}
StrTCpyToC( deviceName, wic.szPname );
CopyTCharStringToUtf8CString( deviceName, len, wic.szPname );
strcat( deviceName, constInputMapperSuffix_ );
}
else
{
len = TCharStringLen( wic.szPname ) + 1;
deviceName = (char*)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations, StrTLen( wic.szPname ) + 1 );
winMmeHostApi->allocations,
(long)len );
if( !deviceName )
{
result = paInsufficientMemory;
goto error;
}
StrTCpyToC( deviceName, wic.szPname );
CopyTCharStringToUtf8CString( deviceName, len, wic.szPname );
}
deviceInfo->name = deviceName;
@ -809,6 +838,7 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
MMRESULT mmresult;
WAVEOUTCAPS woc;
PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
size_t len;
#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
int wdmksDeviceOutputChannelCountIsKnown;
#endif
@ -831,29 +861,35 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
return paNoError;
}
/* NOTE: the WAVEOUTCAPS.szPname is a null-terminated array of 32 characters,
so we are limited to displaying only the first 31 characters of the device name. */
if( winMmeOutputDeviceId == WAVE_MAPPER )
{
/* Append I/O suffix to WAVE_MAPPER device. */
deviceName = (char *)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations, StrTLen( woc.szPname ) + 1 + sizeof(constOutputMapperSuffix_) );
len = TCharStringLen( woc.szPname ) + 1 + sizeof(constOutputMapperSuffix_);
deviceName = (char*)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations,
(long)len );
if( !deviceName )
{
result = paInsufficientMemory;
goto error;
}
StrTCpyToC( deviceName, woc.szPname );
CopyTCharStringToUtf8CString( deviceName, len, woc.szPname );
strcat( deviceName, constOutputMapperSuffix_ );
}
else
{
len = TCharStringLen( woc.szPname ) + 1;
deviceName = (char*)PaUtil_GroupAllocateMemory(
winMmeHostApi->allocations, StrTLen( woc.szPname ) + 1 );
winMmeHostApi->allocations,
(long)len );
if( !deviceName )
{
result = paInsufficientMemory;
goto error;
}
StrTCpyToC( deviceName, woc.szPname );
CopyTCharStringToUtf8CString( deviceName, len, woc.szPname );
}
deviceInfo->name = deviceName;
@ -878,7 +914,7 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
wdmksDeviceOutputChannelCountIsKnown = QueryWaveOutKSFilterMaxChannels(
winMmeOutputDeviceId, &deviceInfo->maxOutputChannels );
winMmeOutputDeviceId, &deviceInfo->maxOutputChannels );
if( wdmksDeviceOutputChannelCountIsKnown && !winMmeDeviceInfo->deviceOutputChannelCountIsKnown )
winMmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
@ -897,9 +933,19 @@ error:
static void GetDefaultLatencies( PaTime *defaultLowLatency, PaTime *defaultHighLatency )
{
/*
NOTE: GetVersionEx() is deprecated as of Windows 8.1 and can not be used to reliably detect
versions of Windows higher than Windows 8 (due to manifest requirements for reporting higher versions).
Microsoft recommends switching to VerifyVersionInfo (available on Win 2k and later), however GetVersionEx
is is faster, for now we just disable the deprecation warning.
See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
See: http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe
*/
#pragma warning (disable : 4996) /* use of GetVersionEx */
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof( osvi );
GetVersionEx( &osvi );
GetVersionEx( &osvi );
/* Check for NT */
if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) )
@ -916,6 +962,8 @@ static void GetDefaultLatencies( PaTime *defaultLowLatency, PaTime *defaultHighL
}
*defaultHighLatency = *defaultLowLatency * 2;
#pragma warning (default : 4996)
}
@ -979,11 +1027,11 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
inputDeviceCount = waveInGetNumDevs();
if( inputDeviceCount > 0 )
maximumPossibleDeviceCount += inputDeviceCount + 1; /* assume there is a WAVE_MAPPER */
maximumPossibleDeviceCount += inputDeviceCount + 1; /* assume there is a WAVE_MAPPER */
outputDeviceCount = waveOutGetNumDevs();
if( outputDeviceCount > 0 )
maximumPossibleDeviceCount += outputDeviceCount + 1; /* assume there is a WAVE_MAPPER */
maximumPossibleDeviceCount += outputDeviceCount + 1; /* assume there is a WAVE_MAPPER */
if( maximumPossibleDeviceCount > 0 ){
@ -2153,29 +2201,29 @@ static PaError ValidateWinMmeSpecificStreamInfo(
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
if( streamInfo )
{
if( streamInfo->size != sizeof( PaWinMmeStreamInfo )
|| streamInfo->version != 1 )
{
return paIncompatibleHostApiSpecificStreamInfo;
}
if( streamInfo )
{
if( streamInfo->size != sizeof( PaWinMmeStreamInfo )
|| streamInfo->version != 1 )
{
return paIncompatibleHostApiSpecificStreamInfo;
}
*winMmeSpecificFlags = streamInfo->flags;
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
if( streamInfo->flags & paWinMmeUseMultipleDevices )
{
if( streamParameters->device != paUseHostApiSpecificDeviceSpecification )
return paInvalidDevice;
*deviceCount = streamInfo->deviceCount;
}
}
if( streamInfo->flags & paWinMmeUseMultipleDevices )
{
if( streamParameters->device != paUseHostApiSpecificDeviceSpecification )
return paInvalidDevice;
*deviceCount = streamInfo->deviceCount;
}
}
return paNoError;
return paNoError;
}
static PaError RetrieveDevicesFromStreamParameters(
@ -2190,34 +2238,34 @@ static PaError RetrieveDevicesFromStreamParameters(
int totalChannelCount;
PaDeviceIndex hostApiDevice;
if( streamInfo && streamInfo->flags & paWinMmeUseMultipleDevices )
{
totalChannelCount = 0;
for( i=0; i < deviceCount; ++i )
{
/* validate that the device number is within range */
result = PaUtil_DeviceIndexToHostApiDeviceIndex( &hostApiDevice,
streamInfo->devices[i].device, hostApi );
if( result != paNoError )
return result;
devices[i].device = hostApiDevice;
devices[i].channelCount = streamInfo->devices[i].channelCount;
totalChannelCount += devices[i].channelCount;
}
if( totalChannelCount != streamParameters->channelCount )
{
/* channelCount must match total channels specified by multiple devices */
return paInvalidChannelCount; /* REVIEW use of this error code */
}
}
else
{
devices[0].device = streamParameters->device;
devices[0].channelCount = streamParameters->channelCount;
}
if( streamInfo && streamInfo->flags & paWinMmeUseMultipleDevices )
{
totalChannelCount = 0;
for( i=0; i < deviceCount; ++i )
{
/* validate that the device number is within range */
result = PaUtil_DeviceIndexToHostApiDeviceIndex( &hostApiDevice,
streamInfo->devices[i].device, hostApi );
if( result != paNoError )
return result;
devices[i].device = hostApiDevice;
devices[i].channelCount = streamInfo->devices[i].channelCount;
totalChannelCount += devices[i].channelCount;
}
if( totalChannelCount != streamParameters->channelCount )
{
/* channelCount must match total channels specified by multiple devices */
return paInvalidChannelCount; /* REVIEW use of this error code */
}
}
else
{
devices[0].device = streamParameters->device;
devices[0].channelCount = streamParameters->channelCount;
}
return result;
}
@ -2231,10 +2279,10 @@ static PaError ValidateInputChannelCounts(
PaWinMmeDeviceInfo *inputDeviceInfo;
PaError paerror;
for( i=0; i < deviceCount; ++i )
{
for( i=0; i < deviceCount; ++i )
{
if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
return paInvalidChannelCount;
inputDeviceInfo =
(PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
@ -2242,7 +2290,7 @@ static PaError ValidateInputChannelCounts(
paerror = IsInputChannelCountSupported( inputDeviceInfo, devices[i].channelCount );
if( paerror != paNoError )
return paerror;
}
}
return paNoError;
}
@ -2256,10 +2304,10 @@ static PaError ValidateOutputChannelCounts(
PaWinMmeDeviceInfo *outputDeviceInfo;
PaError paerror;
for( i=0; i < deviceCount; ++i )
{
for( i=0; i < deviceCount; ++i )
{
if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
return paInvalidChannelCount;
outputDeviceInfo =
(PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
@ -2267,7 +2315,7 @@ static PaError ValidateOutputChannelCounts(
paerror = IsOutputChannelCountSupported( outputDeviceInfo, devices[i].channelCount );
if( paerror != paNoError )
return paerror;
}
}
return paNoError;
}
@ -2316,28 +2364,28 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( inputParameters )
{
inputChannelCount = inputParameters->channelCount;
inputChannelCount = inputParameters->channelCount;
inputSampleFormat = inputParameters->sampleFormat;
suggestedInputLatency = inputParameters->suggestedLatency;
inputDeviceCount = 1;
inputDeviceCount = 1;
/* validate input hostApiSpecificStreamInfo */
/* validate input hostApiSpecificStreamInfo */
inputStreamInfo = (PaWinMmeStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( inputParameters, inputStreamInfo,
result = ValidateWinMmeSpecificStreamInfo( inputParameters, inputStreamInfo,
&winMmeSpecificInputFlags,
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
inputDevices = (PaWinMmeDeviceAndChannelCount*)alloca( sizeof(PaWinMmeDeviceAndChannelCount) * inputDeviceCount );
inputDevices = (PaWinMmeDeviceAndChannelCount*)alloca( sizeof(PaWinMmeDeviceAndChannelCount) * inputDeviceCount );
if( !inputDevices ) return paInsufficientMemory;
result = RetrieveDevicesFromStreamParameters( hostApi, inputParameters, inputStreamInfo, inputDevices, inputDeviceCount );
if( result != paNoError ) return result;
result = RetrieveDevicesFromStreamParameters( hostApi, inputParameters, inputStreamInfo, inputDevices, inputDeviceCount );
if( result != paNoError ) return result;
result = ValidateInputChannelCounts( hostApi, inputDevices, inputDeviceCount );
if( result != paNoError ) return result;
result = ValidateInputChannelCounts( hostApi, inputDevices, inputDeviceCount );
if( result != paNoError ) return result;
hostInputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
@ -2353,7 +2401,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
else
inputChannelMask = PaWin_DefaultChannelMask( inputDevices[0].channelCount );
}
}
}
else
{
inputChannelCount = 0;
@ -2372,22 +2420,22 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
outputDeviceCount = 1;
/* validate output hostApiSpecificStreamInfo */
/* validate output hostApiSpecificStreamInfo */
outputStreamInfo = (PaWinMmeStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( outputParameters, outputStreamInfo,
result = ValidateWinMmeSpecificStreamInfo( outputParameters, outputStreamInfo,
&winMmeSpecificOutputFlags,
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
outputDevices = (PaWinMmeDeviceAndChannelCount*)alloca( sizeof(PaWinMmeDeviceAndChannelCount) * outputDeviceCount );
outputDevices = (PaWinMmeDeviceAndChannelCount*)alloca( sizeof(PaWinMmeDeviceAndChannelCount) * outputDeviceCount );
if( !outputDevices ) return paInsufficientMemory;
result = RetrieveDevicesFromStreamParameters( hostApi, outputParameters, outputStreamInfo, outputDevices, outputDeviceCount );
if( result != paNoError ) return result;
result = RetrieveDevicesFromStreamParameters( hostApi, outputParameters, outputStreamInfo, outputDevices, outputDeviceCount );
if( result != paNoError ) return result;
result = ValidateOutputChannelCounts( hostApi, outputDevices, outputDeviceCount );
if( result != paNoError ) return result;
result = ValidateOutputChannelCounts( hostApi, outputDevices, outputDeviceCount );
if( result != paNoError ) return result;
hostOutputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
@ -3215,9 +3263,9 @@ static PaError StartStream( PaStream *s )
MMRESULT mmresult;
unsigned int i, j;
int callbackResult;
unsigned int channel;
unsigned long framesProcessed;
PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /** @todo implement this for stream priming */
unsigned int channel;
unsigned long framesProcessed;
PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /** @todo implement this for stream priming */
PaUtil_ResetBufferProcessor( &stream->bufferProcessor );

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_unix_hostapis.c 1740 2011-08-25 07:17:48Z philburk $
* $Id$
* Portable Audio I/O Library UNIX initialization table
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_unix_util.c 1510 2010-06-10 08:05:29Z dmitrykos $
* $Id$
* Portable Audio I/O Library
* UNIX platform-specific support functions
*

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_unix_util.h 1241 2007-07-23 20:08:31Z aknudsen $
* $Id$
* Portable Audio I/O Library
* UNIX platform-specific support functions
*

View File

@ -52,7 +52,7 @@
#include "pa_win_coinitialize.h"
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) /* MSC version 6 and above */
#pragma comment( lib, "ole32.lib" )
#endif
@ -76,7 +76,11 @@ PaError PaWinUtil_CoInitialize( PaHostApiTypeId hostApiType, PaWinUtilComInitial
RPC_E_CHANGED_MODE was returned.
*/
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_APP)
hr = CoInitialize(0); /* use legacy-safe equivalent to CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) */
#else
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
#endif
if( FAILED(hr) && hr != RPC_E_CHANGED_MODE )
{
PA_DEBUG(("CoInitialize(0) failed. hr=%d\n", hr));

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_win_hostapis.c 1728 2011-08-18 03:31:51Z rossb $
* $Id$
* Portable Audio I/O Library Windows initialization table
*
* Based on the Open Source API proposed by Ross Bencina

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_win_util.c 1584 2011-02-02 18:58:17Z rossb $
* $Id$
* Portable Audio I/O Library
* Win32 platform-specific support functions
*
@ -44,14 +44,17 @@
*/
#include <windows.h>
#include <mmsystem.h> /* for timeGetTime() */
#include "pa_util.h"
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
#pragma comment( lib, "winmm.lib" )
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
#include <sys/timeb.h> /* for _ftime_s() */
#else
#include <mmsystem.h> /* for timeGetTime() */
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
#pragma comment( lib, "winmm.lib" )
#endif
#endif
#include "pa_util.h"
/*
Track memory allocations to avoid leaks.
@ -144,8 +147,12 @@ double PaUtil_GetTime( void )
}
else
{
#ifndef UNDER_CE
#ifndef UNDER_CE
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
return GetTickCount64() * .001;
#else
return timeGetTime() * .001;
#endif
#else
return GetTickCount() * .001;
#endif

View File

@ -38,6 +38,9 @@
#include <windows.h>
#include <mmsystem.h>
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
#include <mmreg.h> /* for WAVEFORMATEX */
#endif
#include "portaudio.h"
#include "pa_win_waveformat.h"
@ -47,6 +50,7 @@
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
static GUID pawin_ksDataFormatSubtypeGuidBase =
{ (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };
@ -104,7 +108,6 @@ void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
*((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid;
}
PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels )
{
switch( numChannels ){
@ -129,11 +132,16 @@ PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels )
return PAWIN_SPEAKER_5POINT1;
/* case 7: */
case 8:
return PAWIN_SPEAKER_7POINT1;
/* RoBi: PAWIN_SPEAKER_7POINT1_SURROUND fits normal surround sound setups better than PAWIN_SPEAKER_7POINT1, f.i. NVidia HDMI Audio
output is silent on channels 5&6 with NVidia drivers, and channel 7&8 with Micrsoft HD Audio driver using PAWIN_SPEAKER_7POINT1.
With PAWIN_SPEAKER_7POINT1_SURROUND both setups work OK. */
return PAWIN_SPEAKER_7POINT1_SURROUND;
}
/* Apparently some Audigy drivers will output silence
if the direct-out constant (0) is used. So this is not ideal.
RoBi 2012-12-19: Also, NVidia driver seem to output garbage instead. Again not very ideal.
*/
return PAWIN_SPEAKER_DIRECTOUT;

View File

@ -47,41 +47,53 @@
#define _INC_MMREG // for STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
#endif
#include <winioctl.h> // MinGW32 does not define this automatically
#if defined(__GNUC__)
#include "../../hostapi/wasapi/mingw-include/ks.h"
#include "../../hostapi/wasapi/mingw-include/ksmedia.h"
#else
#include <ks.h>
#include <ksmedia.h>
#endif
#include <stdio.h> // just for some development printfs
#include "portaudio.h"
#include "pa_util.h"
#include "pa_win_wdmks_utils.h"
#if !defined(PA_WDMKS_NO_KSGUID_LIB) && !defined(PAWIN_WDMKS_NO_KSGUID_LIB)
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
#pragma comment( lib, "ksguid.lib" )
#endif
#define pa_KSDATAFORMAT_TYPE_AUDIO KSDATAFORMAT_TYPE_AUDIO
#define pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
#define pa_KSDATAFORMAT_SUBTYPE_PCM KSDATAFORMAT_SUBTYPE_PCM
#define pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX KSDATAFORMAT_SUBTYPE_WAVEFORMATEX
#define pa_KSMEDIUMSETID_Standard KSMEDIUMSETID_Standard
#define pa_KSINTERFACESETID_Standard KSINTERFACESETID_Standard
#define pa_KSPROPSETID_Pin KSPROPSETID_Pin
#else
static const GUID pa_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO };
static const GUID pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT };
static const GUID pa_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM };
static const GUID pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX };
static const GUID pa_KSMEDIUMSETID_Standard = { STATIC_KSMEDIUMSETID_Standard };
static const GUID pa_KSINTERFACESETID_Standard = { STATIC_KSINTERFACESETID_Standard };
static const GUID pa_KSPROPSETID_Pin = { STATIC_KSPROPSETID_Pin };
#endif
/* PortAudio-local instances of GUIDs previously sourced from ksguid.lib */
/* GUID KSDATAFORMAT_TYPE_AUDIO */
static const GUID pa_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO };
/* GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT */
static const GUID pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT };
/* GUID KSDATAFORMAT_SUBTYPE_PCM */
static const GUID pa_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM };
/* GUID KSDATAFORMAT_SUBTYPE_WAVEFORMATEX */
static const GUID pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX };
/* GUID KSMEDIUMSETID_Standard */
static const GUID pa_KSMEDIUMSETID_Standard = { STATIC_KSMEDIUMSETID_Standard };
/* GUID KSINTERFACESETID_Standard */
static const GUID pa_KSINTERFACESETID_Standard = { STATIC_KSINTERFACESETID_Standard };
/* GUID KSPROPSETID_Pin */
static const GUID pa_KSPROPSETID_Pin = { STATIC_KSPROPSETID_Pin };
#define pa_IS_VALID_WAVEFORMATEX_GUID(Guid)\
(!memcmp(((PUSHORT)&pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) + 1, ((PUSHORT)(Guid)) + 1, sizeof(GUID) - sizeof(USHORT)))
static PaError WdmGetPinPropertySimple(
HANDLE handle,
unsigned long pinId,

View File

@ -112,6 +112,18 @@ TODO:
0011 1111 1000 0000 0000 0000 0000 0000 => 0x3F800000
*/
#if defined(_WIN64) || defined(_WIN32_WCE)
/*
-EMT64/AMD64 uses different asm
-VC2005 doesnt allow _WIN64 with inline assembly either!
*/
void PaUtil_InitializeX86PlainConverters( void )
{
}
#else
/* -------------------------------------------------------------------------- */
static const short fpuControlWord_ = 0x033F; /*round to nearest, 64 bit precision, all exceptions masked*/
@ -130,19 +142,6 @@ static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
/* -------------------------------------------------------------------------- */
#if defined(_WIN64) || defined(_WIN32_WCE)
/*
-EMT64/AMD64 uses different asm
-VC2005 doesnt allow _WIN64 with inline assembly either!
*/
void PaUtil_InitializeX86PlainConverters( void )
{
}
#else
static void Float32_To_Int32(
void *destinationBuffer, signed int destinationStride,
void *sourceBuffer, signed int sourceStride,