PortAudio  2.0
Data Structures | Macros | Typedefs | Functions
pa_win_wmme.c File Reference

Win32 host API implementation for the Windows MultiMedia Extensions (WMME) audio API. More...

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <windows.h>
#include <mmsystem.h>
#include <process.h>
#include <assert.h>
#include <malloc.h>
#include <memory.h>
#include "portaudio.h"
#include "pa_trace.h"
#include "pa_util.h"
#include "pa_allocation.h"
#include "pa_hostapi.h"
#include "pa_stream.h"
#include "pa_cpuload.h"
#include "pa_process.h"
#include "pa_debugprint.h"
#include "pa_win_wmme.h"
#include "pa_win_waveformat.h"
#include "pa_win_util.h"
#include "pa_win_version.h"

Data Structures

struct  PaWinMmeHostApiRepresentation
 
struct  PaWinMmeDeviceInfo
 
struct  PaWinMmeSingleDirectionHandlesAndBuffers
 
struct  PaWinMmeStream
 

Macros

#define CREATE_THREAD   (HANDLE)_beginthreadex( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
 
#define PA_THREAD_FUNC   static unsigned WINAPI
 
#define PA_THREAD_ID   unsigned
 
#define DWORD_PTR   unsigned long
 
#define PA_MME_USE_HIGH_DEFAULT_LATENCY_   (0) /* For debugging glitches. */
 
#define PA_MME_WIN_9X_DEFAULT_LATENCY_   (0.2)
 
#define PA_MME_MIN_HOST_OUTPUT_BUFFER_COUNT_   (2)
 
#define PA_MME_MIN_HOST_INPUT_BUFFER_COUNT_FULL_DUPLEX_   (3) /* always use at least 3 input buffers for full duplex */
 
#define PA_MME_MIN_HOST_INPUT_BUFFER_COUNT_HALF_DUPLEX_   (2)
 
#define PA_MME_HOST_BUFFER_GRANULARITY_FRAMES_WHEN_UNSPECIFIED_   (16)
 
#define PA_MME_MAX_HOST_BUFFER_SECS_   (0.1) /* Do not exceed unless user buffer exceeds */
 
#define PA_MME_MAX_HOST_BUFFER_BYTES_   (32 * 1024) /* Has precedence over PA_MME_MAX_HOST_BUFFER_SECS_, some drivers are known to crash with buffer sizes > 32k */
 
#define PA_MME_WIN_NT_DEFAULT_LATENCY_   (0.4)
 
#define PA_MME_WIN_WDM_DEFAULT_LATENCY_   (0.090)
 
#define PA_MME_TARGET_HOST_BUFFER_COUNT_   8
 
#define PA_MME_MIN_TIMEOUT_MSEC_   (1000)
 
#define PA_MME_SET_LAST_WAVEIN_ERROR(mmresult)
 
#define PA_MME_SET_LAST_WAVEOUT_ERROR(mmresult)
 
#define PA_MME_SET_LAST_SYSTEM_ERROR(errorCode)   PaMme_SetLastSystemError( errorCode )
 
#define PA_ENV_BUF_SIZE_   (32)
 
#define PA_REC_IN_DEV_ENV_NAME_   ("PA_RECOMMENDED_INPUT_DEVICE")
 
#define PA_REC_OUT_DEV_ENV_NAME_   ("PA_RECOMMENDED_OUTPUT_DEVICE")
 
#define PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_   (13) /* must match array length below */
 
#define DRVM_MAPPER_PREFERRED_GET   (0x2000+21)
 
#define PA_IS_INPUT_STREAM_(stream)   ( stream ->input.waveHandles )
 
#define PA_IS_OUTPUT_STREAM_(stream)   ( stream ->output.waveHandles )
 
#define PA_IS_FULL_DUPLEX_STREAM_(stream)   ( stream ->input.waveHandles && stream ->output.waveHandles )
 
#define PA_IS_HALF_DUPLEX_STREAM_(stream)   ( !(stream ->input.waveHandles && stream ->output.waveHandles) )
 
#define PA_CIRCULAR_INCREMENT_(current, max)   ( (((current) + 1) >= (max)) ? (0) : (current+1) )
 
#define PA_CIRCULAR_DECREMENT_(current, max)   ( ((current) == 0) ? ((max)-1) : (current-1) )
 

Typedefs

typedef struct PaWinMmeStream PaWinMmeStream
 

Functions

PaError PaWinMme_Initialize (PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index)
 
PA_THREAD_FUNC ProcessingThreadProc (void *pArg)
 
int PaWinMME_GetStreamInputHandleCount (PaStream *s)
 
HWAVEIN PaWinMME_GetStreamInputHandle (PaStream *s, int handleIndex)
 
int PaWinMME_GetStreamOutputHandleCount (PaStream *s)
 
HWAVEOUT PaWinMME_GetStreamOutputHandle (PaStream *s, int handleIndex)
 

Detailed Description

Win32 host API implementation for the Windows MultiMedia Extensions (WMME) audio API.

Macro Definition Documentation

#define CREATE_THREAD   (HANDLE)_beginthreadex( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
#define DRVM_MAPPER_PREFERRED_GET   (0x2000+21)

Referenced by PaWinMme_Initialize().

#define DWORD_PTR   unsigned long

Referenced by PaWinMme_Initialize().

#define PA_CIRCULAR_DECREMENT_ (   current,
  max 
)    ( ((current) == 0) ? ((max)-1) : (current-1) )
#define PA_CIRCULAR_INCREMENT_ (   current,
  max 
)    ( (((current) + 1) >= (max)) ? (0) : (current+1) )
#define PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_   (13) /* must match array length below */
#define PA_ENV_BUF_SIZE_   (32)
#define PA_IS_FULL_DUPLEX_STREAM_ (   stream)    ( stream ->input.waveHandles && stream ->output.waveHandles )

Referenced by ProcessingThreadProc().

#define PA_IS_HALF_DUPLEX_STREAM_ (   stream)    ( !(stream ->input.waveHandles && stream ->output.waveHandles) )

Referenced by ProcessingThreadProc().

#define PA_IS_INPUT_STREAM_ (   stream)    ( stream ->input.waveHandles )
#define PA_IS_OUTPUT_STREAM_ (   stream)    ( stream ->output.waveHandles )
#define PA_MME_HOST_BUFFER_GRANULARITY_FRAMES_WHEN_UNSPECIFIED_   (16)
#define PA_MME_MAX_HOST_BUFFER_BYTES_   (32 * 1024) /* Has precedence over PA_MME_MAX_HOST_BUFFER_SECS_, some drivers are known to crash with buffer sizes > 32k */
#define PA_MME_MAX_HOST_BUFFER_SECS_   (0.1) /* Do not exceed unless user buffer exceeds */
#define PA_MME_MIN_HOST_INPUT_BUFFER_COUNT_FULL_DUPLEX_   (3) /* always use at least 3 input buffers for full duplex */
#define PA_MME_MIN_HOST_INPUT_BUFFER_COUNT_HALF_DUPLEX_   (2)
#define PA_MME_MIN_HOST_OUTPUT_BUFFER_COUNT_   (2)
#define PA_MME_MIN_TIMEOUT_MSEC_   (1000)
#define PA_MME_SET_LAST_SYSTEM_ERROR (   errorCode)    PaMme_SetLastSystemError( errorCode )
#define PA_MME_SET_LAST_WAVEIN_ERROR (   mmresult)
Value:
{ \
wchar_t mmeErrorTextWide[ MAXERRORLENGTH ]; \
char mmeErrorText[ MAXERRORLENGTH ]; \
waveInGetErrorTextW( mmresult, mmeErrorTextWide, MAXERRORLENGTH ); \
WideCharToMultiByte( CP_UTF8, 0, mmeErrorTextWide, -1, \
mmeErrorText, MAXERRORLENGTH, NULL, NULL ); \
PaUtil_SetLastHostErrorInfo( paMME, mmresult, mmeErrorText ); \
}
void PaUtil_SetLastHostErrorInfo(PaHostApiTypeId hostApiType, long errorCode, const char *errorText)
Definition: pa_front.c:142
Definition: portaudio.h:281
#define PA_MME_SET_LAST_WAVEOUT_ERROR (   mmresult)
Value:
{ \
wchar_t mmeErrorTextWide[ MAXERRORLENGTH ]; \
char mmeErrorText[ MAXERRORLENGTH ]; \
waveOutGetErrorTextW( mmresult, mmeErrorTextWide, MAXERRORLENGTH ); \
WideCharToMultiByte( CP_UTF8, 0, mmeErrorTextWide, -1, \
mmeErrorText, MAXERRORLENGTH, NULL, NULL ); \
PaUtil_SetLastHostErrorInfo( paMME, mmresult, mmeErrorText ); \
}
void PaUtil_SetLastHostErrorInfo(PaHostApiTypeId hostApiType, long errorCode, const char *errorText)
Definition: pa_front.c:142
Definition: portaudio.h:281
#define PA_MME_TARGET_HOST_BUFFER_COUNT_   8
#define PA_MME_USE_HIGH_DEFAULT_LATENCY_   (0) /* For debugging glitches. */
#define PA_MME_WIN_9X_DEFAULT_LATENCY_   (0.2)
#define PA_MME_WIN_NT_DEFAULT_LATENCY_   (0.4)
#define PA_MME_WIN_WDM_DEFAULT_LATENCY_   (0.090)
#define PA_REC_IN_DEV_ENV_NAME_   ("PA_RECOMMENDED_INPUT_DEVICE")
#define PA_REC_OUT_DEV_ENV_NAME_   ("PA_RECOMMENDED_OUTPUT_DEVICE")
#define PA_THREAD_FUNC   static unsigned WINAPI
#define PA_THREAD_ID   unsigned

