hxaudevds.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:21k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxaudevds.cpp,v 1.13.2.3 2004/07/09 02:01:47 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #if defined( _WINDOWS ) || defined( _WIN32 )
- #include <windows.h>
- #include <tchar.h>
- #include <mmsystem.h>
- #include "mmreg.h"
- #endif /*defined( _WINDOWS ) || defined( _WIN32 )*/
- #include <stdio.h>
- #include <string.h>
- #include "hxresult.h"
- #include "cbqueue.h"
- #include "cpqueue.h"
- #include "hxslist.h"
- #include "hxcom.h"
- #include "hxengin.h"
- #include "ihxpckts.h"
- #include "hxausvc.h"
- #include "auderrs.h"
- #include "math.h"
- #include "hxaudev.h"
- #include "tsconvrt.h"
- #include "hxaudevds.h"
- extern HINSTANCE g_hInstance;
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #include "hlxosstr.h"
- #ifndef TEXT
- #define TEXT(w) OS_STRING(w)
- #endif
- #ifndef _WINDOWS
- #define TCHAR char
- #endif
- typedef HRESULT (WINAPI* FPDIRECTSOUNDCREATE)(LPGUID lpGuid, LPDIRECTSOUND * ppDS, IUnknown FAR * pUnkOuter);
- static LRESULT CALLBACK HXDSWndProc(HWND, UINT, WPARAM, LPARAM);
- UINT CHXAudioDeviceDS::zm_uDestroyMessage = 0;
- const UINT32 kExitThreadWaitTime = 3000; // ms
- #define HXMSG_TIMESYNC WM_USER+501
- const TCHAR* szTitle = TEXT("Helix DSWnd");
- const TCHAR* szWindowClass = TEXT("Helix DSWndClass");
- const TCHAR* kDSWaitEvent = TEXT("HelixDirectSoundNotifyWait");
- const TCHAR* kDSDestroyMessage = TEXT("HX_DestroyDSWindowInternal");
- const int BUFFER_TIME = 8;
- extern BOOL RMEnableLogging();
- extern void RMDSLog(const char* pFormatString, ...);
- #define RMDS_LOG RMDSLog
- CHXAudioDeviceDS::CHXAudioDeviceDS():
- m_ulLastPlayCursor(0)
- , m_ulLastWriteCursor(0)
- , m_ulCurrPlayTime(0)
- , m_ulCurrLoopTime(0)
- , m_pDSDev(NULL)
- , m_pPrimaryBuffer(NULL)
- , m_pSecondaryBuffer(NULL)
- , m_hwnd(NULL)
- , m_pAudioPtrStart(NULL)
- , m_hSoundDll(NULL)
- , m_ulLoops(0)
- , m_ulLoopTime(0)
- , m_hDSNotifyEvent(NULL)
- , m_hWaitThread(NULL)
- , m_nBlocksPerBuffer(0)
- , m_bExitThread(FALSE)
- , m_ulOriginalThreadId(0)
- {
- // Create a unique message for destroying the audio window
- if (!zm_uDestroyMessage)
- {
- zm_uDestroyMessage = RegisterWindowMessage(kDSDestroyMessage);
- }
- #ifdef _WINCE
- WNDCLASS wcex;
- #else
- WNDCLASSEX wcex;
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.hIconSm = NULL;
- #endif
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = (WNDPROC)HXDSWndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = g_hInstance;
- wcex.hIcon = NULL;
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wcex.lpszMenuName = NULL;
- wcex.lpszClassName = szWindowClass;
- #ifdef _WINCE
- RegisterClass(&wcex);
- #else
- RegisterClassEx(&wcex);
- #endif
- #ifdef _WINCE
- m_hwnd = ::CreateWindow(szWindowClass, szTitle,
- WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_SYSMENU,
- -5000, -5000, 1, 1, NULL, NULL, g_hInstance, NULL );
- #else
- m_hwnd = ::CreateWindow(szWindowClass, szTitle,
- WS_OVERLAPPEDWINDOW,
- -5000, -5000, 1, 1, NULL, NULL, g_hInstance, NULL );
- #endif
- m_ulOriginalThreadId = GetCurrentThreadId();
-
- m_hSoundDll = ::LoadLibrary( TEXT("dsound.dll") );
- }
- CHXAudioDeviceDS::~CHXAudioDeviceDS()
- {
- if (m_hSoundDll)
- {
- FreeLibrary(m_hSoundDll);
- m_hSoundDll = NULL;
- }
- if (m_hwnd)
- {
- #if defined(_WIN32)
- if (m_ulOriginalThreadId == GetCurrentThreadId())
- {
- SendMessage(m_hwnd, zm_uDestroyMessage, 0, 0);
- }
- else
- {
- PostMessage(m_hwnd, zm_uDestroyMessage, 0, 0);
- Sleep(0);
- }
- #else
- SendMessage(m_hwnd, zm_uDestroyMessage, 0, 0);
- #endif
- m_hwnd = NULL;
- }
- }
- /*
- * Set the format of the primary buffer, if possible. On WDM drivers, this has
- * no effect -- the kernel mixer determines that format.
- */
- HX_RESULT CHXAudioDeviceDS::SetPrimaryBufferFormat()
- {
- HX_RESULT res = HXR_OK ;
- DSBUFFERDESC bufferDesc;
- ::memset(&bufferDesc, 0, sizeof(DSBUFFERDESC));
- bufferDesc.dwSize = sizeof(DSBUFFERDESC);
- bufferDesc.lpwfxFormat = 0 ;
- bufferDesc.dwBufferBytes = 0 ;
- bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER ;
- /* close the primary buffer if we had one open before. */
- HX_RELEASE(m_pPrimaryBuffer) ;
- /* try to open with WAVE_FORMAT_EXTENSIBLE */
- res = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pPrimaryBuffer, NULL);
- if (res == DS_OK)
- {
- res = !DS_OK ;
- if (m_WaveFormat.Format.nChannels > 2)
- {
- res = m_pPrimaryBuffer->SetFormat(&m_WaveFormat.Format) ;
- }
- if (res != DS_OK)
- {
- /* if that fails, try to open with WAVE_FORMAT_PCM */
- m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_PCM ;
- res = m_pPrimaryBuffer->SetFormat(&m_WaveFormat.Format) ;
- }
- }
- return res ;
- }
- /*
- * IHXAudioDevice override methods
- */
- HX_RESULT CHXAudioDeviceDS::_Imp_Open(const HXAudioFormat* pFormat)
- {
- HX_RESULT theErr = HXR_FAIL;
- if(!m_hwnd || !m_hSoundDll)
- return theErr;
- // close open resources
- _Imp_Close() ;
- /* Get the IDirectSound interface */
- FPDIRECTSOUNDCREATE fpCreateDS = (FPDIRECTSOUNDCREATE) ::GetProcAddress(m_hSoundDll, TEXT("DirectSoundCreate") );
- if(!fpCreateDS)
- return theErr;
- theErr = fpCreateDS(NULL, &m_pDSDev, NULL);
- if (FAILED(theErr))
- return theErr;
- /* set the cooperative level. Because we want control over the format of the
- primary buffer (16 bit, multichannel!), we need DSSCL_PRIORITY. */
- m_pDSDev->SetCooperativeLevel(m_hwnd, DSSCL_PRIORITY );
- /* fill out the wave format structure */
- ::memset(&m_WaveFormat, 0, sizeof(m_WaveFormat));
- m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- m_WaveFormat.Format.nChannels = pFormat->uChannels;
- m_WaveFormat.Format.nSamplesPerSec = pFormat->ulSamplesPerSec;
- m_WaveFormat.Format.wBitsPerSample = pFormat->uBitsPerSample;
- m_WaveFormat.Format.nBlockAlign = pFormat->uBitsPerSample/8 * pFormat->uChannels;
- m_WaveFormat.Format.nAvgBytesPerSec = m_WaveFormat.Format.nBlockAlign * pFormat->ulSamplesPerSec ;
- m_WaveFormat.Format.cbSize = 22;
- m_WaveFormat.Samples.wValidBitsPerSample = pFormat->uBitsPerSample;
- m_WaveFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM ;
- m_WaveFormat.dwChannelMask = defaultChannelMapping(pFormat->uChannels) ;
- /* set the format of the primary buffer. This will fail on WDM systems (because
- the kernel mixer termines the primary buffer format), but is important on
- non-WDM systems.
-
- This might change the m_WaveFormat structure from a WAVE_FORMAT_EXTENSIBLE
- to a WAVEFORMATEX.
- Ignore the result.
- */
- SetPrimaryBufferFormat() ;
- /* Now open a secondary buffer. */
- DSBUFFERDESC bufferDesc;
- ::memset(&bufferDesc, 0, sizeof(DSBUFFERDESC));
- bufferDesc.dwSize = sizeof(DSBUFFERDESC);
- bufferDesc.lpwfxFormat = &m_WaveFormat.Format;
- // Manipulate the buffer size so that is is an exact multiple of the block size.
- // This will ensure that our write positions on the buffer are the same in every loop.
- // We need to do this so that we have fixed playback notification positions marking the end each write block.
- m_nBlocksPerBuffer = (m_WaveFormat.Format.nAvgBytesPerSec*BUFFER_TIME)/pFormat->uMaxBlockSize;
- m_ulTotalBuffer = pFormat->uMaxBlockSize*m_nBlocksPerBuffer;
- m_ulLoopTime = (double)m_ulTotalBuffer / (double)m_WaveFormat.Format.nAvgBytesPerSec;
- bufferDesc.dwBufferBytes = m_ulTotalBuffer ;
- bufferDesc.dwFlags =
- DSBCAPS_CTRLVOLUME | // so we can control the volume
- DSBCAPS_GETCURRENTPOSITION2 | // finer position reports
- DSBCAPS_CTRLPOSITIONNOTIFY | // have them reported here
- DSBCAPS_GLOBALFOCUS | // take control!
- DSBCAPS_STICKYFOCUS ;
- /* Again, try with WAVE_FORMAT_EXTENSIBLE first, but only if multichannel. */
- theErr = !DS_OK ;
- if (m_WaveFormat.Format.nChannels > 2)
- {
- m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL);
- }
- if (theErr != DS_OK)
- {
- /* and if that fails, try WAVEFORMATEX */
- m_WaveFormat.Format.wFormatTag = WAVE_FORMAT_PCM;
- theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL);
- }
- /* call it a day and count our blessings. */
- switch (theErr)
- {
- case DS_OK:
- theErr = HXR_OK;
- break;
- case DSERR_OUTOFMEMORY:
- theErr = HXR_OUTOFMEMORY;
- break;
- default:
- theErr = HXR_FAIL;
- break;
- }
- if (SUCCEEDED(theErr) && m_pSecondaryBuffer)
- {
- m_eState = E_DEV_OPENED;
- KillThreadAndEvent();
- SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);
- // Create the event to be signalled on playback position notifications and the thread to wait for those events to be signalled.
- m_hDSNotifyEvent = CreateEvent(NULL, TRUE, FALSE, kDSWaitEvent);
- // now set the notification positions for direct sound playback.
- IDirectSoundNotify* pNotify = NULL;
- m_pSecondaryBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&pNotify);
- if(pNotify && m_hDSNotifyEvent)
- {
- DSBPOSITIONNOTIFY* aPositionNotify = new DSBPOSITIONNOTIFY[m_nBlocksPerBuffer];
- if(aPositionNotify)
- {
- for(int i = 0; i < m_nBlocksPerBuffer; i++)
- {
- aPositionNotify[i].dwOffset = i * pFormat->uMaxBlockSize;
- aPositionNotify[i].hEventNotify = m_hDSNotifyEvent;
- }
- }
- pNotify->SetNotificationPositions(m_nBlocksPerBuffer, aPositionNotify);
- delete[] aPositionNotify;
- DWORD dwWaitThreadID(0);
- m_hWaitThread = CreateThread(NULL, 0, EventThreadProc, (LPVOID)this, 0, &dwWaitThreadID);
- }
- HX_RELEASE(pNotify);
- m_pSecondaryBuffer->SetVolume(DSBVOLUME_MAX);
- m_pSecondaryBuffer->SetCurrentPosition(0);
- }
- m_ulCurrPlayTime = 0;
- m_ulCurrLoopTime = 0;
- m_ulLoops = 0;
- // Setup converter to convert from samples/sec to milliseconds
- m_TSConverter.SetBase(m_WaveFormat.Format.nSamplesPerSec, 1000);
- return theErr;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Close()
- {
- HX_RESULT theErr = HXR_OK;
- KillThreadAndEvent();
- HX_RELEASE(m_pPrimaryBuffer);
- HX_RELEASE(m_pSecondaryBuffer);
- HX_RELEASE(m_pDSDev);
- m_pAudioPtrStart = NULL;
- m_ulLastPlayCursor = 0;
- m_ulLastWriteCursor =0;
- m_eState = E_DEV_CLOSED;
- m_ulLoops = 0;
- m_ulLoopTime = 0;
- m_nBlocksPerBuffer = 0;
- m_ulCurrPlayTime = 0;
- m_ulCurrLoopTime = 0;
- if (m_hwnd)
- {
- SetWindowLong(m_hwnd, GWL_USERDATA, NULL);
- }
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Pause()
- {
- HX_RESULT theErr = HXR_OK;
- m_bPaused = TRUE;
- if (m_pSecondaryBuffer)
- {
- m_pSecondaryBuffer->Stop();
- }
- m_eState = E_DEV_PAUSED;
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Resume()
- {
- if (m_pSecondaryBuffer && m_pAudioPtrStart)
- {
- m_pSecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
- if(m_bPaused)
- {
- m_bPaused = FALSE;
- }
- OnTimeSync();
- }
- m_eState = E_DEV_RESUMED;
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Write(const HXAudioData* pAudioHdr)
- {
- HRESULT res ;
- IHXBuffer* pBuffer;
- pBuffer = pAudioHdr->pData;
- UINT32 ulBufSize = pBuffer->GetSize();
- void* pAudioPtr1 = NULL;
- void* pAudioPtr2 = NULL;
- DWORD ulAudioBytes1 = 0;
- DWORD ulAudioBytes2 = 0;
- res = m_pSecondaryBuffer->Lock(m_ulLastWriteCursor, ulBufSize, &pAudioPtr1, &ulAudioBytes1,
- &pAudioPtr2, &ulAudioBytes2, 0);
- if(res != DS_OK)
- {
- RMDS_LOG(" Lock failed ulBufSize = %ld pAudioPtr1 = %ld ulAudioBytes1 = %ld pAudioPtr2 = %ld ulAudioBytes2 = %ld n", ulBufSize, pAudioPtr1, ulAudioBytes1, pAudioPtr2, ulAudioBytes2);
- return HXR_FAIL ;
- }
- HX_ASSERT(ulBufSize = ulAudioBytes1+ulAudioBytes2);
- m_ulLastWriteCursor += ulBufSize ;
- if (m_ulLastWriteCursor >= m_ulTotalBuffer)
- m_ulLastWriteCursor -= m_ulTotalBuffer;
- if(pAudioPtr1)
- {
- ::memcpy(pAudioPtr1, (void*) pBuffer->GetBuffer(), ulAudioBytes1); /* Flawfinder: ignore */
- if(!m_pAudioPtrStart)
- {
- m_pAudioPtrStart = pAudioPtr1;
- m_ulLoops = 0;
- m_pSecondaryBuffer->SetCurrentPosition(0);
- }
- }
- if (pAudioPtr2)
- ::memcpy(pAudioPtr2, ((char*)pBuffer->GetBuffer()) + ulAudioBytes1 , ulAudioBytes2); /* Flawfinder: ignore */
- res = m_pSecondaryBuffer->Unlock(pAudioPtr1, ulAudioBytes1, pAudioPtr2, ulAudioBytes2);
- if(res != DS_OK)
- {
- RMDS_LOG(" Unlock failed ulBufSize = %ld pAudioPtr1 = %ld ulAudioBytes1 = %ld pAudioPtr2 = %ld ulAudioBytes2 = %ld n", ulBufSize, pAudioPtr1, ulAudioBytes1, pAudioPtr2, ulAudioBytes2);
- return HXR_FAIL ;
- }
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_SetVolume(const UINT16 uVolume)
- {
- LONG lVol = 0;
- m_uCurVolume = uVolume;
- if( m_uCurVolume == 0)
- lVol = DSBVOLUME_MIN;
- else
- {
- double dVolFromMin = (double)m_uCurVolume - m_uMinVolume;
- double dVolFrac = (dVolFromMin/(m_uMaxVolume - m_uMinVolume));
- lVol = (LONG)(1055.0 * log(dVolFrac));
- }
- if(m_pSecondaryBuffer)
- m_pSecondaryBuffer->SetVolume(lVol);
- return HXR_OK;
- }
- UINT16 CHXAudioDeviceDS::_Imp_GetVolume()
- {
- LONG lVolume;
- if (!m_pSecondaryBuffer)
- return m_uMaxVolume ;
- m_pSecondaryBuffer->GetVolume(&lVolume);
- return (UINT16)(exp(lVolume / 1055.0) * (m_uMaxVolume - m_uMinVolume) + m_uMinVolume) ;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Reset()
- {
- if ( NULL == m_pSecondaryBuffer )
- {
- return HXR_OK;
- }
- void* pAudioPtr1 = NULL;
- void* pAudioPtr2 = NULL;
- DWORD ulAudioBytes1 = 0;
- DWORD ulAudioBytes2 = 0;
- HRESULT result = m_pSecondaryBuffer->Lock(0, 0, &pAudioPtr1, &ulAudioBytes1,&pAudioPtr2, &ulAudioBytes2, DSBLOCK_ENTIREBUFFER);
- if(result == DS_OK)
- {
- ::ZeroMemory(pAudioPtr1, ulAudioBytes1);
- ::ZeroMemory(pAudioPtr2, ulAudioBytes2);
- m_ulLastWriteCursor = 0;
- m_pSecondaryBuffer->Unlock(pAudioPtr1, ulAudioBytes1, pAudioPtr2, ulAudioBytes2);
- m_ulCurrPlayTime = 0;
- m_ulCurrLoopTime = 0;
- m_ulLoops = 0;
- m_ulLastPlayCursor = 0;
- m_pAudioPtrStart = pAudioPtr1;
- m_pSecondaryBuffer->SetCurrentPosition(0);
- RMDS_LOG("RESET n n n n");
- }
- else
- {
- RMDS_LOG(" Reset - Lock failed n");
- }
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_Drain()
- {
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_CheckFormat( const HXAudioFormat* pFormat )
- {
- return HXR_OK;
- }
- HX_RESULT CHXAudioDeviceDS::_Imp_GetCurrentTime(ULONG32& ulCurrentTime)
- {
- DWORD dwCurrentPlayCursor = 0;
- DWORD dwCurrentWriteCursor = 0;
- HRESULT result;
- ulCurrentTime = m_ulCurrPlayTime;
- if (m_pSecondaryBuffer)
- {
- result = m_pSecondaryBuffer->GetCurrentPosition(&dwCurrentPlayCursor,
- &dwCurrentWriteCursor);
- if (result == DS_OK)
- {
- UINT32 uLast = m_ulCurrPlayTime;
- if(dwCurrentPlayCursor != m_ulLastPlayCursor)
- {
- if( (dwCurrentPlayCursor < m_ulLastPlayCursor) && ((m_ulLastPlayCursor-dwCurrentPlayCursor) > (m_ulTotalBuffer/2)) )
- {
- RMDS_LOG(" m_ulLastPlayCursor = %ld ; dwCurrentPlayCursor = %ld n", m_ulLastPlayCursor, dwCurrentPlayCursor);
- m_ulLoops++;
- m_ulCurrPlayTime = m_ulCurrLoopTime = (UINT32) (m_ulLoopTime * 1000.0 * m_ulLoops);
- m_ulLastPlayCursor = 0;
- }
- // Time can only move forward
- if (dwCurrentPlayCursor > m_ulLastPlayCursor)
- {
- ULONG32 ulSamplesPlayedThisLoop =
- dwCurrentPlayCursor / m_WaveFormat.Format.nBlockAlign;
- m_ulCurrPlayTime = m_ulCurrLoopTime +
- m_TSConverter.ConvertVector(ulSamplesPlayedThisLoop);
- m_ulLastPlayCursor = dwCurrentPlayCursor;
- }
- ulCurrentTime = m_ulCurrPlayTime;
- }
- RMDS_LOG(" ulCurrentTime = %ld n", ulCurrentTime);
- }
- else
- {
- RMDS_LOG(" GetCurrentPosition failed n");
- }
- }
- return HXR_OK;
- }
- UINT32
- CHXAudioDeviceDS::CalcMs(UINT32 ulNumBytes)
- {
- return (ulNumBytes * 1000UL ) / m_WaveFormat.Format.nAvgBytesPerSec ;
- }
- DWORD
- CHXAudioDeviceDS::defaultChannelMapping(UINT32 ulChannels) const
- {
- switch (ulChannels)
- {
- case 1:
- return SPEAKER_FRONT_CENTER ;
- case 2:
- return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT ;
- case 5:
- return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
- SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_CENTER ;
- case 6:
- return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
- SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY;
- }
- return 0 ;
- }
- void
- CHXAudioDeviceDS::KillThreadAndEvent()
- {
- DWORD dwThreadWaitResult = WAIT_FAILED;
- if(m_hDSNotifyEvent)
- {
- m_bExitThread = TRUE;
- ::SetEvent(m_hDSNotifyEvent);
- // Wait for thread to exit
- if ( m_hWaitThread )
- {
- dwThreadWaitResult = WaitForSingleObject(m_hWaitThread, kExitThreadWaitTime);
- }
- CloseHandle(m_hDSNotifyEvent);
- m_hDSNotifyEvent = NULL;
- }
- if(m_hWaitThread)
- {
- if ( dwThreadWaitResult != WAIT_OBJECT_0 )
- {
- ::TerminateThread(m_hWaitThread, -1 );
- }
- CloseHandle(m_hWaitThread);
- m_hWaitThread = NULL;
- }
- m_bExitThread = FALSE;
- }
- void
- CHXAudioDeviceDS::PostTimeSyncMessage()
- {
- ::PostMessage(m_hwnd, HXMSG_TIMESYNC, 0, 0);
- }
- DWORD WINAPI CHXAudioDeviceDS::EventThreadProc(LPVOID pVoid)
- {
- CHXAudioDeviceDS* pThis = (CHXAudioDeviceDS*)pVoid;
- if(!pThis)
- return 0;
- HANDLE hWaitEvent = pThis->GetEventHandle();
- if(!hWaitEvent)
- return 0;
- while(1)
- {
- DWORD dwReturn = WaitForMultipleObjects(1, &hWaitEvent, FALSE, INFINITE);
-
- if(pThis->GetExitCode())
- {
- return 0;
- }
- if (dwReturn != (WAIT_OBJECT_0 + 1))
- {
- // Post message to the window so that it can call OnTimeSync on the audio thread( on which the window was created )
- // and then reset the event
- pThis->PostTimeSyncMessage();
- ResetEvent(hWaitEvent);
- }
- }
- return 0;
- }
- static LRESULT CALLBACK HXDSWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- if(message == HXMSG_TIMESYNC)
- {
- CHXAudioDeviceDS* pThis = (CHXAudioDeviceDS*)GetWindowLong(hWnd, GWL_USERDATA);
- if(pThis)
- pThis->OnTimeSync();
- return 0;
- }
- else if (message == CHXAudioDeviceDS::zm_uDestroyMessage)
- {
- LRESULT result = (LRESULT)DestroyWindow(hWnd);
- // free the memory used by this class now that our window is destroyed
- UnregisterClass(szWindowClass, g_hInstance);
- return result;
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
- }