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

📄 audaix.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: audaix.cpp,v 1.2.42.1 2004/07/09 02:01:42 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 ***** *//******************************************************************* *	audaix.cpp * *	CLASS: CAudioOutAIX *	 *	DESCRIPTION: AIX & UMS specific audio class implementation *    *******************************************************************/#include <signal.h>		// for  getenv()#include <stdio.h>#include <stdlib.h>		// for  getenv()#include <math.h>#include <sys/types.h>#include <stropts.h>		// for I_FLUSH ioctl#include <sys/conf.h>#include <sys/stat.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/audio.h>#include "hxcom.h"#include "hxresult.h"#include "hxengin.h"#include "ihxpckts.h"   // for IHXBuffer #include "hxslist.h"#include "timeval.h"#include "audaix.h"#include "hxaudses.h"#include "hxtick.h"#include "chxpckts.h"#include "debug.h"#include "hxstrutl.h"#include <UMSBAUDDevice.xh>#include <UMSAudioDevice.xh>#include <UMSAudioTypes.xh>struct IHXCallback;  // forward declaration needed for callback.// One and ONLY one of the following must be uncommented.  They determine the// strategy used to determine the elaped time. The first is the preferred.#define AIX_TIME_BYTES_WRITTEN         // function of bytes written vrs bytes in buffer.//**********************************************************************//  constants.//// in UMS, balance is really an initial pan setting. // -100 = hard left, 0 is centered, 100 = hard rightstatic const LONG32   lDefaultBalance = 0;   static const LONG32   lDefaultVolume = 50;   // UMS range is 0..100static LONG32   zlCurrentVolume = 50;   // UMS range is 0..100// this is sufficient for PCI devices, for microchannel devices, set the// envar AUDIODEV to "/dev/maud0".static const char *   szDefaultPortFilename = "/dev/paud0";static const char *   moduleName = "CAudioOutAIX"; // this will point to the SOM environment needed by the UMS subsystemstatic Environment*   gpSomEnvironment                  = NULL;// static local routines, used to translate UMS message code to RMA types.static const char *   getUMSAudioDeviceError( UMSAudioDevice_ReturnCode );static audio_error    UMSErrorCodeToRACode( UMSAudioDevice_ReturnCode ); CAudioOutAIX::CAudioOutAIX()   : mixm_wID( -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(NULL),    m_PendingCallbackID (0),    m_bCallbackPending(FALSE),    m_paused(FALSE),    m_pWriteList(NULL),    m_lLeftGain(100),    m_lRightGain(100){      // set up UMS environment.    gpSomEnvironment = somGetGlobalEnvironment();    HX_ASSERT( gpSomEnvironment );    m_pAudioDevice   = new UMSBAUDDevice();        // 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.    m_DevName[26]    = NULL;    m_DevCtlName[26] = NULL;    if (adev && strlen(adev) > 0)        SafeStrCpy(m_DevName, adev, 26);    else        SafeStrCpy(m_DevName, szDefaultPortFilename, 26);    m_pPlaybackCountCBTime = new Timeval;    if (mdev && strlen(mdev) > 0)        SafeStrCpy(m_DevCtlName, mdev, 26);    else        SafeStrCpy(m_DevCtlName, szDefaultPortFilename, 26);        m_pWriteList = new CHXSimpleList();    // now configure our device.    m_pAudioDevice->set_audio_format_type  ( gpSomEnvironment, "PCM" );    m_pAudioDevice->set_number_format      ( gpSomEnvironment, 					     "TWOS_COMPLEMENT" );    m_pAudioDevice->set_byte_order         ( gpSomEnvironment, "MSB" );     m_pAudioDevice->set_time_format        ( gpSomEnvironment, 					     UMSAudioTypes_Msecs );         m_pAudioDevice->set_balance   ( gpSomEnvironment, lDefaultBalance );      m_pAudioDevice->set_volume    ( gpSomEnvironment, zlCurrentVolume );    m_pAudioDevice->enable_output ( gpSomEnvironment, "LINE_OUT", 				    &m_lLeftGain, &m_lRightGain  );}CAudioOutAIX::~CAudioOutAIX(){    if ( m_wState != RA_AOS_CLOSED )       {	_Imp_Close();	m_wState = RA_AOS_CLOSED;      }        mixm_wID = -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;        if (m_pScheduler)       m_pScheduler->Release();        m_PendingCallbackID = 0;    m_bCallbackPending = TRUE;         while(!m_pWriteList->IsEmpty())      {	IHXBuffer* pBuffer = (IHXBuffer*)m_pWriteList->RemoveHead();	HX_RELEASE(pBuffer);      }    HX_DELETE(m_pWriteList);        delete m_pAudioDevice;}/* *    I do not open /dev/mixer to control volume, the volume is scaled *    by the UMS device. *    The device's volume has a range of 0..100. */UINT16 CAudioOutAIX::_Imp_GetVolume(){    long volume;    m_pAudioDevice->get_volume( gpSomEnvironment, &volume );    return zlCurrentVolume;    return (UINT16)volume;}HX_RESULT CAudioOutAIX::_Imp_SetVolume( const UINT16 uVolume ){    m_pAudioDevice->set_volume( gpSomEnvironment, (long)uVolume );    zlCurrentVolume = uVolume;    return RA_AOE_NOERR;}/* *  All UMS audio devices support volume. */BOOL CAudioOutAIX::_Imp_SupportsVolume(){    return TRUE;}HX_RESULT CAudioOutAIX:: _Imp_Open( const HXAudioFormat* pFormatSupplied ){    if( pFormatSupplied != NULL )      m_pAudioFormat = pFormatSupplied;        HX_ASSERT( m_pAudioFormat != NULL );         // 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 );    }    // 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;        m_ulBlocksProcessed = 0;    UMSAudioDevice_ReturnCode retCode =        m_pAudioDevice->open( gpSomEnvironment, m_DevName, "PLAY", 0 );         if( retCode != UMSAudioDevice_Success )       {        return HXR_FAILED;      }        m_wBlockSize = m_ulBytesPerGran;  //m_pAudioFormat->uMaxBlockSize;    m_uSampFrameSize = m_pAudioFormat->uBitsPerSample / 8;        // Set device state    m_wState = RA_AOS_OPENING;        // Configure the audio device.    AUDIOERROR iVal = SetDeviceConfig( m_pAudioFormat );        return RA_AOE_NOERR;}HX_RESULT CAudioOutAIX::_Imp_Close(){    m_wState = RA_AOS_CLOSED;        // this will force the player to play all remaining data.  If passed TRUE,     // the call will block until finished playing. Do we want to call this?    // m_pAudioDevice->play_remaining_data( gpSomEnvironment, TRUE );    _Imp_Write(NULL);        m_pAudioDevice->stop( gpSomEnvironment );    m_pAudioDevice->close( gpSomEnvironment );        // Remove callback from scheduler    if (m_bCallbackPending)      {	m_pScheduler->Remove(m_PendingCallbackID);	m_bCallbackPending = FALSE;    }        return RA_AOE_NOERR;}HX_RESULT CAudioOutAIX::_Imp_Write( const HXAudioData* pAudioOutHdr ){    IHXBuffer* pBuffer = NULL;    UCHAR* pData = NULL;    UMSAudioTypes_Buffer adBuffer;    UINT32* pTimeStamp = NULL;        if ( m_bFirstWrite && pAudioOutHdr)    {        /*  Initialize the playback callback time. */        HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();        m_pPlaybackCountCBTime->tv_sec = lTime.tv_sec;        m_pPlaybackCountCBTime->tv_usec = lTime.tv_usec;	m_bFirstWrite = FALSE;	ReschedPlaybackCheck();    }    if (pAudioOutHdr)      {        ++m_ulBlocksProcessed ; 		DPRINTF(D_INFO, ("_Imp_Write: buf len in milli-seconds: %lu\n",			 ((ULONG32) (( 1000.0				       / (m_num_channels * m_uSampFrameSize * m_sample_rate))				     *  pAudioOutHdr->pData->GetSize()))));      }        // If we are paused, just add the block to the end of the WriteList.    if (m_paused)    {	if (!pAudioOutHdr)	    return m_wLastError = 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;    do {        bWroteSomething = FALSE;	if(m_pWriteList->GetCount() <= 0)	{	    if(!pAudioOutHdr)		return  RA_AOE_NOERR;	    	    pData = (UCHAR*)pAudioOutHdr->pData->GetBuffer();	    adBuffer._length = pAudioOutHdr->pData->GetSize();	}	else	{	    if (pAudioOutHdr)	    {		IHXBuffer* pNewBuffer = new CHXBuffer();		pNewBuffer->AddRef();		pNewBuffer->Set(pAudioOutHdr->pData->GetBuffer(),				pAudioOutHdr->pData->GetSize());		m_pWriteList->AddTail(pNewBuffer);	    }	    pBuffer = (IHXBuffer*)m_pWriteList->RemoveHead();	    HX_ASSERT(pBuffer);	    pData = pBuffer->GetBuffer();	    adBuffer._length  = pBuffer->GetSize();	}            // Write audio data to device.        long	count = 0;        int         wrote;            adBuffer._buffer = pData;        adBuffer._maximum = adBuffer._length;            int     nBytesPerSample = (m_bits_per_sample/8)* m_num_channels;        long    lSamplesToWrite = adBuffer._length / nBytesPerSample;        long    lSamplesWritten =0;                int     transferredCount = adBuffer._length;        m_wLastError = RA_AOE_NOERR;  // less work this way.        UMSAudioDevice_ReturnCode retCode =             m_pAudioDevice->write( gpSomEnvironment, 				 &adBuffer,				 lSamplesToWrite,				 &lSamplesWritten );        switch(retCode)        {            case UMSAudioDevice_Success :    	    {	        int nBytesWritten = lSamplesWritten * nBytesPerSample;	        m_ulTotalWritten += nBytesWritten;	        	  	HX_ASSERT(lSamplesWritten <= lSamplesToWrite);	        if( lSamplesWritten == lSamplesToWrite ) 	        {  		    bWroteSomething = TRUE;	        }	        else                 {  	    	    /* requeue the balance. */		    long lSamplesToRequeue = lSamplesToWrite - lSamplesWritten;		    IHXBuffer* pNewBuffer = new CHXBuffer();		    pNewBuffer->AddRef();		    pNewBuffer->Set( adBuffer._buffer + nBytesWritten,				 adBuffer._length - nBytesWritten );		    m_pWriteList->AddHead(pNewBuffer);	        }	    }	    break;	    	    case UMSAudioDevice_DeviceError : // indicates EWOULDBLOCK	    case UMSAudioDevice_Preempted :	    case UMSAudioDevice_Interrupted :            {	        // just requeue the data	        IHXBuffer* pNewBuffer = new CHXBuffer();	        pNewBuffer->AddRef();	        pNewBuffer->Set( adBuffer._buffer, adBuffer._length );	        m_pWriteList->AddHead(pNewBuffer);	        break;            }	    	    default :  // failure!	        HX_ASSERT(FALSE);	        m_wLastError = UMSErrorCodeToRACode( retCode );        }  

⌨️ 快捷键说明

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