sfxDevice.cpp

Engine/source/sfx/sfxDevice.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "sfx/sfxDevice.h"
 25#include "sfx/sfxBuffer.h"
 26#include "sfx/sfxVoice.h"
 27#include "sfx/sfxInternal.h"
 28#include "core/tAlgorithm.h"
 29#include "console/console.h"
 30#include "console/consoleTypes.h"
 31
 32
 33//-----------------------------------------------------------------------------
 34
 35SFXDevice::SFXDevice( const String& name, SFXProvider* provider, bool useHardware, S32 maxBuffers )
 36   :  mName( name ),
 37      mProvider( provider ),
 38      mUseHardware( useHardware ),
 39      mMaxBuffers( maxBuffers ),
 40      mCaps( 0 ),
 41      mStatNumBuffers( 0 ),
 42      mStatNumVoices( 0 ),
 43      mStatNumBufferBytes( 0 )
 44{
 45   AssertFatal( provider, "We must have a provider pointer on device creation!" );
 46
 47   VECTOR_SET_ASSOCIATION( mBuffers );
 48   VECTOR_SET_ASSOCIATION( mVoices );
 49
 50   SFXBuffer::smBufferDestroyedSignal.notify( this, &SFXDevice::_removeBuffer );
 51   SFXVoice::smVoiceDestroyedSignal.notify( this, &SFXDevice::_removeVoice );
 52
 53   Con::addVariable( "SFX::Device::numBuffers", TypeS32, &mStatNumBuffers );
 54   Con::addVariable( "SFX::Device::numVoices", TypeS32, &mStatNumVoices );
 55   Con::addVariable( "SFX::Device::numBufferBytes", TypeS32, &mStatNumBufferBytes );
 56}
 57
 58//-----------------------------------------------------------------------------
 59
 60SFXDevice::~SFXDevice()
 61{
 62   Con::removeVariable( "SFX::Device::numBuffers" );
 63   Con::removeVariable( "SFX::Device::numVoices" );
 64   Con::removeVariable( "SFX::Device::numBufferBytes" );
 65
 66   _releaseAllResources();
 67}
 68
 69//-----------------------------------------------------------------------------
 70
 71void SFXDevice::_releaseAllResources()
 72{
 73   using namespace SFXInternal;
 74
 75   // Kill the update thread, if there is one.
 76   // Do this first so that further buffer processing
 77   // can be done synchronously by us.
 78
 79   ThreadSafeRef< SFXUpdateThread> sfxThread = UPDATE_THREAD();
 80   if( sfxThread != NULL )
 81   {
 82      gUpdateThread = NULL; // Kill the global reference.
 83
 84      sfxThread->stop();
 85      sfxThread->triggerUpdate();
 86      sfxThread->join();
 87
 88      sfxThread = NULL;
 89   }
 90
 91   // Clean up voices.  Do this before cleaning up buffers so that
 92   // resources held by voices that are tied to resources held by buffers
 93   // get released properly.
 94
 95   SFXVoice::smVoiceDestroyedSignal.remove( this, &SFXDevice::_removeVoice );
 96   for( VoiceIterator voice = mVoices.begin();
 97        voice != mVoices.end(); voice++ )
 98      ( *voice )->destroySelf();
 99   mVoices.clear();
100
101   // Clean up buffers.
102
103   SFXBuffer::smBufferDestroyedSignal.remove( this, &SFXDevice::_removeBuffer );
104   for( BufferIterator buffer = mBuffers.begin();
105        buffer != mBuffers.end(); ++ buffer )
106      if( !( *buffer )->isDead() )
107         ( *buffer )->destroySelf();
108   mBuffers.clear();
109
110   // Flush all asynchronous requests.
111
112   THREAD_POOL().flushWorkItems();
113
114   // Clean out the buffer update list and kill
115   // all buffers that surfaced on the dead list.
116   // Now the sound buffers are really gone.
117
118   UPDATE_LIST().process();
119   PurgeDeadBuffers();
120
121   // Clean out stats.
122
123   mStatNumBuffers = 0;
124   mStatNumVoices = 0;
125   mStatNumBufferBytes = 0;
126}
127
128//-----------------------------------------------------------------------------
129
130void SFXDevice::update()
131{
132   using namespace SFXInternal;
133
134   // If we don't have an update thread, do the
135   // updates now on the main thread.
136
137   if( !UPDATE_THREAD() )
138      UPDATE_LIST().process( MAIN_THREAD_PROCESS_TIMEOUT );
139      
140   // Clean out buffers that have surfaced on the dead
141   // buffer list.
142
143   PurgeDeadBuffers();
144}
145
146//-----------------------------------------------------------------------------
147
148void SFXDevice::_addBuffer( SFXBuffer* buffer )
149{
150   AssertFatal( buffer, "SFXDevice::_addBuffer() - Got a null buffer!" );
151   
152   // Register the buffer.
153   
154   mBuffers.push_back( buffer );
155   mStatNumBuffers ++;
156   mStatNumBufferBytes += buffer->getMemoryUsed();
157   
158   // Start loading the buffer.
159
160   buffer->load();
161}
162
163//-----------------------------------------------------------------------------
164
165void SFXDevice::_removeBuffer( SFXBuffer* buffer )
166{
167   AssertFatal( buffer, "SFXDevice::_removeBuffer() - Got a null buffer!" );
168
169   BufferIterator iter = T3D::find( mBuffers.begin(), mBuffers.end(), buffer );
170   if( iter != mBuffers.end() )
171   {
172      SFXBuffer* curBuf = *iter;
173
174      mStatNumBufferBytes -= curBuf->getMemoryUsed();
175      mStatNumBuffers --;
176      
177      mBuffers.erase( iter );
178   }
179}
180
181//-----------------------------------------------------------------------------
182
183void SFXDevice::_addVoice( SFXVoice* voice )
184{
185   AssertFatal( voice, "SFXDevice::_addVoice() - Got a null voice!" );
186   using namespace SFXInternal;
187
188   // Bind the voice to its buffer.  This is deferred up to here in order
189   // to only bind voices that have been successfully constructed.
190
191   voice->_attachToBuffer();
192   
193   // Register the voice.
194
195   mVoices.push_back( voice );
196   mStatNumVoices ++;
197}
198
199//-----------------------------------------------------------------------------
200
201void SFXDevice::_removeVoice( SFXVoice* voice )
202{
203   AssertFatal( voice, "SFXDevice::_removeVoice() - Got null voice!" );
204
205   VoiceIterator iter = T3D::find( mVoices.begin(), mVoices.end(), voice );
206   if( iter != mVoices.end() )
207   {
208      mStatNumVoices --;
209      mVoices.erase( iter );
210   }
211}
212