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

📄 audqnx.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	pNewBuffer->AddRef();

	// Update total pause bytes offset for time/video sync
	m_ulPauseBytes += pause_bytes;

	return RA_AOE_NOERR;
}

HX_RESULT CAudioOutQNX::_Imp_Resume()
{
	m_paused = FALSE;
	_Imp_Write( NULL );
	return RA_AOE_NOERR;
}

HX_RESULT CAudioOutQNX::_Imp_Reset()
{

	m_ulLastTimeChecked = (UINT32) -1;
	m_ulLastTimeReturned = 0;

	if ( m_wState == RA_AOS_CLOSED )
		return RA_AOE_NOERR;

	if ( m_wID < 0 )
		return RA_AOE_DEVNOTOPEN;

	// Temporary FLUSH <--> DRAIN
	if ( ioctl (m_wID, SND_PCM_IOCTL_DRAIN_PLAYBACK, 0) == -1 )
		return RA_AOE_GENERAL;

	while (m_pWriteList && m_pWriteList->GetCount() > 0)
	{
	    IHXBuffer* pBuffer = (IHXBuffer *)(m_pWriteList->RemoveHead());
	    pBuffer->Release();
	}

	m_ulTotalWritten    = 0;
	m_bFirstWrite	    = TRUE;
	m_ulLastNumBytes    = 0;

	return RA_AOE_NOERR;
}

HX_RESULT CAudioOutQNX::_Imp_Drain()
{
	if ( m_wID < 0 )
		return RA_AOE_DEVNOTOPEN;

	// Temporary FLUSH <--> DRAIN
	if ( ioctl (m_wID, SND_PCM_IOCTL_FLUSH_PLAYBACK, 0) == -1 )
		return RA_AOE_GENERAL;

	return RA_AOE_NOERR;
}

AUDIOERROR CAudioOutQNX::SetDeviceConfig
( 
	const HXAudioFormat* pFormat 
)
{
	if ( m_wID < 0 ) 
		return RA_AOE_NOTENABLED;

	int sampleWidth      = pFormat->uBitsPerSample;
	ULONG32 sampleRate   = pFormat->ulSamplesPerSec;
	int numChannels      = pFormat->uChannels;
	m_wBlockSize         = m_ulBytesPerGran;  //pFormat->uMaxBlockSize;

	ULONG32 bufSize = 128;
	ULONG32 bytesPerBlock = m_wBlockSize; 
	while ( bufSize < 4096 )
	{
		bufSize *= 2;
	}

	m_ulFragSize = bufSize;

	snd_pcm_playback_params_t playback_params;
	memset( &playback_params, 0, sizeof(playback_params) );
	playback_params.fragment_size  = m_ulFragSize;
	playback_params.fragments_max  = -1;
	playback_params.fragments_room =  1;

	/* it's okay to fail, card may not handle fragment size */
	ioctl(m_wID, SND_PCM_IOCTL_PLAYBACK_PARAMS, &playback_params );

	snd_pcm_format_t format;
	memset( &format, 0, sizeof(format));

	if( sampleWidth == 16 )
	{
	    format.format = SND_PCM_SFMT_S16_LE;
	}
	else 
	{
	    format.format = SND_PCM_SFMT_U8;
	    m_uSampFrameSize /= 2;
	}

	format.channels		= numChannels;
	format.rate			= sampleRate;

	m_sample_rate		= sampleRate;
	m_num_channels		= numChannels;
	m_uSampFrameSize	= sampleWidth / 8;

	if(ioctl(m_wID, SND_PCM_IOCTL_PLAYBACK_FORMAT, &format) == -1)
	{
	    return (  m_wLastError = RA_AOE_NOTENABLED );
	}

	numChannels = format.channels;
	sampleRate  = format.rate;

	//
	// Verify that requested format was accepted by the audio device.
	//
	if ( numChannels != pFormat->uChannels )
		((HXAudioFormat*)pFormat)->uChannels = numChannels;
		
	if ( sampleRate != pFormat->ulSamplesPerSec )
		((HXAudioFormat*)pFormat)->ulSamplesPerSec = sampleRate;

	// Get the audio driver's buffer size for our rollback buffer
    snd_pcm_playback_info_t pinfo;
	memset( &pinfo, 0, sizeof( pinfo ) );

	if(ioctl(m_wID, SND_PCM_IOCTL_PLAYBACK_INFO, &pinfo) != -1)
		m_ulDeviceBufferSize = pinfo.buffer_size;	

	return RA_AOE_NOERR;
}