Typedef Documentation

Function Documentation

HWAVEIN PaWinMME_GetStreamInputHandle ( PaStream stream,
int  handleIndex 
)

Retrieve a wave in handle used by a PortAudio WinMME stream.

Parameters
streamThe stream to query.
handleIndexThe zero based index of the wave in handle to retrieve. This should be in the range [0, PaWinMME_GetStreamInputHandleCount(stream)-1].
Returns
A valid wave in handle, or NULL if an error occurred.
See Also
PaWinMME_GetStreamInputHandle

References PaWinMmeStream::input, PA_IS_INPUT_STREAM_, paNoError, and PaWinMmeSingleDirectionHandlesAndBuffers::waveHandles.

int PaWinMME_GetStreamInputHandleCount ( PaStream stream)

Retrieve the number of wave in handles used by a PortAudio WinMME stream. Returns zero if the stream is output only.

Returns
A non-negative value indicating the number of wave in handles or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an error is encountered.
See Also
PaWinMME_GetStreamInputHandle

References PaWinMmeSingleDirectionHandlesAndBuffers::deviceCount, PaWinMmeStream::input, PA_IS_INPUT_STREAM_, and paNoError.

HWAVEOUT PaWinMME_GetStreamOutputHandle ( PaStream stream,
int  handleIndex 
)

Retrieve a wave out handle used by a PortAudio WinMME stream.

Parameters
streamThe stream to query.
handleIndexThe zero based index of the wave out handle to retrieve. This should be in the range [0, PaWinMME_GetStreamOutputHandleCount(stream)-1].
Returns
A valid wave out handle, or NULL if an error occurred.
See Also
PaWinMME_GetStreamOutputHandleCount

References PaWinMmeStream::output, PA_IS_OUTPUT_STREAM_, paNoError, and PaWinMmeSingleDirectionHandlesAndBuffers::waveHandles.

int PaWinMME_GetStreamOutputHandleCount ( PaStream stream)

Retrieve the number of wave out handles used by a PortAudio WinMME stream. Returns zero if the stream is input only.

Returns
A non-negative value indicating the number of wave out handles or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an error is encountered.
See Also
PaWinMME_GetStreamOutputHandle

References PaWinMmeSingleDirectionHandlesAndBuffers::deviceCount, PaWinMmeStream::output, PA_IS_OUTPUT_STREAM_, and paNoError.

PaError PaWinMme_Initialize ( PaUtilHostApiRepresentation **  hostApi,
PaHostApiIndex  index 
)

References PaWinMmeHostApiRepresentation::allocations, PaWinMmeHostApiRepresentation::blockingStreamInterface, PaWinMmeHostApiRepresentation::callbackStreamInterface, PaDeviceInfo::defaultHighInputLatency, PaDeviceInfo::defaultHighOutputLatency, PaDeviceInfo::defaultLowInputLatency, PaDeviceInfo::defaultLowOutputLatency, PaWinMmeDeviceInfo::deviceInputChannelCountIsKnown, PaWinMmeDeviceInfo::deviceOutputChannelCountIsKnown, DRVM_MAPPER_PREFERRED_GET, DWORD_PTR, GetStreamCpuLoad(), GetStreamReadAvailable(), GetStreamTime(), GetStreamWriteAvailable(), PaDeviceInfo::hostApi, PaUtilHostApiRepresentation::info, PaWinMmeDeviceInfo::inheritedDeviceInfo, PaWinMmeHostApiRepresentation::inheritedHostApiRep, PaWinMmeHostApiRepresentation::inputDeviceCount, IsFormatSupported(), IsStreamActive(), IsStreamStopped(), PaDeviceInfo::maxInputChannels, PaDeviceInfo::maxOutputChannels, OpenStream(), PaWinMmeHostApiRepresentation::outputDeviceCount, paInsufficientMemory, paMME, paNoDevice, paNoError, PaUtil_AllocateZeroInitializedMemory(), PaUtil_CreateAllocationGroup(), PaUtil_DestroyAllocationGroup(), PaUtil_DummyGetCpuLoad(), PaUtil_DummyGetReadAvailable(), PaUtil_DummyGetWriteAvailable(), PaUtil_DummyRead(), PaUtil_DummyWrite(), PaUtil_FreeAllAllocations(), PaUtil_FreeMemory(), PaUtil_GroupAllocateZeroInitializedMemory(), PaUtil_InitializeStreamInterface(), ReadStream(), PaHostApiInfo::structVersion, PaDeviceInfo::structVersion, Terminate(), PaWinMmeHostApiRepresentation::winMmeDeviceIds, and WriteStream().

PA_THREAD_FUNC ProcessingThreadProc ( void *  pArg)
Todo:
support paInputUnderflow, paOutputOverflow and paNeverDropInput
Todo:
FIXME/REVIEW: can't return host error info from an asynchronous thread. see http://www.portaudio.com/trac/ticket/143
Todo:
if all of the other buffers are also ready then we discard all but the most recent. This is an input buffer overflow. FIXME: these buffers should be passed to the callback in a paNeverDropInput stream. http://www.portaudio.com/trac/ticket/142

note that it is also possible for an input overflow to happen while the callback is processing a buffer. that is handled further down.

Todo:
implement inputBufferAdcTime
Todo:
FIXME: should probably reset the output device immediately once the callback returns paAbort see: http://www.portaudio.com/trac/ticket/141
Todo:
need to handle PaNeverDropInput here where necessary

References PaWinMmeStream::abortEvent, PaWinMmeStream::abortProcessing, PaWinMmeStream::allBuffersDurationMs, PaWinMmeSingleDirectionHandlesAndBuffers::bufferCount, PaWinMmeSingleDirectionHandlesAndBuffers::bufferEvent, PaWinMmeStream::bufferProcessor, PaUtilBufferProcessor::bytesPerHostInputSample, PaUtilBufferProcessor::bytesPerHostOutputSample, PaWinMmeStream::cpuLoadMeasurer, PaWinMmeSingleDirectionHandlesAndBuffers::currentBufferIndex, PaStreamCallbackTimeInfo::currentTime, PaWinMmeSingleDirectionHandlesAndBuffers::deviceCount, FALSE, PaWinMmeSingleDirectionHandlesAndBuffers::framesPerBuffer, PaUtilBufferProcessor::framesPerHostBuffer, PaWinMmeSingleDirectionHandlesAndBuffers::framesUsedInCurrentBuffer, HANDLE(), PaWinMmeStream::highThreadPriority, PaWinMmeStream::input, PaWinMmeStream::isActive, PaWinMmeStream::output, PaStreamCallbackTimeInfo::outputBufferDacTime, PA_IS_FULL_DUPLEX_STREAM_, PA_IS_HALF_DUPLEX_STREAM_, PA_IS_INPUT_STREAM_, PA_IS_OUTPUT_STREAM_, paAbort, paContinue, paInputOverflow, paNoError, paOutputUnderflow, paUnanticipatedHostError, PaUtil_BeginBufferProcessing(), PaUtil_BeginCpuLoadMeasurement(), PaUtil_EndBufferProcessing(), PaUtil_EndCpuLoadMeasurement(), PaUtil_GetCpuLoad(), PaUtil_GetTime(), PaUtil_ResetCpuLoadMeasurer(), PaUtil_SetInputFrameCount(), PaUtil_SetInterleavedInputChannels(), PaUtil_SetInterleavedOutputChannels(), PaUtil_SetOutputFrameCount(), PaUtil_ZeroOutput(), PaWinMmeStream::processingThread, PaWinMmeStream::processingThreadPriority, PaUtilBufferProcessor::samplePeriod, PaWinMmeStream::stopProcessing, PaUtilStreamRepresentation::streamFinishedCallback, PaWinMmeStream::streamRepresentation, PaWinMmeStream::throttledSleepMsecs, PaWinMmeStream::throttledThreadPriority, PaWinMmeStream::throttleProcessingThreadOnOverload, PaUtilStreamRepresentation::userData, PaWinMmeSingleDirectionHandlesAndBuffers::waveHandles, and PaWinMmeSingleDirectionHandlesAndBuffers::waveHeaders.