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

📄 audlinux_oss.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: audlinux_oss.cpp,v 1.6.18.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 ***** */#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <errno.h>#include <sys/ioctl.h>#include <stdio.h> #include <math.h> #include "ihxpckts.h"#include "hxtick.h"#include "hxprefs.h"#include "timeval.h"#include "hxthread.h"#include "audlinux_oss.h"#include "hxstrutl.h"#include "hxprefutil.h"//we can't set the PCM volume on the PowerPC. The sound driver//only lets up set the master volume.#ifdef __powerpc__#   define HX_VOLUME  SOUND_MIXER_VOLUME#else#   define HX_VOLUME  SOUND_MIXER_PCM#endif//------------------------------------------// Ctors and Dtors.//------------------------------------------CAudioOutLinux::CAudioOutLinux() :    CAudioOutUNIX(),    m_ulTickCount(0),    m_ulLastBytesPlayed(0),    m_ulLastTimeStamp(0),    m_ulPausePosition(0),    m_nDevID(NO_FILE_DESCRIPTOR),    m_nMixerID(NO_FILE_DESCRIPTOR),    m_bGetODelayFailed(TRUE),    m_bGetOSpaceFailed(FALSE),    m_bTestGetODelay(TRUE){};CAudioOutLinux::~CAudioOutLinux(){    //The mixer is opened independently of the audio device. Make sure     //it is closed.    _CloseMixer();};//-------------------------------------------------------// These Device Specific methods must be implemented // by the platform specific sub-classes.//-------------------------------------------------------INT16 CAudioOutLinux::_Imp_GetAudioFd(void){    return m_nDevID;}//Devic specific method to set the audio device characteristics. Sample rate,//bits-per-sample, etc.//Method *must* set member vars. m_unSampleRate and m_unNumChannels.HX_RESULT CAudioOutLinux::_SetDeviceConfig( const HXAudioFormat* pFormat ){    if ( m_nDevID < 0 )        return RA_AOE_DEVNOTOPEN;    m_wBlockSize = m_ulBytesPerGran;    //First, we want to determine the fragment size of the device buffer.    //We will let the device determine the number of fragments after we    //make sure that each fragment is no bigger than our block size.    //The minimum block size for OSS is 16 bytes and the max is 2^0xf.    //Basically, Log-base-two(m_wBlockSize)+1.    int nPower = 0x4;    while( (1<<nPower)<m_wBlockSize && nPower<0xf )    {         nPower++;    }    if( nPower > 4 )        nPower--;        //Frag info is 0xMMMMSSSS. Where    //    // MMMM is the total number of fragments. Set this to 7fff if you want    //      OSS to figure it out.    // SSSS is the size of each fragment. The size is 2^0xSSSS.    int nFragInfo = 0x7fff0000 | nPower;    //Now set the fragment size.    if (ioctl(m_nDevID, SNDCTL_DSP_SETFRAGMENT, &nFragInfo) == -1)    {        return (m_wLastError = RA_AOE_NOTENABLED);    }    //Now set the format. Either 8-bit or 16-bit audio is supported.    int      nSampleWidth  = pFormat->uBitsPerSample;    ULONG32  nSampleRate   = pFormat->ulSamplesPerSec;    int      numChannels   = pFormat->uChannels;    int      nFormat1      = 0;    int      nFormat2      = 0;        if( nSampleWidth == 16)    {        nFormat1 = nFormat2 = AFMT_S16_NE;    }    else    {        nFormat1 = nFormat2 = AFMT_U8;    }        if(ioctl(m_nDevID, SNDCTL_DSP_SETFMT, &nFormat1) == -1)    {        return (  m_wLastError = RA_AOE_NOTENABLED );    }    //Check and see if the device supports the format we tried to set.    //If it didn't take our only other option is unsigned 8 bit. So, if    //that is what the device returned just use it.    if(nFormat1!=nFormat2 && nFormat1 != AFMT_U8 )    {        //Just try to set AFMT_U8.        nFormat1 = AFMT_U8;        if(ioctl(m_nDevID, SNDCTL_DSP_SETFMT, &nFormat1) == -1)        {            return (  m_wLastError = RA_AOE_NOTENABLED );        }        if( nFormat1 != AFMT_U8 )        {            //No know format is supported.            return (  m_wLastError = RA_AOE_NOTENABLED );         }    }    //If we went to 8-bit then     if( nFormat1 == AFMT_U8 )    {        //AFMT_U8 is set.        nSampleWidth = 8;    }    m_uSampFrameSize = nSampleWidth/8;    if ( nSampleWidth != pFormat->uBitsPerSample )    {        ((HXAudioFormat*)pFormat)->uBitsPerSample = nSampleWidth;    }            // Set sampling rate, sample width, #channels.    //    // Make sure you set num channels before rate. If you don't it will    // screw up SBPro  devices. Your rate will actually be 1/2 of what    // you think it is.    //Set number of channels. Stereo or mono.    if (ioctl(m_nDevID, SOUND_PCM_WRITE_CHANNELS, &numChannels) == -1)    {        return ( m_wLastError = RA_AOE_NOTENABLED );    }    m_unNumChannels = numChannels;    if ( numChannels != pFormat->uChannels )    {        ((HXAudioFormat*)pFormat)->uChannels = numChannels;    }    //Set the sample rate.    if (ioctl(m_nDevID, SOUND_PCM_WRITE_RATE, &nSampleRate) == -1)    {        return ( m_wLastError = RA_AOE_NOTENABLED );    }    if (nSampleRate == 0)    {	/* 	 * Some drivers actually set the sample rate on the device, but	 * return 0 for the sample rate. On these platforms we just ignore	 * the return value and assume the sample rate is set to what was	 * requested.	 */	nSampleRate = pFormat->ulSamplesPerSec;    }    m_unSampleRate = nSampleRate;    if ( nSampleRate != pFormat->ulSamplesPerSec )    {        ((HXAudioFormat*)pFormat)->ulSamplesPerSec = nSampleRate;    }    //Find out if the user wants to support old OSS drivers that don't have,    //or support well, the iocls needed for good syncing.  SNDCTL_DSP_GETOSPACE and    //SNDCTL_DSP_GETODELAY.    IHXPreferences* pPreferences = NULL;    if( m_pContext && HXR_OK == m_pContext->QueryInterface( IID_IHXPreferences, (void **) &pPreferences))    {	UINT32 nOldOSS = 0;	if (HXR_OK == ReadPrefINT32(pPreferences, "SoundDriver", nOldOSS) &&	    (nOldOSS == 1))	{	    m_bGetODelayFailed = TRUE;	    m_bGetOSpaceFailed = TRUE;	    m_bTestGetODelay = FALSE;	}        HX_RELEASE( pPreferences );    }//for now, PowerPC linux doesn't support the following ioctl call//So, I will just make up some buffer size and live with it for//now. You won't be able to tell the difference until you turn//off threaded audio, then it will be block city!#ifndef __powerpc__      audio_buf_info getYourInfoHere;    if( !m_bGetOSpaceFailed )    {        //This call is to get how the device is set up after we have        //set the sample rate etc. We use this to set up the buffers        //we use for the fake pause/resume features.        if (ioctl(m_nDevID, SNDCTL_DSP_GETOSPACE, &getYourInfoHere) == -1)         {            m_wLastError = RA_AOE_NOTENABLED;            return m_wLastError;        }        m_ulDeviceBufferSize = getYourInfoHere.fragsize*getYourInfoHere.fragstotal;    }    else    {        //We don't have anyway to determine how big the buffer is.        //just guess I guess.        m_ulDeviceBufferSize = 8192*4;    }#else    m_ulDeviceBufferSize = 8192*4;#endif#ifdef _DEBUG    fprintf( stderr, "Device Configured:\n");    fprintf( stderr, "         Sample Rate: %d\n",  m_unSampleRate);    fprintf( stderr, "        Sample Width: %d\n",  nSampleWidth);    fprintf( stderr, "        Num channels: %d\n",  m_unNumChannels);    fprintf( stderr, "          Block size: %d\n",  m_wBlockSize);    fprintf( stderr, "  Device buffer size: %lu\n", m_ulDeviceBufferSize);    fprintf( stderr, "  Supports GETOSPACE: %d\n",  !m_bGetOSpaceFailed);    fprintf( stderr, "  Supports GETODELAY: %d\n",  !m_bGetODelayFailed);#endif    return RA_AOE_NOERR;}void CAudioOutLinux::_SyncUpTimeStamps(ULONG32 lCount){    int bytes2  = 0;    int theErr = -1;    if( m_bTestGetODelay || !m_bGetODelayFailed )    {        HX_ASSERT(m_nDevID );        theErr = ::ioctl(m_nDevID, SNDCTL_DSP_GETODELAY, &bytes2);    }    if( theErr != -1)    {	if (m_bTestGetODelay && (bytes2 != 0))	{	    // We've now seen SNDCTL_DSP_GETODELAY return	    // a non-zero value so we know it is working	    m_bTestGetODelay = FALSE;            m_bGetODelayFailed = FALSE;	}	if (!m_bTestGetODelay)	{	    m_ulLastBytesPlayed = (UINT64)(m_ulTotalWritten+lCount-bytes2);	    m_ulLastTimeStamp   = GetTickCount();	}    }    else    {        //so we don't try it again.        m_bGetODelayFailed = TRUE;	m_bTestGetODelay = FALSE;    }}//Device specific method to write bytes out to the audiodevice and return a//count of bytes written. HX_RESULT CAudioOutLinux::_WriteBytes( UCHAR* buffer, ULONG32 ulBuffLength, LONG32& lCount ){    HX_RESULT retCode = RA_AOE_NOERR;    if( m_nDevID < 0 )    {        retCode = RA_AOE_DEVNOTOPEN;    }    else    {        if( m_ulTickCount == 0 )            m_ulTickCount = GetTickCount();        lCount = ::write( m_nDevID, buffer, ulBuffLength);        if( lCount < 0 )        {            //Error occurred.            if( errno == EAGAIN )                retCode = RA_AOE_NOERR;            if( errno == EINTR )                retCode = RA_AOE_DEVBUSY;        }        else        {            _SyncUpTimeStamps(lCount);        }    }    return retCode;}//Device specific methods to open/close the mixer and audio devices.HX_RESULT CAudioOutLinux::_OpenAudio(){    HX_RESULT retCode = RA_AOE_NOERR;    //Set the tick count to zero    m_ulTickCount       = 0;    m_ulLastTimeStamp   = 0;    m_ulLastBytesPlayed = 0;    m_ulPausePosition   = 0;    //Check the environmental variable to let user overide default device.    char *pszOverrideName = getenv( "AUDIO" ); /* Flawfinder: ignore */    char szDevName[MAX_DEV_NAME]; /* Flawfinder: ignore */        // Use defaults if no environment variable is set.    if ( pszOverrideName && strlen(pszOverrideName)>0 )    {        SafeStrCpy( szDevName, pszOverrideName, MAX_DEV_NAME );    }    else    {

⌨️ 快捷键说明

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