📄 wavemdd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
//
// Module Name:
//
// wavemdd.c
//
// Abstract:
//
// Functions:
//
// Notes:
//
// -----------------------------------------------------------------------------
#include <wavemdd.h>
BOOL fPowerUp;
// Global
ULONG WMDD_InterruptThread(VOID);
HANDLE hAudioInterrupt; // Handle to Audio Interrupt event.
HANDLE hAudioInterruptThread; // Handle to thread which waits on an audio
// interrupt event.
CRITICAL_SECTION v_GSICritSect[2]; // One for input, one for output
STREAM_INFO gsi[2]; // Global Stream Info : one for input and one for output
BOOL g_bDriverOpened;
BOOL g_bDriverInitialized; // whether it has been inited or not
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL WINAPI
DllEntry (
HANDLE hinstDLL,
DWORD Op,
LPVOID lpvReserved
)
{
switch (Op) {
case DLL_PROCESS_ATTACH :
DEBUGREGISTER((HINSTANCE)hinstDLL);
DisableThreadLibraryCalls((HMODULE) hinstDLL);
break;
case DLL_PROCESS_DETACH :
break;
case DLL_THREAD_DETACH :
break;
case DLL_THREAD_ATTACH :
break;
default :
break;
}
return TRUE;
}
// -----------------------------------------------------------------------------
// Function to read the interrupt thread priority from the registry.
// If it is not in the registry then a default value is returned.
// -----------------------------------------------------------------------------
static DWORD
GetInterruptThreadPriority(
LPWSTR lpszActiveKey
)
{
HKEY hDevKey;
DWORD dwValType;
DWORD dwValLen;
DWORD dwPrio;
dwPrio = DEFAULT_THREAD_PRIORITY;
hDevKey = OpenDeviceKey(lpszActiveKey);
if (hDevKey) {
dwValLen = sizeof(DWORD);
RegQueryValueEx(
hDevKey,
REGISTRY_PRIORITY_VALUE,
NULL,
&dwValType,
(PUCHAR)&dwPrio,
&dwValLen);
RegCloseKey(hDevKey);
}
return dwPrio;
}
// -----------------------------------------------------------------------------
// RemoveCompleteBlocks
// -----------------------------------------------------------------------------
VOID
RemoveCompleteBlocks(
WAPI_INOUT apidir
)
{
UINT uMsg = ((apidir == WAPI_OUT) ? MM_WOM_DONE : MM_WIM_DATA);
DRVCALLBACK* pfnCallback = gsi[apidir].pfnCallback;
HANDLE hWave = gsi[apidir].hWave;
PWAVEHDR pwh = gsi[apidir].pwh;
while (gsi[apidir].pwh != NULL) {
if (IS_BUFFER_DONE(gsi[apidir].pwh)) {
pwh = gsi[apidir].pwh;
if (IS_BUFFER_INLOOP(pwh)) {
//
// This buffer is in a loop.
//
if (IS_BUFFER_BEGINLOOP(pwh)) {
if (pwh->dwLoops == 1) {
PWAVEHDR pwh_temp = pwh;
while (pwh_temp != NULL) {
MARK_BUFFER_NOT_INLOOP(pwh_temp);
pwh_temp = pwh_temp->lpNext;
}
} else {
if (pwh->dwLoops != INFINITE)
pwh->dwLoops--;
}
}
}
if (!IS_BUFFER_INLOOP(pwh)) {
//
// Only remove a block if it's not in a loop.
//
INTMSG("Block Complete... Sending callback");
gsi[apidir].dwBytePosition += gsi[apidir].pwh->dwBytesRecorded;
gsi[apidir].pwh = gsi[apidir].pwh->lpNext;
gsi[apidir].pwhReal = gsi[apidir].pwh;
MARK_BUFFER_DEQUEUED(pwh);
//
// Make the callback function call to the Wave API Manager
//
pfnCallback(hWave, uMsg, gsi[apidir].dwInstance, (DWORD) pwh, 0);
} else {
//
// If this buffer is in a loop, then just advance to the next block.
//
if (IS_BUFFER_ENDLOOP(pwh) || pwh->lpNext == NULL) {
gsi[apidir].pwh = gsi[apidir].pwhReal; // go the beginning.
} else {
gsi[apidir].dwBytePosition += gsi[apidir].pwh->dwBytesRecorded;
gsi[apidir].pwh = gsi[apidir].pwh->lpNext;
}
//
// Since we're not actually removing anything, we don't want to loop.
//
MARK_BUFFER_NOT_DONE(pwh);
MARK_BUFFER_EMPTY(pwh);
break;
}
} else {
//
// Only remove from the front of the list, but as many as are done.
//
break; // If the first one's not DONE, then break the loop.
}
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
GetBytePosition(
WAPI_INOUT apidir
)
{
DWORD dwBytePositionTotal;
LOCK_GSI(apidir);
if (gsi[apidir].pwh != NULL)
dwBytePositionTotal = gsi[apidir].dwBytePosition +
gsi[apidir].pwh->dwBytesRecorded;
else
dwBytePositionTotal = gsi[apidir].dwBytePosition;
UNLOCK_GSI(apidir);
return(dwBytePositionTotal);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
MarkAllAsDone(
WAPI_INOUT apidir
)
{
PWAVEHDR pwh_temp = gsi[apidir].pwh;
while (pwh_temp != NULL) {
MARK_BUFFER_DONE(pwh_temp);
pwh_temp = pwh_temp->lpNext;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
MarkAllAsNotInLoop(
WAPI_INOUT apidir
)
{
PWAVEHDR pwh_temp = gsi[apidir].pwh;
while (pwh_temp != NULL) {
MARK_BUFFER_NOT_INLOOP(pwh_temp);
pwh_temp = pwh_temp->lpNext;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
MarkAllAsFull(
WAPI_INOUT apidir
)
{
PWAVEHDR pwh_temp = gsi[apidir].pwh;
while (pwh_temp != NULL) {
MARK_BUFFER_FULL(pwh_temp);
pwh_temp = pwh_temp->lpNext;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
MarkFullAsDone(
WAPI_INOUT apidir
)
{
PWAVEHDR pwh_temp = gsi[apidir].pwh;
while (pwh_temp != NULL) {
if (IS_BUFFER_FULL(pwh_temp)) {
MARK_BUFFER_DONE(pwh_temp);
}
pwh_temp = pwh_temp->lpNext;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
InitGSI(
WAPI_INOUT apidir
)
{
FUNC_WMDD("+InitGSI");
gsi[apidir].pwh = NULL;
gsi[apidir].pwhReal = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -