audqnx.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:24k
- /* ***** 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_openn" );
- 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_closen" );
- 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();
- // Make sure we only deal with full samples. Bytes-per-sample*num-channels.
- int nRem = ulNumBytesToRewind % (m_uSampFrameSize * m_num_channels);
- ulNumBytesToRewind -= nRem;
- pNewBuffer->Set( m_pRollbackBuffer+m_ulDeviceBufferSize-ulNumBytesToRewind, ulNumBytesToRewind );
- m_pWriteList->AddHead(pNewBuffer);
- 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;
- }
- }