?? audiorouting.cpp
字號:
// AudioRouting.cpp : Defines the entry point for the DLL application.
// Audio Routing Service
//
#define DEBUG_TRACE 1
#include "stdafx.h"
typedef struct
{
CRITICAL_SECTION cs;
ULONG ServiceStatus;
CAudioRouting *AudioRouting;
HANDLE hThread;
HANDLE hThreadStopEvent;
HANDLE hSpkOnEvent;
HANDLE hSpkOffEvent;
HANDLE hPatchVoiceOnEvent;
HANDLE hPatchVoiceOffEvent;
HREGNOTIFY hRegEvSpeaker;
HREGNOTIFY hRegEvVoice;
HMODULE hDllCoredll;
_KernelIoControl pfnKernelIoControl;
} ARSCONTEXT;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
static BOOL CloseEvents( ARSCONTEXT *pC )
{
BOOL bRet = TRUE;
if ( pC->hSpkOnEvent ) CloseHandle( pC->hSpkOnEvent );
if ( pC->hSpkOffEvent ) CloseHandle( pC->hSpkOffEvent );
if ( pC->hPatchVoiceOnEvent ) CloseHandle( pC->hPatchVoiceOnEvent );
if ( pC->hPatchVoiceOffEvent ) CloseHandle( pC->hPatchVoiceOffEvent );
if ( pC->hThreadStopEvent ) CloseHandle( pC->hThreadStopEvent );
pC->hSpkOnEvent = NULL;
pC->hSpkOffEvent = NULL;
pC->hPatchVoiceOnEvent = NULL;
pC->hPatchVoiceOffEvent = NULL;
pC->hThreadStopEvent = NULL;
return bRet;
}
static BOOL OpenEvents( ARSCONTEXT *pC )
{
BOOL bRet = TRUE;
pC->hSpkOnEvent = CreateEvent(NULL, FALSE, FALSE, EVENTNAME_AUDIO_SPKON);
pC->hSpkOffEvent = CreateEvent(NULL, FALSE, FALSE, EVENTNAME_AUDIO_SPKOFF);
pC->hPatchVoiceOnEvent = CreateEvent(NULL, FALSE, FALSE, EVENTNAME_AUDIO_ROUTINGON);
pC->hPatchVoiceOffEvent = CreateEvent(NULL, FALSE, FALSE, EVENTNAME_AUDIO_ROUTINGOFF);
pC->hThreadStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if ( !pC->hThreadStopEvent || !pC->hSpkOnEvent || !pC->hSpkOffEvent
|| !pC->hPatchVoiceOnEvent || !pC->hPatchVoiceOffEvent || !pC->hThreadStopEvent )
{
CloseEvents( pC );
bRet = FALSE;
}
return bRet;
}
static ULONG AudioRoutingThread( ARSCONTEXT *pC )
{
BOOL bNotDone = TRUE;
HANDLE h[5];
h[0] = pC->hSpkOnEvent;
h[1] = pC->hSpkOffEvent;
h[2] = pC->hPatchVoiceOnEvent;
h[3] = pC->hPatchVoiceOffEvent;
h[4] = pC->hThreadStopEvent;
while ( bNotDone )
{
bool bSpk, bRecord;
DebugMsg(L"AudioRoutingThread Waiting\r\n");
ULONG WaitRet = WaitForMultipleObjects( sizeof( h )/sizeof( h[0]), h, FALSE, INFINITE );
EnterCriticalSection( &pC->cs );
if ( !pC->hThreadStopEvent )
{
bNotDone = false;
LeaveCriticalSection( &pC->cs );
continue;
}
switch ( WaitRet )
{
case WAIT_OBJECT_0+0:
// Speaker on
// If in VOIP call then do this
DebugMsg(L"AudioRoutingThread 0\r\n");
pC->AudioRouting->SetSpeakerState( true );
break;
case WAIT_OBJECT_0+1:
DebugMsg(L"AudioRoutingThread 1\r\n");
// Speaker Off
// If in VOIP call then do this
pC->AudioRouting->SetSpeakerState( false );
break;
case WAIT_OBJECT_0+2:
DebugMsg(L"AudioRoutingThread 2\r\n");
// Route phone to wav in if Cellular call
pC->AudioRouting->SetRecordState( true );
break;
case WAIT_OBJECT_0+3:
DebugMsg(L"AudioRoutingThread 3\r\n");
// Route phone to wav in off if cellular call
pC->AudioRouting->SetRecordState( false );
break;
case WAIT_OBJECT_0+4:
DebugMsg(L"AudioRoutingThread 4\r\n");
// Hmm this should not get triggered!
// fall thru
default:
DebugMsg(L"Thread done\r\n");
bNotDone = FALSE;
break;
}
if ( bNotDone )
{
pC->AudioRouting->GetSpeakerState( bSpk );
pC->AudioRouting->GetRecordState( bRecord );
DebugMsg(L"Spk:%d Record:%d\r\n", bSpk, bRecord);
}
LeaveCriticalSection( &pC->cs );
}
return 0;
}
void RegCallbackSpeaker(HREGNOTIFY hNotify, DWORD dwUserData, const PBYTE pData, const UINT cbData)
{
ARSCONTEXT *pC = (ARSCONTEXT *)dwUserData;
if (*pData)
{
SetEvent( pC->hSpkOnEvent );
}
else
{
SetEvent( pC->hSpkOffEvent );
}
}
static BOOL StopService( ARSCONTEXT *pC )
{
BOOL bRet=TRUE;
FUNCTRACEIN();
EnterCriticalSection( &pC->cs );
if ( pC->hRegEvSpeaker )
{
RegistryCloseNotification( pC->hRegEvSpeaker );
pC->hRegEvSpeaker = NULL;
}
CloseEvents( pC );
LeaveCriticalSection( &pC->cs );
FUNCTRACEOUT();
return bRet;
}
static BOOL StartService( ARSCONTEXT *pC )
{
BOOL bRet=FALSE;
FUNCTRACEIN();
bRet = OpenEvents( pC );
if (!bRet)
{
DebugMsg(L"OpenEvents Failed\r\n");
goto ErrorExit;
}
EnterCriticalSection( &pC->cs );
// Setup notification broker
HRESULT hr = RegistryNotifyCallback(SN_SPEAKERPHONEACTIVE_ROOT,
SN_SPEAKERPHONEACTIVE_PATH,
SN_SPEAKERPHONEACTIVE_VALUE,
RegCallbackSpeaker,
(ULONG)pC,
NULL,
&pC->hRegEvSpeaker );
if ( FAILED(hr) )
{
DebugMsg(L"RegCallbackSpeaker callback failed\r\n");
bRet = FALSE;
goto ErrorExit;
}
ULONG SpkOnVal;
hr = RegistryGetDWORD( SN_SPEAKERPHONEACTIVE_ROOT, SN_SPEAKERPHONEACTIVE_PATH, SN_SPEAKERPHONEACTIVE_VALUE, &SpkOnVal );
if ( FAILED(hr) )
{
DebugMsg(L"RegistryGetDWORD spk failed\r\n");
bRet = FALSE;
goto ErrorExit;
}
if ( SpkOnVal )
{
SetEvent( pC->hSpkOnEvent );
}
else
{
SetEvent( pC->hSpkOffEvent );
}
LeaveCriticalSection( &pC->cs );
ULONG ThreadId;
pC->hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)AudioRoutingThread, (void*)pC, 0, &ThreadId );
ErrorExit:
if ( !bRet )
{
StopService( pC );
}
FUNCTRACEOUT();
return bRet;
}
//_____________________________________________________________________________
// The Stream interface follows below
extern "C" __declspec(dllexport) BOOL ARS_Deinit(
ULONG Data
)
{
ARSCONTEXT *pC = (ARSCONTEXT*)Data;
FUNCTRACEIN();
if (pC)
{
if ( pC->AudioRouting )
{
pC->AudioRouting->Deinit();
delete pC->AudioRouting;
pC->AudioRouting = NULL;
}
FreeLibrary( pC->hDllCoredll );
pC->hDllCoredll = NULL;
pC->pfnKernelIoControl = NULL;
if ( pC->hThreadStopEvent )
{
EnterCriticalSection( &pC->cs );
// Closing this will exit the monitor thread too
CloseHandle( pC->hThreadStopEvent );
pC->hThreadStopEvent = NULL;
LeaveCriticalSection( &pC->cs );
// wait a while for the thread ot exit
if ( pC->hThread )
{
WaitForSingleObject( pC->hThread, 10000);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -