📄 wavemdd.cxx
字号:
//
// 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"
// WAPI_IN=0; WAPI_OUT=1
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 = FALSE;
BOOL g_bDriverInitialized = FALSE; // whether it has been inited or not
BOOL g_fInitSco = FALSE;
#ifdef DEBUG
DBGPARAM dpCurSettings =
{
TEXT("BTAUDIODRV"),
{
TEXT("Test"),
TEXT("Params"),
TEXT("Verbose"),
TEXT("Interrupt"),
TEXT("WODM"),
TEXT("WIDM"),
TEXT("PDD"),
TEXT("MDD"),
TEXT("Regs"),
TEXT("Misc"),
TEXT("Init"),
TEXT("IOcontrol"),
TEXT("Alloc"),
TEXT("Function"),
TEXT("Warning"),
TEXT("Error")
},
0x0000C000
};
#endif
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL WINAPI
DllEntry (
HANDLE hinstDLL,
DWORD Op,
LPVOID lpvReserved
)
{
switch (Op)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hinstDLL);
DisableThreadLibraryCalls((HMODULE) hinstDLL);
BSS_VERBOSE2(TEXT("DLL_PROCESS_ATTACH: ProcessId=%#x hinstDLL=%#x"), GetCurrentProcessId(), hinstDLL);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_DETACH:
case DLL_THREAD_ATTACH:
default:
break;
}
return TRUE;
}
// -----------------------------------------------------------------------------
// RemoveCompleteBlocks
// -----------------------------------------------------------------------------
VOID
RemoveCompleteBlocks(
WAPI_INOUT apidir
)
{
PREFAST_ASSERT(apidir < 2);
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.
//
//DEBUGMSG(1, (_T("=== BT Audio Driver: Sending callback into mixer: Tick:%u\n"), GetTickCount()));
BSS_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
//
if (pfnCallback) {
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
)
{
BSS_FUNC_WMDD("+InitGSI");
gsi[apidir].pwh = NULL;
gsi[apidir].pwhReal = NULL;
gsi[apidir].bInLoop = FALSE;
gsi[apidir].bStarted = FALSE;
gsi[apidir].bPaused = FALSE;
gsi[apidir].bInMiddle = FALSE;
gsi[apidir].pfnCallback = NULL;
gsi[apidir].dwInstance = 0;
gsi[apidir].dwOpenFlags = 0;
gsi[apidir].pwfx = NULL;
gsi[apidir].hWave = INVALID_HANDLE_VALUE;
BSS_FUNC_WMDD("-InitGSI");
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
WMDD_PowerHandler(
BOOL power_down
)
{
PDD_AudioPowerHandler(power_down);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL
WMDD_Deinit(
DWORD dwData
)
{
BSS_FUNCTION1 ("WAV_Deinit(0x%X)\r\n", dwData);
PDD_AudioDeinitialize();
DeleteCriticalSection(&(v_GSICritSect[WAPI_IN]));
DeleteCriticalSection(&(v_GSICritSect[WAPI_OUT]));
g_bDriverInitialized = FALSE;
return TRUE;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
WMDD_Init(
DWORD Index
)
{
if(g_bDriverInitialized)
return 10L; // already inited,
BSS_FUNC_WMDD("+WMDD_Init");
BSS_HEXPARAM(Index);
InitializeCriticalSection(&(v_GSICritSect[WAPI_IN]));
InitializeCriticalSection(&(v_GSICritSect[WAPI_OUT]));
// init the hardware first
if (PDD_AudioInitialize(Index) != TRUE) {
BSS_ERRMSG("PDD_AudioInitialize() FAILED");
goto InitFail;
}
BSS_FUNC_WMDD("-WMDD_Init (SUCCESS)");
g_bDriverInitialized = TRUE; // set it
g_bDriverOpened = FALSE;
// Return Non-Zero for success, will be passed to Deinit and Open
return 1;
InitFail:
BSS_FUNC_WMDD("-WMDD_Init (FAILURE)");
WMDD_Deinit(0);
return 0L;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -