audunix.cpp
来自「linux下的一款播放器」· C++ 代码 · 共 1,081 行 · 第 1/3 页
CPP
1,081 行
//has alread exited. retCode = _Imp_Reset(); if( retCode != RA_AOE_DEVNOTOPEN ) { if( _IsSelectable() ) { IHXAsyncIOSelection* pAsyncIO = NULL; if( HXR_OK == m_pContext->QueryInterface( IID_IHXAsyncIOSelection, (void**)&pAsyncIO) ) { pAsyncIO->Remove(_Imp_GetAudioFd() , PNAIO_WRITE); HX_RELEASE( pAsyncIO ); } } } //Close the audio device. retCode = _CloseAudio(); //Close the mixer device. _CloseMixer(); //Set state. LOCK(m_mtxWriteListPlayStateLock); m_wState = RA_AOS_CLOSED; UNLOCK(m_mtxWriteListPlayStateLock); //Remove callback from scheduler if (m_bCallbackPending) { m_pScheduler->Remove(m_PendingCallbackID); m_bCallbackPending = FALSE; } HX_VECTOR_DELETE(m_pRollbackBuffer); //return m_wLastError = retCode; return m_wLastError;}//So far no UN*X platforms support this.HX_RESULT CAudioOutUNIX::_Imp_Seek(ULONG32 ulSeekTime){ m_wLastError = HXR_OK; return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_Pause(){ //XXXgfw We really should be closing the device instead of keeping it open to be nice to //other procs. LOCK(m_mtxWriteListPlayStateLock); m_wState = RA_AOS_OPEN_PAUSED; UNLOCK(m_mtxWriteListPlayStateLock); if( !_HardwarePauseSupported() ) { // Strategy. //--Find out how much we have left in the device's buffer. ULONG32 ulBytesPlayed = _GetBytesActualyPlayed(); ULONG32 ulNumBytesToRewind = m_ulTotalWritten-ulBytesPlayed; //Sometimes we can get a value for bytesPlayed that is slightly //more then the amount we have actually written. This results //in a huge number. if( ulBytesPlayed > m_ulTotalWritten ) ulNumBytesToRewind = 0; //--and reset player and discard all the data in the device's buffer //We will just ignore an error here. That means the buffer will just drain //and we will hear it again when they unpause. LOCK(m_mtxDeviceStateLock); _Reset(); UNLOCK(m_mtxDeviceStateLock); //Make sure we only deal with full samples. Bytes-per-sample*num-channels. int nRem = ulNumBytesToRewind%(m_uSampFrameSize*m_unNumChannels); ulNumBytesToRewind = ulNumBytesToRewind>nRem ? ulNumBytesToRewind-nRem : 0; // In heap-optimized mode, we accept that we're going to lose a // little bit of data after a pause/resume because we are using as // small a rollback buffer as we can get away with.#ifdef HELIX_CONFIG_MIN_ROLLBACK_BUFFER if( ulNumBytesToRewind > m_ulDeviceBufferSize ) { ulNumBytesToRewind = m_ulDeviceBufferSize; }#endif // HELIX_CONFIG_MIN_ROLLBACK_BUFFER // and add it to the front of the write buffer. IHXBuffer* pNewBuffer = new CHXBuffer(); pNewBuffer->Set( m_pRollbackBuffer+m_ulDeviceBufferSize-ulNumBytesToRewind, ulNumBytesToRewind ); LOCK(m_mtxWriteListPlayStateLock); m_pWriteList->AddHead(pNewBuffer); pNewBuffer->AddRef(); UNLOCK(m_mtxWriteListPlayStateLock); //--Subtract that from m_ulTotalWritten. m_ulTotalWritten -= ulNumBytesToRewind; _Pause(); } else { //The hardware device handles the Pause/Resume. LOCK(m_mtxDeviceStateLock); _Pause(); UNLOCK(m_mtxDeviceStateLock); } m_wLastError = HXR_OK; return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_Resume(){ //XXXgfw We really should be closing and re-opening the device to be nice to other procs. LOCK(m_mtxWriteListPlayStateLock); m_wState = RA_AOS_OPEN_PLAYING; UNLOCK(m_mtxWriteListPlayStateLock); //XXXgfw If the two branches of the if are the same maybe get rid of one???? if( !_HardwarePauseSupported() ) { _Resume(); _Imp_Write(NULL); } else { //The hardware device handles the Pause/Resume. _Resume(); _Imp_Write(NULL); } m_wLastError = HXR_OK; return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_Reset(){ HX_RESULT retCode = RA_AOE_NOERR; if ( m_wState != RA_AOS_CLOSED ) { LOCK(m_mtxDeviceStateLock); retCode = _Reset(); UNLOCK(m_mtxDeviceStateLock); LOCK(m_mtxWriteListPlayStateLock); while (m_pWriteList && m_pWriteList->GetCount() > 0) { IHXBuffer* pBuffer = (IHXBuffer *)(m_pWriteList->RemoveHead()); HX_RELEASE( pBuffer ); } UNLOCK(m_mtxWriteListPlayStateLock); m_ulTotalWritten = 0; m_bFirstWrite = TRUE; m_ulLastNumBytes = 0; } m_wLastError = retCode; return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_Drain(){ HX_RESULT retCode = RA_AOE_NOERR; LOCK(m_mtxWriteListPlayStateLock); if( m_wState != RA_AOS_CLOSED ) { retCode = _Drain(); } while( m_pWriteList && !m_pWriteList->IsEmpty() ) { IHXBuffer* pBuffer = (IHXBuffer *)(m_pWriteList->RemoveHead()); HX_RELEASE( pBuffer ); } UNLOCK(m_mtxWriteListPlayStateLock); m_wLastError = retCode; return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_CheckFormat( const HXAudioFormat* pFormat ){ HX_RESULT retCode = RA_AOE_NOERR; m_wLastError = HXR_OK; retCode = _CheckFormat( pFormat ); if( RA_AOE_NOERR != retCode && RA_AOE_DEVBUSY != retCode ) { m_wLastError = HXR_FAILED; } else { m_wLastError = HXR_OK; } return m_wLastError;}HX_RESULT CAudioOutUNIX::_Imp_GetCurrentTime( ULONG32& ulCurrentTime ){ ULONG32 ulTime = 0; UINT64 ulBytes = 0; LOCK(m_mtxWriteListPlayStateLock); ulBytes = _GetBytesActualyPlayed(); UNLOCK(m_mtxWriteListPlayStateLock); ulTime = (ULONG32)(( ( (double)ulBytes/(double)m_uSampFrameSize)/(double)m_unSampleRate) * 1000.0 / (double)m_unNumChannels); //Not used anywhere but belongs to CHXAudioDevice so we must set it. m_ulCurrentTime = ulTime; //Set the answer. ulCurrentTime = ulTime; m_wLastError = HXR_OK; return HXR_OK;}void CAudioOutUNIX::DoTimeSyncs(){ ReschedPlaybackCheck(); OnTimeSync(); return;}HX_RESULT CAudioOutUNIX::ReschedPlaybackCheck(){ HX_RESULT retCode = HXR_OK; if(!m_bCallbackPending) { HX_ASSERT( m_pCallback ); if(m_pCallback) { *m_pPlaybackCountCBTime += (int)(500*m_ulGranularity); m_bCallbackPending = TRUE; m_PendingCallbackID = m_pScheduler->AbsoluteEnter( m_pCallback,*((HXTimeval*)m_pPlaybackCountCBTime)); } else { retCode = HXR_OUTOFMEMORY; } } m_wLastError = retCode; return m_wLastError;}UINT16 CAudioOutUNIX::_NumberOfBlocksRemainingToPlay(void){ UINT32 bytesBuffered = 0; //We have to go through all of the buffers and count the size. Even though //we always write m_wBlockSize buffers, we can get off-sized buffs because //of the pause/resume code. When we pause we rewind however many bytes have //not been played yet in the buffer. LOCK(m_mtxWriteListPlayStateLock); if( m_pWriteList ) { LISTPOSITION i = m_pWriteList->GetHeadPosition(); while( i ) { bytesBuffered += ((IHXBuffer *)m_pWriteList->GetAt(i)) -> GetSize(); m_pWriteList->GetNext(i); } } bytesBuffered += (m_ulTotalWritten - _GetBytesActualyPlayed()); UNLOCK(m_mtxWriteListPlayStateLock); return bytesBuffered / m_wBlockSize + 1;}CAudioOutUNIX::HXPlaybackCountCB::~HXPlaybackCountCB(){}STDMETHODIMP CAudioOutUNIX::HXPlaybackCountCB::QueryInterface( REFIID riid, void** ppvObj ){ HX_RESULT retCode = HXR_OK; if( IsEqualIID(riid, IID_IHXCallback) ) { AddRef(); *ppvObj = (IHXCallback*)this; } else if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = this; } else { *ppvObj = NULL; retCode = HXR_NOINTERFACE; } return retCode;}STDMETHODIMP_(ULONG32) CAudioOutUNIX::HXPlaybackCountCB::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(ULONG32) CAudioOutUNIX::HXPlaybackCountCB::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return HXR_OK;}STDMETHODIMP CAudioOutUNIX::HXPlaybackCountCB::Func(void){ if (m_pAudioDeviceObject) { if(!m_timed) { //m_pAudioDeviceObject->_Imp_Write(NULL); } else { m_pAudioDeviceObject->m_bCallbackPending = FALSE; m_pAudioDeviceObject->_Imp_Write(NULL); m_pAudioDeviceObject->DoTimeSyncs(); } } return HXR_OK;}HX_RESULT CAudioOutUNIX::_Pause(){ return RA_AOE_NOTSUPPORTED;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?