HX_RESULT CAudioOutQNX::_Imp_CheckFormat
( 
	const HXAudioFormat* pFormat 
)
{

	// QNX audio driver can do all formats that we our
	// currently interested in. However, we should check
	// for valid inputs.
	if ( pFormat->uChannels != 1 && pFormat->uChannels != 2 )
		return HXR_FAILED;
	if ( pFormat->uBitsPerSample != 8 && pFormat->uBitsPerSample != 16 )
		return HXR_FAILED;

	// Ask driver later
#if 0
  /*No reason why the driver won't accept other sampling rates...*/
	if ( pFormat->ulSamplesPerSec != 8000 && pFormat->ulSamplesPerSec != 9600  &&
	     pFormat->ulSamplesPerSec != 11025 && pFormat->ulSamplesPerSec != 16000  &&
	     pFormat->ulSamplesPerSec != 18900 && pFormat->ulSamplesPerSec != 22050  &&
	     pFormat->ulSamplesPerSec != 32000 && pFormat->ulSamplesPerSec != 44100  &&
	     pFormat->ulSamplesPerSec != 48000 )
		return HXR_FAILED;
#endif

	return HXR_OK;
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::_Imp_GetCurrentTime
 *      Purpose:
 *              Get the current time from the audio device.
 *		We added this to support the clock available in the
 *		Window's audio driver.
 */
HX_RESULT CAudioOutQNX::_Imp_GetCurrentTime ( ULONG32& ulCurrentTime )
{

    ULONG32 ulTime   = 0;
    ULONG32 ulBytes  = GetPlaybackBytes();

	ulBytes += m_ulPauseBytes;
    
    ulTime = (UINT32)((  (double)(ulBytes/m_uSampFrameSize)/(double)m_sample_rate) * 1000 / m_num_channels);
    
    //Not used anywhere but belongs to CHXAudioDevice so we must set it.
    m_ulCurrentTime  = ulTime;

    //Set the answer.
    ulCurrentTime = ulTime;

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::_Imp_GetAudioFd
 *      Purpose:
 */
INT16 CAudioOutQNX::_Imp_GetAudioFd()
{
    return m_wID;
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::DoTimeSyncs
 *      Purpose:
 *		Manual time syncs! Fork!
 */
void CAudioOutQNX::DoTimeSyncs()
{
    ReschedPlaybackCheck();
	OnTimeSync();

    return;
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::GetPlaybackBytes
 *      Purpose:
 *		Get the number of bytes played since last open() was
 *		called. This ioctl() returns funky values sometimes?!@%
 */
ULONG32 CAudioOutQNX::GetPlaybackBytes()
{

	snd_pcm_playback_status_t info;
	memset( &info,0, sizeof(info));

	if ( ioctl (m_wID, SND_PCM_IOCTL_PLAYBACK_STATUS, &info) != -1 )
		return info.scount;

	// If ioctl failed, just guess the value
    int bytes = m_ulTotalWritten - m_ulGranularity / 2;
    if (bytes < 0) 
		bytes = 0;

	return (ULONG32) bytes; 
}

ULONG32 CAudioOutQNX::_GetPlaybackBuffer( )
{
	return( m_ulTotalWritten - GetPlaybackBytes( ) );
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::ReschedPlaybackCheck()
 *      Purpose:
 *		Reschedule playback callback.
 */
HX_RESULT CAudioOutQNX::ReschedPlaybackCheck()
{
    HX_RESULT theErr = HXR_OK;
    if (m_bCallbackPending)
		return theErr;
    /* Put this back in the scheduler.
     */
    HXPlaybackCountCb* pCallback = 0;
    pCallback = new HXPlaybackCountCb;
    if (pCallback)
    {
        *m_pPlaybackCountCBTime += (int) (1000 * m_ulGranularity);
        pCallback->m_pAudioDeviceObject = this;
        m_bCallbackPending = TRUE;
        m_PendingCallbackID = m_pScheduler->AbsoluteEnter(pCallback,
                        *((HXTimeval*) m_pPlaybackCountCBTime));
    }
    else
    {
        theErr = HXR_OUTOFMEMORY;
    }

    return HXR_OK;
}

UINT16	CAudioOutQNX::_NumberOfBlocksRemainingToPlay(void)
{
    UINT32 			bytesBuffered = 0;
    LISTPOSITION	i = m_pWriteList->GetHeadPosition();

    while (i)
    {
		bytesBuffered += ((IHXBuffer *)m_pWriteList->GetAt(i)) -> GetSize();
		m_pWriteList->GetNext(i);
    }
    
    bytesBuffered += (m_ulTotalWritten - GetPlaybackBytes());

    return bytesBuffered / m_wBlockSize + 1;
}


// CAudioOutQNX::HXPlaybackCountCb

CAudioOutQNX::HXPlaybackCountCb::HXPlaybackCountCb(BOOL timed) :
     m_lRefCount (0)
    ,m_pAudioDeviceObject (0)
    ,m_timed(timed)
{
}

CAudioOutQNX::HXPlaybackCountCb::~HXPlaybackCountCb()
{
}

/*
 * IUnknown methods
 */
/////////////////////////////////////////////////////////////////////////
//      Method:
//              IUnknown::QueryInterface
//      Purpose:
//              Implement this to export the interfaces supported by your 
//              object.
//
STDMETHODIMP CAudioOutQNX::HXPlaybackCountCb::QueryInterface
(	REFIID riid, void** ppvObj )
{
    if (IsEqualIID(riid, IID_IHXCallback))
    {
        AddRef();
        *ppvObj = (IHXCallback*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

/////////////////////////////////////////////////////////////////////////
//      Method:
//              IUnknown::AddRef
//      Purpose:
//              Everyone usually implements this the same... feel free to use
//              this implementation.
//
STDMETHODIMP_(ULONG32) CAudioOutQNX::HXPlaybackCountCb::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

/////////////////////////////////////////////////////////////////////////
//      Method:
//              IUnknown::Release
//      Purpose:
//              Everyone usually implements this the same... feel free to use
//              this implementation.
//
STDMETHODIMP_(ULONG32) CAudioOutQNX::HXPlaybackCountCb::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

/*
 *      IHXPlaybackCountCb methods
 */
STDMETHODIMP CAudioOutQNX::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;
}

/************************************************************************
 *  Method:
 *              CAudioOutQNX::BuffersEmpty
 *      Purpose:
 */
BOOL CAudioOutQNX::BuffersEmpty()
{
    snd_pcm_playback_status_t info;

    if ( -1 == ioctl(m_wID, SND_PCM_IOCTL_PLAYBACK_STATUS, &info) )
		return FALSE;

    if ( info.queue )
		return FALSE;

    return TRUE;
}



void CAudioOutQNX::OpenMixer()
{
	int								i;
	struct snd_mixer_info_t 		info;
	struct snd_mixer_channel_info_t cinfo;

    //
    // return if the mixer is already opened
    //
    if (m_bMixerPresent)
		return;

    mixm_wID = open ( m_DevCtlName, O_RDWR );

	if ( -1 == ioctl( mixm_wID, SND_MIXER_IOCTL_INFO, &info ) )
	{
		CloseMixer( );
		return;
	}
    
    if (mixm_wID > 0)
    {
		/* find pcm channel */
		memset( &cinfo, 0, sizeof( cinfo ) );
		for ( i = 0; i < info.channels; i++ )
		{
			cinfo.channel = i;
			if ( -1 == ioctl( mixm_wID, SND_MIXER_IOCTL_CHANNEL_INFO, &cinfo ) )
			{
				continue;
			}
			if ( 0 == strcmp( (char *)cinfo.name, SND_MIXER_ID_PCM ) ) 
			{
				m_wPCMChannel = i;
				break;
			}
		}

	}

	if ( m_wPCMChannel > 0 )
	{
		m_bMixerPresent = 1;
    }
    else
    {
		CloseMixer( );
		m_bMixerPresent = 0;
    }
}


void CAudioOutQNX::CloseMixer()
{
    // Close the mixer device.
    if ( mixm_wID >= 0 ) 
    {
		close ( mixm_wID );
		mixm_wID = -1;
    }
}

⌨️ 快捷键说明

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