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

📄 hxaudevds.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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#endiftypedef 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+501const 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 RMDSLogCHXAudioDeviceDS::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;

⌨️ 快捷键说明

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