📄 player.cpp
字号:
BOOL CPlayer::GetStreamTitle(LPTSTR pszTitle)
{
if (_tcslen(m_szOvdTitle)) {
_tcscpy(pszTitle, m_szOvdTitle);
return TRUE;
}
return m_Receiver.GetStreamTitle(pszTitle);
}
void CPlayer::GetOptions(MAP_OPTIONS* pOptions)
{
*pOptions = m_Options;
}
BOOL CPlayer::SetOptions(MAP_OPTIONS* pOptions)
{
if (m_Status != MAP_STATUS_STOP)
return FALSE;
if (m_Options.nOutputPrebuffer < 0 || m_Options.nOutputPrebuffer > 100)
return FALSE;
if (pOptions->nOutputBufferLen == m_Options.nOutputBufferLen &&
pOptions->fAlwaysOpenDevice == m_Options.fAlwaysOpenDevice &&
pOptions->fFadeIn == m_Options.fFadeIn) {
m_Options = *pOptions;
return TRUE;
}
m_Output.CloseAll();
if (!m_Output.SetOutputParam(pOptions->nOutputBufferLen,
pOptions->fAlwaysOpenDevice, pOptions->fFadeIn))
return FALSE;
m_Options = *pOptions;
return TRUE;
}
void CPlayer::GetStreamingOptions(MAP_STREAMING_OPTIONS* pOptions)
{
pOptions->nBuf = m_Receiver.GetBufferCount();
pOptions->nPreBuf = m_Receiver.GetPrebufferingCount();
pOptions->fUseProxy = m_Receiver.GetProxy(pOptions->szProxy);
m_Receiver.GetUserAgent(pOptions->szUserAgent);
}
BOOL CPlayer::SetStreamingOptions(MAP_STREAMING_OPTIONS* pOptions)
{
if (!m_Receiver.SetBufferCount(pOptions->nBuf))
return FALSE;
int nPreBuf = pOptions->nPreBuf;
if (nPreBuf > pOptions->nBuf)
nPreBuf = pOptions->nBuf;
m_Receiver.SetPrebufferingCount(nPreBuf);
m_Receiver.SetProxy(pOptions->fUseProxy, pOptions->szProxy);
m_Receiver.SetUserAgent(pOptions->szUserAgent);
return TRUE;
}
MAP_STREAMING_STATUS CPlayer::GetStreamingStatus()
{
return m_StreamingStatus;
}
int CPlayer::GetStreamingBufferingCount()
{
if (m_StreamingStatus < MAP_STREAMING_CONNECTING)
return 0;
return m_Receiver.GetBufferingCount();
}
// protected members
void CPlayer::PostCallbackMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PostMessage(m_hwndMessage, uMsg, wParam, lParam);
}
void CPlayer::UpdateStatus(MAP_STATUS status, BOOL fError)
{
if (m_Status != status) {
m_Status = status;
PostCallbackMessage(MAP_MSG_STATUS, status, fError);
}
}
void CPlayer::UpdatePeek()
{
PostCallbackMessage(MAP_MSG_PEEK, m_Output.m_nLPeek, m_Output.m_nRPeek);
}
BOOL CPlayer::PreparePlayback()
{
if (m_fStop)
return FALSE;
CAutoLock lock(&m_csecInterface);
int nBitsPerSample;
switch (m_fOpen) {
case OPEN_WAV_FILE:
nBitsPerSample = m_pwfxDst->wBitsPerSample; break;
case OPEN_PLUGIN:
nBitsPerSample = m_nPlugInBps; break;
default:
nBitsPerSample = 16;
}
if (!m_Output.Open(m_Info.nChannels, m_Info.nSamplingRate, nBitsPerSample))
return FALSE;
m_cbOutBuf = m_Output.GetBufferSize();
m_Output.Pause(TRUE);
m_Decoder.Init();
m_BassBoost.Open(m_Info.nChannels, m_Info.nSamplingRate);
m_Echo.Open(m_Info.nChannels, m_Info.nSamplingRate);
m_Reverb.Open(m_Info.nChannels, m_Info.nSamplingRate);
if (m_Info.nChannels == 2)
m_3DChorus.Open(m_Info.nSamplingRate);
m_fPlay = TRUE;
m_fStop = FALSE;
SetThreadPriority(m_hThread, INITIAL_THREAD_PRIORITY);
return TRUE;
}
BOOL CPlayer::UnpreparePlayback(BOOL fEos, BOOL fError)
{
if (fEos) {
if (m_pOutHdr) {
OutputBuffer(m_pOutHdr, m_cbOutBuf - m_cbOutBufLeft);
m_pOutHdr = NULL;
m_cbOutBufLeft = 0;
}
while (!m_Output.IsFlushed()) {
if (m_fPlay && GetStatus() == MAP_STATUS_PLAY) {
m_Output.Pause(FALSE);
m_fPlay = FALSE;
}
Sleep(1);
if (m_fSeek)
return FALSE;
if (m_fStop)
break;
UpdatePeek();
}
}
m_Output.Close();
m_Echo.Close();
m_Reverb.Close();
m_BassBoost.Close();
m_3DChorus.Close();
m_Decoder.Destroy();
if (!m_Options.fAlwaysOpenDevice || fError)
m_Output.CloseAll();
if (m_fOpen == OPEN_URL) {
m_Receiver.Disconnect();
m_StreamingStatus = MAP_STREAMING_DISCONNECTED;
}
m_pOutHdr = NULL;
m_cbOutBufLeft = 0;
m_nSeek = 0;
m_fPlay = FALSE;
m_fStop = FALSE;
m_fSeek = FALSE;
switch (m_fOpen) {
case OPEN_PLUGIN:
PlugInStop(); break;
case OPEN_MPG_FILE:
MpgStop(); break;
case OPEN_OV_FILE:
OvStop(); break;
case OPEN_WAV_FILE:
WavStop(); break;
case OPEN_URL:
NetStop(); break;
}
PostMessage(m_hwndMessage, MAP_MSG_PEEK, 0, 0);
UpdateStatus(MAP_STATUS_STOP, fError);
return TRUE;
}
void CPlayer::OutputBuffer(WAVEHDR* pHdr, DWORD cbRecorded)
{
int nBitsPerSample;
switch (m_fOpen) {
case OPEN_WAV_FILE:
nBitsPerSample = m_pwfxDst->wBitsPerSample; break;
case OPEN_PLUGIN:
nBitsPerSample = m_nPlugInBps; break;
default:
nBitsPerSample = 16;
}
// 愭摢偺柍壒僒儞僾儖偺彍嫀
if (m_fOpen != OPEN_URL) {
if (m_fFileBegin) {
m_Output.SetFadeOff();
if (m_Options.fSuppressZeroSamples) {
DWORD cb = m_Output.ScanZeroSamples(TRUE, (BYTE*)pHdr->lpData, cbRecorded);
if (cb == cbRecorded) {
pHdr->dwBytesRecorded = 0;
m_Output.OutputBuffer(pHdr);
m_nSeek += cb / (m_Info.nChannels * (nBitsPerSample / 8));
#ifdef _WIN32_WCE
Sleep(1);
#endif
return;
}
else {
cbRecorded -= cb;
memmove(pHdr->lpData, pHdr->lpData + cb, cbRecorded);
m_nSeek += cb / (m_Info.nChannels * (nBitsPerSample / 8));
}
}
m_fFileBegin = FALSE;
}
else {
// 僼傽僀儖枛旜偺柍壒偺彍嫀
if (m_Options.fSuppressZeroSamples) {
if (m_fSuppress) {
pHdr->dwBytesRecorded = 0;
m_Output.OutputBuffer(pHdr);
return;
}
if (m_nWritten + m_nSeek >= m_nDuration - (m_Info.nSamplingRate * 10)) { // 枛抂10昩偵摓払偟偨偐丠
DWORD cb = m_Output.ScanZeroSamples(FALSE, (BYTE*)pHdr->lpData, cbRecorded);
if ((int)cb > m_Info.nChannels * m_Info.nSamplingRate * (nBitsPerSample / 8) / 100) { // 10儈儕昩埲忋柍壒偑偁傞偐丠
cbRecorded -= cb;
m_fSuppress = TRUE;
}
}
}
}
}
pHdr->dwBufferLength = pHdr->dwBytesRecorded = cbRecorded;
// 僄僼僃僋僩偺張棟
short* p = (short*)pHdr->lpData;
if (m_Info.nChannels == 2) {
m_3DChorus.Process(nBitsPerSample, (LPBYTE)p, cbRecorded);
m_Surround.Process(nBitsPerSample, p, cbRecorded);
}
m_BassBoost.Process(nBitsPerSample, p, cbRecorded);
m_Echo.Process(nBitsPerSample, p, cbRecorded);
m_Reverb.Process(nBitsPerSample, p, cbRecorded);
// 僺乕僋儊乕僞傪峏怴
UpdatePeek();
// 弌椡
m_Output.OutputBuffer(pHdr);
m_nWritten += pHdr->dwBytesRecorded / (nBitsPerSample / 8 * m_Info.nChannels);
// 嵞惗奐巒捠抦
if (m_fPlay && GetStatus() == MAP_STATUS_PLAY) {
if ((int)m_Output.GetBufferingSamples() >=
((m_Info.nSamplingRate * m_Options.nOutputBufferLen) / 1000) * m_Options.nOutputPrebuffer / 100) {
m_Output.Pause(FALSE);
m_fPlay = FALSE;
::SetThreadPriority(m_hThread, m_Options.nThreadPriority);
}
else if (m_Output.GetBufferingCount() == m_Output.GetBufferCount()) {
m_Output.Pause(FALSE);
m_fPlay = FALSE;
::SetThreadPriority(m_hThread, m_Options.nThreadPriority);
}
}
}
void CPlayer::AudioDeviceClose()
{
if (m_Status != MAP_STATUS_STOP)
Stop();
m_Output.CloseAll();
}
void CPlayer::GetBufferInfo(DWORD* pcbTotalAudio, DWORD* pcbBufferedAudio,
DWORD* pcbTotalStream, DWORD* pcbBufferedStream)
{
m_Output.GetBufferInfo(pcbTotalAudio, pcbBufferedAudio);
m_Receiver.GetBufferInfo(pcbTotalStream, pcbBufferedStream);
}
BOOL CPlayer::WaitForPrebuffering(int nBuffering)
{
if (!nBuffering)
nBuffering = m_Receiver.GetPrebufferingCount();
while (TRUE) {
if (m_fStop)
return FALSE;
if (!m_Receiver.IsConnected())
return m_Receiver.IsEos() ? TRUE : FALSE;
if (m_Receiver.GetBufferingCount() >= nBuffering)
return TRUE;
Sleep(1);
}
}
void CPlayer::Preamp(LPBYTE pbBuf, DWORD cbBuf)
{
if (m_fPreamp)
m_Output.Preamp(pbBuf, cbBuf, m_nPreampRate);
}
DWORD WINAPI CPlayer::PlayerThreadProc(LPVOID pParam)
{
CPlayer* pPlayer = (CPlayer*)pParam;
if (pPlayer->m_fOpen == OPEN_URL)
pPlayer->NetStreamingThread();
else
pPlayer->FilePlayerThread();
return 0;
}
void CPlayer::FilePlayerThread()
{
int nRet = RET_ERROR;
UpdateStatus(MAP_STATUS_WAIT);
if (!PreparePlayback()) {
UnpreparePlayback(FALSE, TRUE);
return;
}
UpdateStatus(MAP_STATUS_PLAY);
retry:
switch (m_fOpen) {
case OPEN_PLUGIN:
nRet = PlugInPlayerThread(); break;
case OPEN_MPG_FILE:
nRet = MpgPlayerThread(); break;
case OPEN_OV_FILE:
nRet = OvPlayerThread(); break;
case OPEN_WAV_FILE:
nRet = WavPlayerThread(); break;
}
switch (nRet) {
case RET_EOF:
if (!UnpreparePlayback(TRUE))
goto retry;
break;
case RET_STOP:
UnpreparePlayback();
break;
case RET_ERROR:
UnpreparePlayback(FALSE, TRUE);
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -