From: dmitrykos Date: Wed, 17 Feb 2010 10:11:40 +0000 (+0000) Subject: improved PaWasapi_ThreadPriorityBoost by providing enum PaWasapiThreadPriority with... X-Git-Tag: pa_stable_v19_20110326_r1647~173 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=75e59cb874f04d7cbb062294f732661f01ac536f;p=portaudio improved PaWasapi_ThreadPriorityBoost by providing enum PaWasapiThreadPriority with explicit thread priority values for convenience. it is possible to override default thread priority setting for Event/Poll-driven modes by specifying new flag paWinWasapiThreadPriority and setting priority value through PaWasapiStreamInfo::threadPriority member. --- diff --git a/include/pa_win_wasapi.h b/include/pa_win_wasapi.h index 1d26a2e..9023ff1 100644 --- a/include/pa_win_wasapi.h +++ b/include/pa_win_wasapi.h @@ -68,12 +68,17 @@ typedef enum PaWasapiFlags Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling 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. */ + paWinWasapiThreadPriority = (1 << 4) } PaWasapiFlags; #define paWinWasapiExclusive (paWinWasapiExclusive) #define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor) #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask) #define paWinWasapiPolling (paWinWasapiPolling) +#define paWinWasapiThreadPriority (paWinWasapiThreadPriority) /* Host processor. Allows to skip internal PA processing completely. @@ -86,6 +91,39 @@ typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFra void *outputBuffer, long outputFrames, void *userData); +/* Device role */ +typedef enum PaWasapiDeviceRole +{ + eRoleRemoteNetworkDevice = 0, + eRoleSpeakers, + eRoleLineLevel, + eRoleHeadphones, + eRoleMicrophone, + eRoleHeadset, + eRoleHandset, + eRoleUnknownDigitalPassthrough, + eRoleSPDIF, + eRoleHDMI, + eRoleUnknownFormFactor +} +PaWasapiDeviceRole; + + +/* Thread priority */ +typedef enum PaWasapiThreadPriority +{ + eThreadPriorityNone = 0, + eThreadPriorityAudio, //!< Default for Shared mode. + eThreadPriorityCapture, + eThreadPriorityDistribution, + eThreadPriorityGames, + eThreadPriorityPlayback, + eThreadPriorityProAudio, //!< Default for Exclusive mode. + eThreadPriorityWindowManager +} +PaWasapiThreadPriority; + + /* Stream descriptor. */ typedef struct PaWasapiStreamInfo { @@ -98,16 +136,27 @@ typedef struct PaWasapiStreamInfo /* 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 + are specified in pa_win_waveformat.h. Will be used only if + paWinWasapiUseChannelMask flag is specified. */ PaWinWaveFormatChannelMask channelMask; /* 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. + be the same that was passed to Pa_OpenStream method. Will be used only if + paWinWasapiRedirectHostProcessor flag is specified. */ PaWasapiHostProcessorCallback hostProcessorOutput; PaWasapiHostProcessorCallback hostProcessorInput; + + /* 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) + you shall specify same value for threadPriority or othervise one of the values will be used + to setup thread priority. + */ + PaWasapiThreadPriority threadPriority; } PaWasapiStreamInfo; @@ -123,25 +172,7 @@ PaWasapiStreamInfo; or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an error is encountered. */ -int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice ); - - -/* Device role */ -typedef enum PaWasapiDeviceRole -{ - eRoleRemoteNetworkDevice = 0, - eRoleSpeakers, - eRoleLineLevel, - eRoleHeadphones, - eRoleMicrophone, - eRoleHeadset, - eRoleHandset, - eRoleUnknownDigitalPassthrough, - eRoleSPDIF, - eRoleHDMI, - eRoleUnknownFormFactor -} -PaWasapiDeviceRole; +int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice ); /** Returns device role (PaWasapiDeviceRole enum). @@ -160,18 +191,13 @@ int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice ); @param hTask a handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority method to revert thread priority to initial state. - @param nPriorityClass an Id of thread priority: 1 - Audio - 2 - Capture - 3 - Distribution - 4 - Games - 5 - Playback - 6 - Pro Audio - 7 - Window Manager + @param nPriorityClass an Id of thread priority of PaWasapiThreadPriority type. Specifying + eThreadPriorityNone does nothing. @return Error code indicating success or failure. @see PaWasapi_RevertThreadPriority */ -PaError PaWasapi_ThreadPriorityBoost( void **hTask, int nPriorityClass ); +PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass ); /** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread diff --git a/src/hostapi/wasapi/pa_win_wasapi.cpp b/src/hostapi/wasapi/pa_win_wasapi.cpp index 33ae296..86b0267 100644 --- a/src/hostapi/wasapi/pa_win_wasapi.cpp +++ b/src/hostapi/wasapi/pa_win_wasapi.cpp @@ -97,6 +97,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param); enum { S_INPUT = 0, S_OUTPUT, S_COUNT }; +#define STATIC_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) + #define PRINT(x) PA_DEBUG(x); #define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \ @@ -315,6 +317,9 @@ typedef struct PaWasapiStream // Av Task (MM thread management) HANDLE hAvTask; + + // Thread priority level + PaWasapiThreadPriority nThreadPriority; } PaWasapiStream; @@ -893,7 +898,7 @@ static inline PaWasapiHostApiRepresentation *GetHostApi(PaError *_error = NULL) } // ------------------------------------------------------------------------------------------ -int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice ) +int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice ) { if (pFormat == NULL) return paBadBufferPtr; @@ -907,10 +912,10 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceInd if (paWasapi == NULL) return ret; - if (nDevice >= (int)paWasapi->deviceCount) + if ((UINT32)nDevice >= paWasapi->deviceCount) return paInvalidDevice; - int size = min(nFormatSize, sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat)); + UINT32 size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat)); memcpy(pFormat, &paWasapi->devInfo[ nDevice ].DefaultFormat, size); return size; @@ -1560,6 +1565,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, goto error; } + // Default thread priority is Audio: for exclusive mode we will use Pro Audio. + stream->nThreadPriority = eThreadPriorityAudio; + // Try create device: Input if (inputParameters != NULL) { @@ -1572,7 +1580,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, // Select Exclusive/Shared mode stream->in.shareMode = AUDCLNT_SHAREMODE_SHARED; if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiExclusive)) + { + // Boost thread priority + stream->nThreadPriority = eThreadPriorityProAudio; + // Make Exclusive stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE; + } + + // If user provided explicit thread priority level, use it + if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiThreadPriority)) + { + if ((inputStreamInfo->threadPriority > eThreadPriorityNone) && + (inputStreamInfo->threadPriority <= eThreadPriorityWindowManager)) + stream->nThreadPriority = inputStreamInfo->threadPriority; + } // Choose processing mode stream->in.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK; @@ -1661,7 +1682,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, // Select Exclusive/Shared mode stream->out.shareMode = AUDCLNT_SHAREMODE_SHARED; if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiExclusive)) + { + // Boost thread priority + stream->nThreadPriority = eThreadPriorityProAudio; + // Make Exclusive stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE; + } + + // If user provided explicit thread priority level, use it + if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiThreadPriority)) + { + if ((outputStreamInfo->threadPriority > eThreadPriorityNone) && + (outputStreamInfo->threadPriority <= eThreadPriorityWindowManager)) + stream->nThreadPriority = outputStreamInfo->threadPriority; + } // Choose processing mode stream->out.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK; @@ -2440,13 +2474,14 @@ void MMCSS_deactivate(HANDLE hTask) } // ------------------------------------------------------------------------------------------ -PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass) +PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass) { if (hTask == NULL) return paUnanticipatedHostError; - static const char *mmcs_name[7] = + static const char *mmcs_name[] = { + NULL, "Audio", "Capture", "Distribution", @@ -2455,7 +2490,7 @@ PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass) "Pro Audio", "Window Manager" }; - if ((UINT32)nPriorityClass >= 7) + if ((UINT32)nPriorityClass >= STATIC_ARRAY_SIZE(mmcs_name)) return paUnanticipatedHostError; HANDLE task = MMCSS_activate(mmcs_name[nPriorityClass]); @@ -2546,7 +2581,7 @@ void _OnStreamStop(PaWasapiStream *stream) // Restore thread priority if (stream->hAvTask != NULL) { - MMCSS_deactivate(stream->hAvTask); + PaWasapi_ThreadPriorityRevert(stream->hAvTask); stream->hAvTask = NULL; } @@ -2584,7 +2619,8 @@ PA_THREAD_FUNC ProcThreadEvent(void *param) } // Boost thread priority - stream->hAvTask = MMCSS_activate("Pro Audio"); + stream->hAvTask = NULL; + PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority); // Initialize event & start INPUT stream if (stream->in.client) @@ -2693,7 +2729,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) processor[S_OUTPUT] = (stream->hostProcessOverrideOutput.processor != NULL ? stream->hostProcessOverrideOutput : defaultProcessor); // Boost thread priority - stream->hAvTask = MMCSS_activate("Pro Audio"); + stream->hAvTask = NULL; + PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority); // Initialize event & start INPUT stream if (stream->in.client)