⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiorouting.cpp

📁 AudioRouting.cpp : Defines the entry point for the DLL application. Audio Routing Service
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -