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

📄 audunix.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            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;
}

HX_RESULT CAudioOutUNIX::_Resume()
{

⌨️ 快捷键说明

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