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

📄 audiomanager.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

    //Loop playing!
    bool    Done = false;

    while (MMResult == MMSYSERR_NOERROR && !Done)
    {
        //Play the wave
        MMResult = waveOutWrite(
                    WaveOutHandle, 
                    &WaveBufferHeader, 
                    sizeof(WaveBufferHeader)
                    );
        //Make sure it succeeded
        if (MMResult != MMSYSERR_NOERROR)
        {
            break;
        }

        //Wait for either : 
        //  the sound to finish  - signaled by waveOutWrite
        //  or a user calling StopTone - which signals m_StopToneEvent
        const HANDLE  c_WaitEvents[] = { SoundDoneEvent, m_StopToneEvent };
        
        DWORD   Result = WaitForMultipleObjects( 
                            ARRAYSIZE(c_WaitEvents),
                            c_WaitEvents,
                            FALSE,
                            INFINITE
                            );

        ASSERT(Result != WAIT_FAILED);
        if (Result == WAIT_FAILED)
        {
            MMResult = MMSYSERR_ERROR;
            break;
        }
        
        //Figure out which handle was signaled (which event)
        HANDLE  SignaledEvent = c_WaitEvents[ Result - WAIT_OBJECT_0 ];

        //If the sound finished playing - restart the loop
        if (SignaledEvent == SoundDoneEvent)
        {
            ResetEvent(SoundDoneEvent);
            continue;
        }

        //If StopProgressTone was called - signal the end of the loop
        else if (SignaledEvent == m_StopToneEvent)
        {
            Done = true;
            break;
        }
        //Otherwise we don't know what happened
        else
        {
            MMResult = MMSYSERR_ERROR; 
        }
    }


cleanup: 
    
    //Clean up the waveOut device and waveHeader
    waveOutReset(WaveOutHandle);
    
    //Cleans up the WaveBufferHeader struct
    waveOutUnprepareHeader(
        WaveOutHandle, 
        &WaveBufferHeader, 
        sizeof(WaveBufferHeader)
        );
    
    //Closes the WaveOutHandle handle
    waveOutClose(WaveOutHandle);
    
    if (WaveBufferHeader.lpData)
    {
        delete[] (BYTE*)(WaveBufferHeader.lpData);
        WaveBufferHeader.lpData = NULL;
    }

    if (pWaveFormat)
    {
        delete pWaveFormat;
    }

    //close the event handle
    CloseHandle(SoundDoneEvent); 

    m_ProgressToneThreadId = NULL;
    
    return (MMResult == MMSYSERR_NOERROR) ? S_OK : E_FAIL;
}

HRESULT
AudioManager_t::StopProgressTone(
    void
    )
{
    HRESULT hr = S_OK;

    //Restrict access to the player - this Lock is ref-counted
    EnterCriticalSection(&m_Lock); 
    
    if (m_ProgressToneThreadId == NULL)
    {
        //There is no tone playing
        hr = S_FALSE;
        goto leave; 
    }
    
    //Signal the playing thread to stop playing the tone
    SetEvent(m_StopToneEvent);

    //Wait for the thread to exit
    WaitForSingleObject(
        m_ProgressToneThreadId, 
        INFINITE
        );

    //Reset the event so it can be reused
    ResetEvent(m_StopToneEvent);
    m_ProgressToneThreadId = NULL;


leave:
    
    ASSERT(m_ProgressToneThreadId == NULL);
    
    LeaveCriticalSection(&m_Lock); 

    return hr;
}

HRESULT
AudioManager_t::PlaySound(
    BSTR    bstrFilePath, 
    DWORD   CallbackHandle
    )
{
    if (bstrFilePath == NULL || 
        bstrFilePath[0] == L'\0')
    {
        return E_INVALIDARG; 
    }
    
    MMRESULT        MMResult        = MMSYSERR_NOERROR;
    DWORD           BufferSize      = 0;
    BYTE*           pBufferBytes    = NULL;
    WAVEFORMATEX*   pWaveFormat     = NULL;
    DWORD           Wait            = 0;
    DWORD           Duration        = 0;
    HRESULT         hr              = S_OK;

    if (m_RingWaveOutHandle != NULL)
    {
        StopSound();
    }
    
    //Read Wave File figures out how long the wave is and prepares the
    //WaveFormat Structure for playing by waveOutWrite
    MMResult = ReadWaveFile(
                    bstrFilePath, 
                    &pWaveFormat, 
                    &BufferSize, 
                    &pBufferBytes
                    );
    if (MMResult != MMSYSERR_NOERROR)
    {
        goto leave;    
    }
    
    //The time that it takes to play the wave
    Duration = BufferSize * 1000 / pWaveFormat->nSamplesPerSec;

    //Open the wave file
    MMResult = waveOutOpen(
                    &m_RingWaveOutHandle,   //handle to the out wave
                    0,                      //unused
                    pWaveFormat,            //the waveformatex struct that contains the wav info
                    CallbackHandle,         //The event to signal when the sound is done
                    NULL,                   //No additional params
                    CALLBACK_EVENT          //flag indicating that hDoneSound is an event
                    );
    if (MMResult != MMSYSERR_NOERROR)
    {
        goto leave;    
    }

    
    //Prepare the header
    m_RingWaveDataBlockHeader.dwBufferLength = BufferSize;
    //Yes it should be a 'char' even though we are using unicode!
    m_RingWaveDataBlockHeader.lpData         = (char *)pBufferBytes;

    //Inform the wave handle about the header
    MMResult = waveOutPrepareHeader(
                    m_RingWaveOutHandle, 
                    &m_RingWaveDataBlockHeader, 
                    sizeof(m_RingWaveDataBlockHeader)
                    );
    if (MMResult != MMSYSERR_NOERROR)
    {
        goto leave;    
    }

    MMResult = waveOutWrite(
                    m_RingWaveOutHandle, 
                    &m_RingWaveDataBlockHeader, 
                    sizeof(m_RingWaveDataBlockHeader)
                    ); 
    if (MMResult == MMSYSERR_NOERROR)
    {
        hr = S_OK; 
    }

leave: 
    if (MMResult != MMSYSERR_NOERROR)
    {
        StopSound();
        hr = E_FAIL;
    }

    if (pWaveFormat)
    {
        delete pWaveFormat; 
    }

    return hr; 
}

HRESULT
AudioManager_t::StopSound(
    void
    )
{
    if (m_RingWaveOutHandle != NULL)
    {
        waveOutReset(m_RingWaveOutHandle);
        
        //Cleans up the hdr struct
        waveOutUnprepareHeader(
                m_RingWaveOutHandle, 
                &m_RingWaveDataBlockHeader, 
                sizeof(m_RingWaveDataBlockHeader)
                );

        //Closes the hwo handle
        waveOutClose(m_RingWaveOutHandle);

        //cleanup the allocated wave buffer
        if (m_RingWaveDataBlockHeader.lpData)
        {
            delete[] (BYTE*)(m_RingWaveDataBlockHeader.lpData);
            m_RingWaveDataBlockHeader.lpData = NULL;
        }
        
        //Null it out for my own sanity
        m_RingWaveOutHandle = NULL;
    }

    return S_OK;
}


HRESULT
AudioManager_t::Ring(
    const WCHAR*    RingTonePath
    )
{
    if (RingTonePath == NULL)
    {
        return E_INVALIDARG; 
    }
    
    if (IsRinging())
    {
        return E_FAIL; 
    }

    ResetEvent(m_StopRingEvent); 

    if (!m_RingTonePath.assign(RingTonePath))
    {
        ASSERT(FALSE); 
        return E_OUTOFMEMORY; 
    }
    
    m_RingThreadId = CreateThread(
                        NULL, 
                        0, 
                        s_RingerProc, 
                        reinterpret_cast<VOID*>(this), 
                        0, 
                        NULL
                        ); 
    if (m_RingThreadId == NULL)
    {
        return CommonUtilities_t::GetErrorFromWin32(); 
    }
    
    return S_OK; 
}

HRESULT
AudioManager_t::CancelRing(
    void
    )
{
    if (m_RingThreadId == NULL)
    {
        //There is no tone playing
        return S_FALSE;
    }
    
    //Signal the playing thread to stop playing the tone
    SetEvent(m_StopRingEvent);

    //Wait for the thread to exit
    WaitForSingleObject(
        m_RingThreadId, 
        INFINITE
        );

    //Reset the event so it can be reused
    ResetEvent(m_StopRingEvent);
    m_RingThreadId = NULL;

    return S_OK;
    
}


DWORD WINAPI
AudioManager_t::s_RingerProc(
    LPVOID  Parameter
    )
{
    AudioManager_t* pAudioManager = reinterpret_cast<AudioManager_t*>(Parameter); 
    if (pAudioManager == NULL)
    {
        return E_UNEXPECTED; 
    }

    return pAudioManager->RingerProc(); 
}

DWORD
AudioManager_t::RingerProc(
    void
    )
{
    HRESULT         hr              = S_OK;
    HANDLE          SoundDoneEvent  = NULL; 
    bool            Stopped         = false;
    DWORD           Wait            = 0;
    
    //Create an event for the sound begin done playing
    SoundDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!SoundDoneEvent)
    {
        goto exit;
    }

    /*
        wait for 2 possible events:
        1) The sound is done playing and needs to be relooped
        2) The stop ring event
    */
    
    HANDLE  Events[]        = {SoundDoneEvent, m_StopRingEvent};
    unsigned int EventCount = ARRAYSIZE(Events);
    
    //While it is not stopped
    while (!Stopped)
    {
        //The handles to wait for.
        StartRing(SoundDoneEvent);

        //Wait for: the sound being done playing
        //          kill the sound
        Wait = WaitForMultipleObjects(
                    EventCount,
                    Events,
                    FALSE,
                    INFINITE
                    );

        if (Wait == WAIT_FAILED)
        {
            ASSERT(FALSE);
            //Simulate an external answered event to kill the ringer
            //Note: The index of the StopRing event is 1
            Wait = 1;
        }
        else
        {
            Wait -= WAIT_OBJECT_0;
        }
        
        //Get the handle returned
        HANDLE ReturnedEvent = Events[Wait];

        //If the ring needs to be killed, then kill the ring and re-loop
        if (ReturnedEvent == SoundDoneEvent)
        {
            //Reset the SoundDone event so we can play the sound again
            ResetEvent(SoundDoneEvent);

            //Wait for a second for the answering or timeout event
            Wait = WaitForSingleObject(
                        m_StopRingEvent, 
                        1000
                        );
            
            if (Wait != WAIT_TIMEOUT)
            {
                ReturnedEvent = m_StopRingEvent; 
            }
        }

        //If we got the "call answered" event then break the loop
        if (ReturnedEvent == m_StopRingEvent)
        {
            Stopped = true;
        }
    }

    //Immediately terminate the sound
    StopRing();

exit:
    //Cleanup
    //
    
    //Cleanup the handles for the events that were created
    CloseHandle(SoundDoneEvent);

    //clean up the handle to this thread
    CloseHandle(m_RingThreadId);
    m_RingThreadId = NULL;
    
    return 0;
    
}


HRESULT 
AudioManager_t::StartRing(
    HANDLE CallbackEvent
    )
{
    //a tone is a call waiting tone IFF the ringtone path is empty
    bool    CallWaiting = (m_RingTonePath[0] == 0);
    ce::auto_bstr  bstrRingtone;

    
    if (CallWaiting)
    {
        PlayProgressTone(ProgressToneCallWaiting);
    }
    else
    {
        bstrRingtone = SysAllocString(m_RingTonePath);
        if (bstrRingtone != NULL)
        {
            PlaySound(bstrRingtone, reinterpret_cast<DWORD>(CallbackEvent));
        }
    }

    return S_OK;
}

HRESULT
AudioManager_t::StopRing(
    void
    )
{
    //the tone is a call waiting tone IFF the ringtone path is empty
    bool CallWaiting = (m_RingTonePath[0] == 0);
    
    if (CallWaiting)
    {
        StopProgressTone();
    }
    else
    {
        StopSound();
    }

    return S_OK;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -