📄 hxaudses.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: hxaudses.cpp,v 1.39.2.3.2.3 2005/01/24 07:55:08 rggammon 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"
#include "safestring.h"
#include "hlxclib/stdio.h"
#include "hlxclib/string.h"
#include "hlxclib/stdlib.h"
#ifndef WIN32_PLATFORM_PSPC
#include "hlxclib/signal.h"
#else
#include <winbase.h>
#include <dbgapi.h>
#endif
//#define _TESTING 1
#ifdef _TESTING
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined (_WINDOWS) || defined (_WIN32)
#include <io.h>
#endif
#endif
//#include "racodec.h"
#include "hxresult.h"
#include "hxcom.h"
#include "hxshtdn.h"
#include "hxengin.h"
#include "hxausvc.h"
#include "hxrasyn.h"
#include "hxprefs.h"
#include "ihxpckts.h"
#include "chxpckts.h"
#include "auderrs.h"
#include "hxslist.h"
#include "hxtick.h"
#ifdef _SYMBIAN
#include "audsymbian.h"
#else
#include "hxaudev.h"
#endif
#include "hxaudply.h"
#include "hxaudstr.h"
#include "hxaudvol.h"
#include "timeval.h"
#include "hxaudses.h"
#include "hxaudtyp.h"
#include "hxmixer.h"
#include "hxthread.h"
#if defined (HELIX_FEATURE_RESAMPLER) && !defined (HELIX_CONFIG_FIXEDPOINT)
#include "hxrsmp2.h"
#endif /* HELIX_FEATURE_RESAMPLER && !HELIX_CONFIG_FIXEDPOINT */
#include "hxprefs.h"
#include "hxprefutil.h"
class CHXAudioPlayer;
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
// The following value was arrived at via trial and error and has been
// demonstrated to give optimal heap usage values for RA8, ATRAC3, & MP3.
#define IDEAL_MINIMAL_INITIAL_PUSHDOWN 500 //ms
#else
#define IDEAL_MINIMAL_INITIAL_PUSHDOWN 1000 // ms
#endif
#define MIN_BLOCKS_TOBEQUEUED (m_ulMinimumPushdown*1.0/m_ulGranularity)
#define SOME_INSANELY_LARGE_VALUE 3600000 /* 1 hour */
#ifdef _WIN32
#define HXMSG_QUIT (WM_USER + 200) /* Exit from the thread */
#define HXMSG_RESUME (WM_USER + 201) /* Resume audio thread */
#define HXMSG_STOP (WM_USER + 202) /* Stop audio thread */
#else
#define HXMSG_QUIT 200 /* Exit from the thread */
#define HXMSG_RESUME 201 /* Change timer value */
#define HXMSG_STOP 202 /* Stop audio thread */
#endif /*_WIN32*/
#ifdef _MACINTOSH
BOOL CHXAudioSession::zm_Locked=FALSE;
#endif /* _MACINTOSH */
#ifdef _UNIX
IHXPreferences* z_pIHXPrefs = NULL;
#endif
//XXXgfw can whatever this SH4 is be moved down into the audio device
//code for this chipset? This is how we don't allow certain sample
//rates in other devices; by returning HXR_FAIL from _imp_checkformat.
#if !defined(SH4)
const unsigned short z_anValidSampleRates[] = { 8000,
11025,
16000,
22050,
32000,
44100
};
#else
const unsigned short z_anValidSampleRates[] = { 11025,
22050,
44100
};
#endif
struct tableEntry
{
UINT16 usSampleRate;
UINT8 usChannels;
UINT8 usBits;
inline void set(UINT16 sr,
UINT8 chan,
UINT8 bits
)
{
usSampleRate = sr;
usChannels = chan;
usBits = bits;
}
};
/*
* HXAudioSession methods
*/
/************************************************************************
* Method:
* CHXAudioSession::CHXAudioSession()
* Purpose:
* Constructor. Create player list.
*/
CHXAudioSession::CHXAudioSession()
: m_pContext(NULL)
, m_lRefCount(0)
, m_pScheduler (0)
, m_pPreferences(0)
, m_pInterruptState(0)
, m_pPlayerBuf (NULL)
, m_pSessionBuf (NULL)
, m_ulGranularity(0)
, m_dGranularity((double) 0.)
, m_ulMinimumPushdown(MINIMUM_INITIAL_PUSHDOWN)
, m_ulIdealMinimumPushdown(IDEAL_MINIMAL_INITIAL_PUSHDOWN)
, m_ulMinBlocksTobeQueued(1)
, m_ulMinBlocksTobeQueuedAtStart(1)
, m_ulBytesPerGran(0)
, m_ulBlocksWritten(0)
, m_ulCallbackID(0)
, m_bFakeAudioTimeline(FALSE)
, m_bShouldOpenOnCoreThread(FALSE)
, m_bToBeReOpened(FALSE)
, m_pDeviceCallback(NULL)
, m_bHasStreams(FALSE)
, m_ulIncreasingTimer (0)
, m_ulCurrentTime (0)
, m_ulLastAudioTime(0)
, m_ulLastAudioReturnTime(0)
, m_ulLastSystemTime(0)
, m_bAtLeastOneTimeReceived(FALSE)
, m_ulStartTime(0)
, m_bTimeSyncReceived(FALSE)
, m_bPaused(TRUE)
, m_bStoppedDuringPause(FALSE)
, m_ulLastFakeCallbackTime(0)
, m_pFakeAudioCBTime(0)
, m_pInDataPtr(0)
, m_pOutDataPtr(0)
, m_pPlayerResponse(0)
, m_bFirstPlayAudio(TRUE)
, m_uVolume(HX_INIT_VOLUME)
, m_bMute(FALSE)
, m_bAudioDeviceSupportsVolume(TRUE)
, m_dBufEndTime((double) 0.)
, m_bDisableWrite(FALSE)
, m_bInPlayAudio(FALSE)
, m_bInActualResume(FALSE)
, m_dNumBytesWritten((double)0)
, m_dNumBytesPlayed((double)0)
, m_bInited(FALSE)
, m_pAudioDev(0)
, m_pCurrentAudioDev(NULL)
, m_pReplacedAudioDev(NULL)
, m_bReplacedDev(FALSE)
, m_pPlayerList(0)
, m_pHookList(NULL)
, m_pAuxiliaryAudioBuffers(0)
, m_pMutex(NULL)
, m_pFinalHook(NULL)
, m_bUseFinalHook(FALSE)
, m_pCoreMutex(NULL)
, m_uAskFromAudioDevice(0)
, m_bDeferActualResume(FALSE)
, m_pLastPausedPlayer(NULL)
, m_bUsingReplacedDevice(FALSE)
, m_bToBeRewound(FALSE)
, m_ulLastRewindTimestamp(0)
, m_uNumToBePushed(0)
, m_bSessionBufferDirty(FALSE)
, m_bPostMixHooksUpdated(FALSE)
, m_pMPPSupport(NULL)
#if defined(HELIX_FEATURE_TIMELINE_WATCHER)
, m_pTimeLineWatchers(NULL)
#endif
{
m_pFakeAudioCBTime = new Timeval;
m_pInDataPtr = new HXAudioData;
m_pOutDataPtr = new HXAudioData;
m_pInDataPtr->pData = 0;
m_pInDataPtr->ulAudioTime = 0;
m_pInDataPtr->uAudioStreamType = STREAMING_AUDIO;
m_pOutDataPtr->ulAudioTime = 0;
m_pOutDataPtr->pData = 0;
m_pOutDataPtr->uAudioStreamType = STREAMING_AUDIO;
/* Default value of Device format */
m_DeviceFmt.uChannels = 2;
m_DeviceFmt.uBitsPerSample = 16;
m_DeviceFmt.ulSamplesPerSec = 16000;
m_DeviceFmt.uMaxBlockSize = 64000;
#ifdef HELIX_FEATURE_VOLUME
m_pDeviceVolume = NULL;
#endif
#ifdef THREADS_SUPPORTED
HXMutex::MakeMutex(m_pMutex);
#else
HXMutex::MakeStubMutex(m_pMutex);
#endif
};
/************************************************************************
* Method:
* CHXAudioSession::~CHXAudioSession()
* Purpose:
* Destructor. Clean up and set free.
*/
CHXAudioSession::~CHXAudioSession()
{
Close();
}
void
CHXAudioSession::Close(void)
{
// Delete all player items
if ( m_pPlayerList )
{
CHXAudioPlayer* p = 0;
CHXSimpleList::Iterator lIter = m_pPlayerList->Begin();
for (; lIter != m_pPlayerList->End(); ++lIter)
{
p = (CHXAudioPlayer*) (*lIter);
if ( p )
p->Release();
}
delete m_pPlayerList;
m_pPlayerList = 0;
}
while (m_pHookList && m_pHookList->GetCount() > 0)
{
HXAudioHookInfo* pHookInfo = (HXAudioHookInfo*) m_pHookList->RemoveHead();
pHookInfo->pHook->Release();
delete pHookInfo;
}
HX_DELETE(m_pHookList);
if (m_pAuxiliaryAudioBuffers)
{
while (m_pAuxiliaryAudioBuffers->GetCount() > 0)
{
HXAudioData* pAudioData =
(HXAudioData*) m_pAuxiliaryAudioBuffers->RemoveHead();
pAudioData->pData->Release();
delete pAudioData;
}
delete m_pAuxiliaryAudioBuffers;
m_pAuxiliaryAudioBuffers = 0;
}
ResetSession();
if( m_ulCallbackID && m_pScheduler)
{
m_pScheduler->Remove(m_ulCallbackID);
m_ulCallbackID = 0;
}
#ifdef HELIX_FEATURE_VOLUME
if( m_pDeviceVolume )
{
m_pDeviceVolume->RemoveAdviseSink(this);
HX_RELEASE(m_pDeviceVolume);
}
#endif
if (m_pDeviceCallback && m_pDeviceCallback->PendingID())
{
m_pScheduler->Remove(m_pDeviceCallback->PendingID());
}
HX_RELEASE(m_pDeviceCallback);
HX_RELEASE(m_pScheduler);
HX_RELEASE(m_pInterruptState);
#if defined(HELIX_FEATURE_PREFERENCES)
if (m_pPreferences)
{
/* Store the last volume setting */
IHXBuffer* pBuffer = new CHXBuffer;
pBuffer->AddRef();
pBuffer->SetSize(16);
SafeSprintf((char*) pBuffer->GetBuffer(),16,"%d",(int) m_uVolume); /* Flawfinder: ignore */
m_pPreferences->WritePref("Volume", pBuffer);
pBuffer->Release();
#if defined(HELIX_FEATURE_MUTE_PREFERENCE)
/* Store the last mute setting */
IHXBuffer* pMuteBuffer = new CHXBuffer;
pMuteBuffer->AddRef();
pMuteBuffer->SetSize(16);
SafeSprintf((char*) pMuteBuffer->GetBuffer(),16,"%d",(int) m_bMute);
m_pPreferences->WritePref("Mute", pMuteBuffer);
pMuteBuffer->Release();
#endif /* HELIX_FEATURE_MUTE_PREFERENCE */
HX_RELEASE(m_pPreferences);
#ifdef _UNIX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -