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

📄 audqnx.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: audqnx.cpp,v 1.3.42.1 2004/07/09 02:01:43 hubbe 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 ***** *//******************************************************************* * *	audqnx.cpp * *	CLASS: CAudioOutQNX *	 *	DESCRIPTION: Class implementation for QNX-specific audio devices  *	 *******************************************************************/#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <sys/ioctl.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/asound.h>#include "hxcom.h"#include "hxresult.h"#include "hxengin.h"#include "ihxpckts.h"#include "hxslist.h"#include "hxstrutl.h"#include "timeval.h"#include "audqnx.h"#include "hxaudses.h"#include "hxtick.h"#include "chxpckts.h"#include "debug.h"struct IHXCallback;CAudioOutQNX::CAudioOutQNX() :	m_wID( -1 ),	mixm_wID( -1 ),	m_wPCMChannel( -1 ),	m_wState( RA_AOS_CLOSED ),	m_wLastError( RA_AOE_NOERR ),	m_bMixerPresent(FALSE),	m_wBlockSize(0),	m_ulLastNumBytes (0),	m_ulBytesRemaining(0),	m_ulTotalWritten(0),	m_bFirstWrite (TRUE),	m_pPlaybackCountCBTime(0),	m_PendingCallbackID (0),	m_bCallbackPending(FALSE),	m_paused(FALSE),	m_pWriteList(NULL),	m_last_audio_time(0),	m_ulPauseBytes(0),    m_ulDeviceBufferSize(0),    m_pRollbackBuffer(NULL){	// Use Photon registry later 	// Get AUDIODEV environment var to find audio device of choice	char *adev = (char*)getenv( "AUDIODEV" ); /* Flawfinder: ignore */	char *mdev = (char*)getenv( "MIXERDEV" ); /* Flawfinder: ignore */	// Use defaults if no environment variable is set.	if ( adev )	{	    SafeStrCpy( m_DevName, adev, DEVICE_NAME_SIZE );	}	else	{	    SafeStrCpy( m_DevName, "/dev/pcm00", DEVICE_NAME_SIZE );	// default	}	if ( mdev )	{	    SafeStrCpy( m_DevCtlName, mdev, DEVICE_NAME_SIZE );	}	else	{	    SafeStrCpy( m_DevCtlName, "/dev/mixer00", DEVICE_NAME_SIZE );   // default for volume	}	m_pPlaybackCountCBTime = new Timeval;	m_pWriteList = new CHXSimpleList();}CAudioOutQNX::~CAudioOutQNX(){    // Check to make sure device is closed    if ( m_wState != RA_AOS_CLOSED )     {        HX_ASSERT( "Device not closed in dtor." == NULL );		_Imp_Close();    } 	HX_RELEASE( m_pScheduler );    //Just in case it isn't empty at this point.    while( m_pWriteList && !m_pWriteList->IsEmpty() )    {        IHXBuffer* pBuffer = (IHXBuffer *)(m_pWriteList->RemoveHead());        HX_RELEASE( pBuffer );    }	HX_DELETE( m_pWriteList );	HX_VECTOR_DELETE( m_pRollbackBuffer );}UINT16 CAudioOutQNX::_Imp_GetVolume(){	struct snd_mixer_channel_direction_t cdata;    if (!m_bMixerPresent)		OpenMixer();    if ( !m_bMixerPresent ) 		return m_uCurVolume;	cdata.channel = m_wPCMChannel;	if ( ioctl( mixm_wID, SND_MIXER_IOCTL_CHANNEL_OREAD, &cdata ) == -1 )		return (0);	m_uCurVolume = cdata.volume ; 	return m_uCurVolume;}HX_RESULT CAudioOutQNX::_Imp_SetVolume( UINT16 uVolume ){	struct snd_mixer_channel_direction_t cdata;    if (!m_bMixerPresent)		OpenMixer();    	if ( !m_bMixerPresent ) 		return RA_AOE_NOERR;	cdata.channel = m_wPCMChannel;	if ( ioctl( mixm_wID, SND_MIXER_IOCTL_CHANNEL_OREAD, &cdata ) == -1 )		return ( m_wLastError = RA_AOE_NOTSUPPORTED );	cdata.volume  = uVolume;	if ( ioctl( mixm_wID, SND_MIXER_IOCTL_CHANNEL_OWRITE, &cdata ) == -1 )		return ( m_wLastError = RA_AOE_NOTSUPPORTED );	return RA_AOE_NOERR;}BOOL CAudioOutQNX::_Imp_SupportsVolume(){	return TRUE;}HX_RESULT CAudioOutQNX:: _Imp_Open ( const HXAudioFormat* pFormat ){printf( "_imp_open\n" );	m_ulLastTimeChecked = (UINT32) -1;	m_ulLastTimeReturned = 0;	// Get the core scheduler interface; Use this to schedule polling	// the audio device for number of bytes played.#if 0	if ( m_pOwner )	{		m_pOwner->GetScheduler( &m_pScheduler );		m_pScheduler->AddRef();	}#else    // Get the core scheduler interface; Use this to schedule polling    // the audio device for number of bytes played.    if ( m_pContext )    {		m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler );    }#endif	// Check state. Could already be opened.	if ( m_wState == RA_AOS_OPEN_PAUSED || m_wState == RA_AOS_OPEN_PLAYING ||		m_wState == RA_AOS_OPENING )		return RA_AOE_NOERR;	// Open audio device.	if ( m_wID < 0 )		m_wID = open ( m_DevName, O_WRONLY | O_NONBLOCK );	if ( m_wID < 0 )		return ( m_wLastError = RA_AOE_BADOPEN );	m_wBlockSize = m_ulBytesPerGran;  //pFormat->uMaxBlockSize;	m_uSampFrameSize = pFormat->uBitsPerSample / 8;	// Set device state	m_wState = RA_AOS_OPENING;	// Configure the audio device.	AUDIOERROR iVal = SetDeviceConfig( pFormat );	if (iVal != RA_AOE_NOERR) 	{		close ( m_wID );		m_wID = -1;		return iVal;	}	// Find out if mixer is there.. the mixer controls volume.	// If there is no mixer device, then we handle volume manually by	// multiplying the samples by the volume level in the Write() method.	if (!m_bMixerPresent)		OpenMixer();		IHXAsyncIOSelection* pAsyncIO = NULL;	if( HXR_OK == m_pContext->QueryInterface(IID_IHXAsyncIOSelection, (void**)&pAsyncIO))	{	    pAsyncIO->Add(new HXPlaybackCountCb(FALSE), m_wID, PNAIO_WRITE);		HX_RELEASE( pAsyncIO );	}     	HX_ASSERT( m_ulDeviceBufferSize != 0 );	if( NULL == m_pRollbackBuffer)	{		m_pRollbackBuffer = new UCHAR[m_ulDeviceBufferSize];		memset( m_pRollbackBuffer, '0', m_ulDeviceBufferSize );	}	return RA_AOE_NOERR;}HX_RESULT CAudioOutQNX::_Imp_Close(){printf( "_imp_close\n" );	m_wState = RA_AOS_CLOSING;	/* reset pause offset */	m_ulPauseBytes = 0;	_Imp_Reset( );	// Close the audio device.	if ( m_wID >= 0 ) 	{		close ( m_wID );		IHXAsyncIOSelection* pAsyncIO;		if( HXR_OK == m_pContext->QueryInterface(IID_IHXAsyncIOSelection, (void**)&pAsyncIO))        {	    	pAsyncIO->Remove(m_wID, PNAIO_WRITE);	    	pAsyncIO->Release();		}		m_wID = -1;	}    CloseMixer();	m_wState = RA_AOS_CLOSED;	// Remove callback from scheduler	if (m_bCallbackPending)	{	    m_pScheduler->Remove(m_PendingCallbackID);	    m_bCallbackPending = FALSE;	}	HX_VECTOR_DELETE( m_pRollbackBuffer );	return RA_AOE_NOERR;}HX_RESULT CAudioOutQNX::_Imp_Write ( const HXAudioData* pAudioOutHdr ){    IHXBuffer*	pBuffer		= NULL;	UCHAR*		pData		= 0;	ULONG32		ulBufLen	= 0;	// Schedule callbacks	if ( m_bFirstWrite && pAudioOutHdr)	{  	    m_bFirstWrite = FALSE;	    /*  Initialize the playback callback time. */	    HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();	    m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;	    m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;	    /*  Scheduler playback callback. */    	ReschedPlaybackCheck();	}    if ( m_paused )	{		if ( !pAudioOutHdr )			return RA_AOE_NOERR;		IHXBuffer* pNewBuffer = new CHXBuffer();		pNewBuffer->Set(pAudioOutHdr->pData->GetBuffer(),				pAudioOutHdr->pData->GetSize());		pNewBuffer->AddRef();		m_pWriteList->AddTail(pNewBuffer);	    return RA_AOE_NOERR;	}	BOOL bWroteSomething = TRUE;	do 	{		bWroteSomething = FALSE;	    if(m_pWriteList->GetCount() <= 0)	    {			if(!pAudioOutHdr)			    return RA_AOE_NOERR;			pData = (UCHAR*)pAudioOutHdr->pData->GetBuffer();			ulBufLen = pAudioOutHdr->pData->GetSize();	    }	    else	    {			if(pAudioOutHdr)			{			    IHXBuffer* pNewBuffer = new CHXBuffer();			    pNewBuffer->Set(pAudioOutHdr->pData->GetBuffer(),					    pAudioOutHdr->pData->GetSize());			    m_pWriteList->AddTail(pNewBuffer);			    pNewBuffer->AddRef();			}		pBuffer = (IHXBuffer*)m_pWriteList->RemoveHead();		pData = pBuffer->GetBuffer();		ulBufLen = pBuffer->GetSize();	    }		// Write audio data to device.		int		count = 0;		count = write(m_wID, pData, ulBufLen);		if ( count == -1 )		{			// Rebuffer the data			IHXBuffer* pNewBuffer = new CHXBuffer( );            pNewBuffer->AddRef( );			pNewBuffer->Set( pData, ulBufLen );			m_pWriteList->AddHead( pNewBuffer );		}		// anything that is left over must be added to the write list at 		// the beginning		if (count != -1 && count != ulBufLen) 		{ 			// replace the extra data in the writelist			IHXBuffer* pNewBuffer = new CHXBuffer();			pNewBuffer->Set(pData + count, ulBufLen - count);			m_pWriteList->AddHead(pNewBuffer);			pNewBuffer->AddRef();		}		if (count != -1)		{			bWroteSomething = TRUE;			m_ulTotalWritten += count;            // If we wrote to the device we need to keep a copy of the             // data our device buffer. We use this to 'rewind' the data            // in case we get paused.            // If we could write ulCount without blocking then there was at             // least that much room in the device and since m_pRollbackBuffer            // is as large as the devices buffer, we can safely shift and copy.            // Add the new stuff to the end pushing the rest of the data forward.                                                // Throw an assert here                        HX_ASSERT(count <= m_ulDeviceBufferSize);                        // Now protect against a crash                        if (count > m_ulDeviceBufferSize) count = m_ulDeviceBufferSize;            memmove( m_pRollbackBuffer, m_pRollbackBuffer+count, m_ulDeviceBufferSize-count);            memcpy( m_pRollbackBuffer+m_ulDeviceBufferSize-count, pData, count ); /* Flawfinder: ignore */		}		HX_RELEASE( pBuffer );		pBuffer = NULL;		pAudioOutHdr = NULL; // Don't add the same buffer again	} while( bWroteSomething );	return RA_AOE_NOERR;}HX_RESULT CAudioOutQNX::_Imp_Seek(ULONG32 ulSeekTime){    return HXR_OK;}HX_RESULT CAudioOutQNX::_Imp_Pause(){    m_paused = TRUE;		// Find out how much we have left in the device's buffer.	int pause_bytes = GetPlaybackBytes( );	ULONG32 ulNumBytesToRewind = m_ulTotalWritten - pause_bytes;	// Reset player and discard all the data in the device's buffer	if( _Imp_Reset() != RA_AOE_NOERR )	{	    //We will just ignore it. That means the buffer will just drain	    //and we will hear it again when they unpause.	}	// Add it to the front of the write buffer.	IHXBuffer* pNewBuffer = new CHXBuffer();

⌨️ 快捷键说明

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