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

📄 winaudio.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 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 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (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.  
 *  
 * 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"

#include "hlxclib/windows.h"
#include <mmsystem.h>
#include <tchar.h> 
#include <stdio.h>

#ifdef _TESTING
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#if defined (_WINDOWS) || defined (_WIN32)

#include <io.h>

#endif

#endif

#include "hxresult.h"

#include "hxcom.h"
#include "hxausvc.h"
#include "auderrs.h"
#include "ihxpckts.h"
#include "hxengin.h"

#include "timeval.h"

#include "hxaudev.h"
#include "hxslist.h"
#include "hxtick.h"

//#include "hxaudses.h"

#include "cbqueue.h"
#include "cpqueue.h"
#include "hxthread.h"

#include "winaudio.h"

#ifdef WIN32_PLATFORM_PSPC
#define WM_NCCREATE WM_CREATE
#define WM_NCDESTROY WM_DESTROY
#endif

struct IHXCallback;

extern HINSTANCE g_hInstance;
#define	OFFSET_THIS		0

#ifdef _TESTING
int m_audfile = -1;
#endif

BOOL	CAudioOutWindows::zm_bVolSupport = FALSE;
BOOL	CAudioOutWindows::zm_bLRVolSupport = FALSE;
WORD	CAudioOutWindows::zm_uMaxVolume = 100;
BOOL	CAudioOutWindows::zm_bMixerVolSupport = FALSE;
BOOL	CAudioOutWindows::zm_bMixerVolSupportChecked = FALSE;
UINT	CAudioOutWindows::zm_uDestroyMessage = 0;
BOOL	CAudioOutWindows::zm_bClosed = TRUE;
CAudioOutWindows* zm_pCurrentAudioDevice = NULL;

// BAD drivers which need to call waveOutSetVolume directly
const UINT16	g_nBadDrivers = 1;
const TCHAR*	g_badDrivers[] = {_T("Crystal Audio System")};
audioDevice	CAudioOutWindows::zm_audioDevice = HXAUDIO_UNKNOWN;

//CRITICAL_SECTION CAudioOutWindows::zm_AudioCritSection;

#define MAX_REASONABLE_BUFFS 40

#define PUSH_DOWN_TIME		400    /* push down 400 ms  */
#define LIKELY_PUSH_COUNT	10

CAudioOutWindows::CAudioOutWindows()
    : m_hWave(NULL)
    , m_unAllocedBufferCnt(0)
    , m_unAllocedBuffSize(0)
    , m_ppAllocedBuffers(NULL)
    , m_pWaveHdrs(NULL)
    , m_rAvailBuffers(MAX_REASONABLE_BUFFS)
    , m_bInitialized(FALSE)
    , m_bResetting(FALSE)
    , m_bIsFirstPacket(TRUE)
    , m_hWnd(NULL)
    , m_bClassRegistered(FALSE)
    , m_ulDevPosRollOver(0)
    , m_ulLastDeviceBytesPlayed(0)
    , m_ulLastDeviceSamplesPlayed(0)
    , m_llDeviceBytesPlayed(0)
    , m_llDeviceSamplesPlayed(0)
#if defined(_WIN32)
    , m_ulOriginalThreadId(0)
#endif /*_WIN32*/
{
    zm_bClosed = TRUE;    
    zm_pCurrentAudioDevice = this;

#if defined(_WIN32) && !defined(_WINCE)
    m_hMixer = NULL;  
    memset(&m_VolumeControlDetails, 0 , sizeof(MIXERCONTROLDETAILS));
#endif // _WIN32

    // Create a unique message for destroying the audio window
    if (!zm_uDestroyMessage)
    {
	zm_uDestroyMessage = RegisterWindowMessage(_T("HX_DestroyAudioServicesInternal"));
    }
    
#ifdef THREADS_SUPPORTED
    HXMutex::MakeMutex(m_pMutex);
#else
    HXMutex::MakeStubMutex(m_pMutex);
#endif
}		   


CAudioOutWindows::~CAudioOutWindows()
{
//    OutputDebugString("BEFORE CALL TO:CAudioOutWindows::~CAudioOutWindows\r\n");
    // this gives us one last chance to recover packets that are still in the device
    Reset();

    // We might as well consider the device closed!
    zm_bClosed = TRUE;

#if defined(_WIN32) && !defined(_WINCE)

    /* This sleep is added to fix a hang bug that ONLY happens on
     * Darren's machine if you adjust audio volume. His machine
     * has a really old audio driver
     * 
     * I have no clue what this bug is and how this Sleep(0)
     * fixes it. Obviously, there was some race condition.
     *
     * Sound Driver Info:
     *
     * Version 2.03.0 Build 1
     * Creative Sound Blaster 16 Driver (Windows NT)
     * 
     */
    Sleep(0);

    if(m_hMixer)
    {
        mixerClose(m_hMixer);
    }
#endif // _WIN32

    _Imp_Close();

    zm_pCurrentAudioDevice = NULL;
    HX_DELETE(m_pMutex);
}

UINT16 CAudioOutWindows::_Imp_GetVolume()
{
    DWORD dwVol	    = 0;                          
    BOOL bSuccess   = FALSE;

#if defined(_WIN32) && !defined(_WINCE)
    if (!zm_bMixerVolSupportChecked)
    {
	CheckForVolumeSupport();
    }

    if(zm_bMixerVolSupport)
    {
	if (!m_hMixer)
	{
	    CheckForVolumeSupport();
	}

        PMIXERCONTROLDETAILS_UNSIGNED pmxVolume;
        UINT16 nItems = 1;
        if(m_VolumeControlDetails.cMultipleItems)
            nItems = (UINT16)m_VolumeControlDetails.cMultipleItems;
        pmxVolume = new MIXERCONTROLDETAILS_UNSIGNED[nItems];
        m_VolumeControlDetails.cbDetails = nItems * sizeof(MIXERCONTROLDETAILS_UNSIGNED);
        m_VolumeControlDetails.paDetails = pmxVolume;
        if(mixerGetControlDetails((HMIXEROBJ)m_hMixer, &m_VolumeControlDetails, 
           MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
        {
            dwVol = pmxVolume[0].dwValue;
            bSuccess = TRUE;
        }
        delete[] pmxVolume;
    }
#endif

    if (!bSuccess)
    {
	if (!zm_bVolSupport)
	{
	    return 0;
	}

	MMRESULT hResult = waveOutGetVolume( m_hWave, &dwVol );

	if (hResult != MMSYSERR_NOERROR && m_hWave != NULL)
	{
	    hResult = waveOutGetVolume( NULL, &dwVol );
	}

	if (hResult != MMSYSERR_NOERROR)
	{
	    return 0;
	}
    }

    return ( (UINT16)((DWORD)LOWORD( dwVol ) * zm_uMaxVolume / 0xFFFF ) );
}

HX_RESULT CAudioOutWindows::_Imp_SetVolume
( 
    const UINT16 uVolume
)
{
    DWORD dwVol = 0;
    BOOL bSuccess = FALSE;

    if (uVolume > zm_uMaxVolume)
    {
        return HXR_OK;
    }

    dwVol = (DWORD)uVolume * 0xFFFF / zm_uMaxVolume;
    
    // Here we are avoiding rounding error
    if(dwVol * zm_uMaxVolume / 0xFFFF < uVolume)
	dwVol += 0xFFFF / zm_uMaxVolume;

    if (zm_audioDevice == HXAUDIO_BADDEVICE)
    {
	goto noMixer;
    }

#if defined(_WIN32) && !defined(_WINCE)
    if (!zm_bMixerVolSupportChecked)
    {
	CheckForVolumeSupport();
    }

    if(zm_bMixerVolSupport)
    {
	if (!m_hMixer)
	{
	    CheckForVolumeSupport();
	}
        PMIXERCONTROLDETAILS_UNSIGNED pmxVolume;
        UINT16 nItems = 1;
        if(m_VolumeControlDetails.cMultipleItems)
            nItems = (UINT16)m_VolumeControlDetails.cMultipleItems;
        pmxVolume = new MIXERCONTROLDETAILS_UNSIGNED[nItems];
        for(UINT16 nIndex = 0; nIndex < nItems; nIndex++)
            pmxVolume[nIndex].dwValue = dwVol;
        m_VolumeControlDetails.cbDetails = nItems * sizeof(MIXERCONTROLDETAILS_UNSIGNED);
        m_VolumeControlDetails.paDetails = pmxVolume;
        if(mixerSetControlDetails((HMIXEROBJ)m_hMixer, &m_VolumeControlDetails, 
           MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR)
		{
			bSuccess = TRUE;
        }
        delete[] pmxVolume;
    }
#endif

noMixer:
    if ( !bSuccess )
    {
	DWORD dwLRVol = MAKELONG(dwVol, dwVol) ;
	// fix of bug 4965, in which the balance is thrown to one side.  My speculation is that the
	// driver incorrectly reports MONO here when stereo is in use.  To fix the bug, set both
	// channels equally.  john dempsey

	/* related information: 
	"If a devicedoes not support both left and right volume control, the low-order
	 word of the dwVolume argument specifies the volume level and the
	 high-order word is ignored." -- some DEC document on waveOutSetVolume.
	*/

	HX_ASSERT(LOWORD(dwLRVol) == HIWORD(dwLRVol)) ;
	if (!zm_bVolSupport)
	{
	    return HXR_FAILED;
	}

	MMRESULT hResult    = waveOutSetVolume(m_hWave, dwLRVol);

	
	MMRESULT hResult2 = hResult;

	/* 
	 * always set the volume on NULL device. 
	 * Needed to attach volume control on win98 SE, Creative SB Live! Value sound card.
	 */
	if (m_hWave != NULL)
	{
	     hResult2 = waveOutSetVolume(NULL, dwLRVol);
	}

	if (hResult != MMSYSERR_NOERROR && hResult2 != MMSYSERR_NOERROR)
	{
	    return HXR_FAILED;
	}
    }

    return HXR_OK;
}

BOOL CAudioOutWindows::_Imp_SupportsVolume()
{
    MMRESULT wSuccess;
    WAVEOUTCAPS auxcap; 

#if defined(_WIN32) && !defined(_WINCE)
    if (!zm_bMixerVolSupportChecked)
    {
	CheckForVolumeSupport();
    }
#endif

#if defined(_WIN32) || defined(_WINCE)

	// Gonna have to make VolSupport static  
    if ( zm_bVolSupport )
    {
        return (zm_bVolSupport);
    }

    wSuccess = waveOutGetDevCaps( 0, &auxcap, sizeof(WAVEOUTCAPS) );

    if ( MMSYSERR_NOERROR == wSuccess )
    { 
        if (auxcap.dwSupport & WAVECAPS_VOLUME)
		{
		    zm_bVolSupport=TRUE;
		}

		if (auxcap.dwSupport & WAVECAPS_LRVOLUME)
		{
			zm_bLRVolSupport = TRUE;
		}
	
		zm_uMaxVolume = 100;
	}                   
    else
    {
        zm_bVolSupport = FALSE;
        zm_bLRVolSupport = FALSE;
    }

    return zm_bVolSupport;
#else
    return FALSE;
#endif /*_WIN32*/
}

HX_RESULT CAudioOutWindows:: _Imp_Open
( 
    const HXAudioFormat* pFormat
)
{
    HX_RESULT theErr = HXR_OK;
#if defined(_WIN32)
    LPWAVEFORMATEX	wavePtr;
#elif defined( _WINDOWS )
    LPWAVEFORMAT	wavePtr;
#endif

    theErr = Register();
    if (theErr)
    {
	return theErr;
    }
	
#ifdef _TESTING
    m_audfile =  open("e:\\auddev.raw", O_WRONLY | O_CREAT);
#endif

    m_WaveFormat.SetFormat(pFormat->ulSamplesPerSec, pFormat->uChannels, pFormat->uBitsPerSample);
    // Get the Windows style wave format!
    wavePtr = m_WaveFormat.GetWaveFormat();

    // We ain't closed now
    zm_bClosed = FALSE;

    // Open the wave driver.
#ifdef _WIN16
    MMRESULT wRet = waveOutOpen( &m_hWave, WAVE_MAPPER, wavePtr,
			(UINT16)m_hWnd, (DWORD)this, CALLBACK_WINDOW);
#else
    MMRESULT wRet = waveOutOpen( &m_hWave, WAVE_MAPPER, wavePtr,
			(DWORD)m_hWnd, (DWORD)this, CALLBACK_WINDOW);
#endif


    //	Okay, translate any error returns and get out if there was an error
    switch (wRet)
    {
	case MMSYSERR_NOERROR:	    theErr = HXR_OK;		break;
	case MMSYSERR_ALLOCATED:    theErr = HXR_AUDIO_DRIVER;	break;
	case MMSYSERR_NOMEM:	    theErr = HXR_OUTOFMEMORY;	break;
	case MMSYSERR_BADDEVICEID:  theErr = HXR_AUDIO_DRIVER;	break;
	case WAVERR_BADFORMAT:	    theErr = HXR_AUDIO_DRIVER;	break;
	case WAVERR_SYNC:	    theErr = HXR_AUDIO_DRIVER;	break;
	default:		    theErr = HXR_OUTOFMEMORY;	break;
    }
#if defined(_WIN32) && !defined(_WINCE)
	if ( !theErr )
	{
	    if (!zm_bMixerVolSupportChecked)
	    {
		CheckForVolumeSupport();
	    }
	}
#endif


    return theErr;

⌨️ 快捷键说明

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