3D Audio GSoC:
authorJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:21:43 +0000 (20:21 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:21:43 +0000 (20:21 +0000)
- Created Handle classes
- Changed Reference counting completely
- Fixing some streaming bugs
- Completely disabled OpenAL Buffered Factories (they were unused anyway)

23 files changed:
intern/audaspace/CMakeLists.txt
intern/audaspace/FX/AUD_DoubleReader.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/Python/AUD_PyAPI.cpp
intern/audaspace/Python/AUD_PyAPI.h
intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
intern/audaspace/intern/AUD_BufferReader.cpp
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_I3DDevice.h
intern/audaspace/intern/AUD_I3DHandle.h [new file with mode: 0644]
intern/audaspace/intern/AUD_IDevice.h
intern/audaspace/intern/AUD_IHandle.h [new file with mode: 0644]
intern/audaspace/intern/AUD_NULLDevice.cpp
intern/audaspace/intern/AUD_NULLDevice.h
intern/audaspace/intern/AUD_Reference.h
intern/audaspace/intern/AUD_ReferenceHandler.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerFactory.cpp
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
source/blender/blenkernel/intern/sound.c
source/gameengine/Ketsji/KX_SoundActuator.cpp

index ab88c9ecabd23601efdc48dc7c75f396825592ad..9c75cd67e6aca0e98761c37dc0ddbd85eed0057e 100644 (file)
@@ -87,8 +87,10 @@ set(SRC
        intern/AUD_FileFactory.cpp
        intern/AUD_FileFactory.h
        intern/AUD_I3DDevice.h
+       intern/AUD_I3DHandle.h
        intern/AUD_IDevice.h
        intern/AUD_IFactory.h
+       intern/AUD_IHandle.h
        intern/AUD_IReader.h
        intern/AUD_LinearResampleFactory.cpp
        intern/AUD_LinearResampleFactory.h
@@ -104,6 +106,7 @@ set(SRC
        intern/AUD_ReadDevice.cpp
        intern/AUD_ReadDevice.h
        intern/AUD_Reference.h
+       intern/AUD_ReferenceHandler.cpp
        intern/AUD_ResampleFactory.h
        intern/AUD_SequencerFactory.cpp
        intern/AUD_SequencerFactory.h
index 5d9ebbd618708fb9d133930f418bce75f148db92..2c39d193f67c02dabd767dbbbaa87691d8847aa4 100644 (file)
@@ -91,6 +91,8 @@ AUD_Specs AUD_DoubleReader::getSpecs() const
 
 void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer)
 {
+       eos = false;
+
        if(!m_finished1)
        {
                int len = length;
index 465ad5b5ae6f53fc28b606597f5ed6c7802ea7e8..f24d3aef4e2fa3d56f8d1012f50d8becb597ec84 100644 (file)
 #include <unistd.h>
 #endif
 
-#define AUD_OPENAL_CYCLE_BUFFERS 3
+/*struct AUD_OpenALBufferedFactory
+{
+       /// The factory.
+       AUD_IFactory* factory;
+
+       /// The OpenAL buffer.
+       ALuint buffer;
+};*/
+
+typedef std::list<AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> >::iterator AUD_HandleIterator;
+//typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
+
+
+/******************************************************************************/
+/*********************** AUD_OpenALHandle Handle Code *************************/
+/******************************************************************************/
+
+static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
+                                                                        "generated.";
+static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
+                                                                        "generated.";
+static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
+                                                                "queued to the source.";
+static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
+                                                                         "filled with data.";
 
-/// Saves the data for playback.
-struct AUD_OpenALHandle : AUD_Handle
+AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) :
+       m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
+       m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
+       m_device(device)
 {
-       /// Whether it's a buffered or a streamed source.
-       bool isBuffered;
+       AUD_DeviceSpecs specs = m_device->m_specs;
+       specs.specs = m_reader->getSpecs();
 
-       /// The reader source.
-       AUD_Reference<AUD_IReader> reader;
+       // OpenAL playback code
+       alGenBuffers(CYCLE_BUFFERS, m_buffers);
+       if(alGetError() != AL_NO_ERROR)
+               AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
 
-       /// Whether to keep the source if end of it is reached.
-       bool keep;
+       try
+       {
+               m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+               int length;
+               bool eos;
 
-       /// OpenAL sample format.
-       ALenum format;
+               for(int i = 0; i < CYCLE_BUFFERS; i++)
+               {
+                       length = m_device->m_buffersize;
+                       reader->read(length, eos, m_device->m_buffer.getBuffer());
+                       alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
+                                                length * AUD_DEVICE_SAMPLE_SIZE(specs),
+                                                specs.rate);
+                       if(alGetError() != AL_NO_ERROR)
+                               AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
+               }
 
-       /// OpenAL source.
-       ALuint source;
+               alGenSources(1, &m_source);
+               if(alGetError() != AL_NO_ERROR)
+                       AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
 
-       /// OpenAL buffers.
-       ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS];
+               try
+               {
+                       alSourceQueueBuffers(m_source, CYCLE_BUFFERS,
+                                                                m_buffers);
+                       if(alGetError() != AL_NO_ERROR)
+                               AUD_THROW(AUD_ERROR_OPENAL, queue_error);
+               }
+               catch(AUD_Exception&)
+               {
+                       alDeleteSources(1, &m_source);
+                       throw;
+               }
+       }
+       catch(AUD_Exception&)
+       {
+               alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
+               throw;
+       }
+       alSourcei(m_source, AL_SOURCE_RELATIVE, 1);
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
+{
+       if(m_status)
+       {
+               m_device->lock();
 
-       /// The first buffer to be read next.
-       int current;
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       m_device->m_playingSounds.remove(this);
+                       m_device->m_pausedSounds.push_back(this);
 
-       /// Whether the stream doesn't return any more data.
-       bool eos;
+                       alSourcePause(m_source);
 
-       /// The loop count of the source.
-       int loopcount;
+                       m_status = AUD_STATUS_PAUSED;
+                       m_device->unlock();
 
-       /// The stop callback.
-       stopCallback stop;
+                       return true;
+               }
 
-       /// Stop callback data.
-       void* stop_data;
-};
+               m_device->unlock();
+       }
 
-struct AUD_OpenALBufferedFactory
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
 {
-       /// The factory.
-       AUD_IFactory* factory;
+       if(m_status)
+       {
+               m_device->lock();
+
+               if(m_status == AUD_STATUS_PAUSED)
+               {
+                       m_device->m_pausedSounds.remove(this);
+                       m_device->m_playingSounds.push_back(this);
+
+                       m_device->start();
+                       m_status = AUD_STATUS_PLAYING;
+                       m_device->unlock();
+                       return true;
+               }
+
+               m_device->unlock();
+       }
+
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       if(m_status == AUD_STATUS_PLAYING)
+               m_device->m_playingSounds.remove(this);
+       else
+               m_device->m_pausedSounds.remove(this);
+
+       m_device->unlock();
+
+       alDeleteSources(1, &m_source);
+       if(!m_isBuffered)
+               alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
+
+       m_status = AUD_STATUS_INVALID;
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
+{
+       if(m_status)
+               return m_keep;
+
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_keep = keep;
+
+       m_device->unlock();
+
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       if(m_isBuffered)
+               alSourcef(m_source, AL_SEC_OFFSET, position);
+       else
+       {
+               m_reader->seek((int)(position * m_reader->getSpecs().rate));
+               m_eos = false;
+
+               ALint info;
+
+               alGetSourcei(m_source, AL_SOURCE_STATE, &info);
+
+               if(info != AL_PLAYING)
+               {
+                       if(info == AL_PAUSED)
+                               alSourceStop(m_source);
+
+                       alSourcei(m_source, AL_BUFFER, 0);
+                       m_current = 0;
+
+                       ALenum err;
+                       if((err = alGetError()) == AL_NO_ERROR)
+                       {
+                               int length;
+                               AUD_DeviceSpecs specs = m_device->m_specs;
+                               specs.specs = m_reader->getSpecs();
+                               m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+
+                               for(int i = 0; i < CYCLE_BUFFERS; i++)
+                               {
+                                       length = m_device->m_buffersize;
+                                       m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
+                                       alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
+                                                                length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
+
+                                       if(alGetError() != AL_NO_ERROR)
+                                               break;
+                               }
+
+                               if(m_loopcount != 0)
+                                       m_eos = false;
+
+                               alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
+                       }
+
+                       alSourceRewind(m_source);
+               }
+       }
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
+{
+       if(!m_status)
+               return 0.0f;
+
+       m_device->lock();
+
+       float position = 0.0f;
+
+       alGetSourcef(m_source, AL_SEC_OFFSET, &position);
+
+       if(!m_isBuffered)
+       {
+               AUD_Specs specs = m_reader->getSpecs();
+               position += (m_reader->getPosition() - m_device->m_buffersize *
+                                        CYCLE_BUFFERS) / (float)specs.rate;
+       }
+
+       m_device->unlock();
+
+       return position;
+}
+
+AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus()
+{
+       return m_status;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolume()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_PITCH, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_PITCH, pitch);
+
+       m_device->unlock();
+
+       return true;
+}
+
+int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount()
+{
+       if(!m_status)
+               return 0;
+       return m_loopcount;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
+{
+       if(!m_status)
+               return false;
+       m_loopcount = count;
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_stop = callback;
+       m_stop_data = data;
+
+       m_device->unlock();
+
+       return true;
+}
+
+/******************************************************************************/
+/********************* AUD_OpenALHandle 3DHandle Code *************************/
+/******************************************************************************/
+
+AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation()
+{
+       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       ALfloat p[3];
+       alGetSourcefv(m_source, AL_POSITION, p);
+
+       m_device->unlock();
+
+       result = AUD_Vector3(p[0], p[1], p[2]);
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
+
+       m_device->unlock();
+
+       return true;
+}
+
+AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
+{
+       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       ALfloat v[3];
+       alGetSourcefv(m_source, AL_VELOCITY, v);
+
+       m_device->unlock();
+
+       result = AUD_Vector3(v[0], v[1], v[2]);
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
+
+       m_device->unlock();
+
+       return true;
+}
+
+AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
+{
+       // AUD_XXX not implemented yet
+       return AUD_Quaternion(0, 0, 0, 0);
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
+{
+       if(!m_status)
+               return false;
+
+       ALfloat direction[3];
+       direction[0] = -2 * (orientation.w() * orientation.y() +
+                                                orientation.x() * orientation.z());
+       direction[1] = 2 * (orientation.x() * orientation.w() -
+                                               orientation.z() * orientation.y());
+       direction[2] = 2 * (orientation.x() * orientation.x() +
+                                               orientation.y() * orientation.y()) - 1;
+       m_device->lock();
+
+       alSourcefv(m_source, AL_DIRECTION, direction);
+
+       m_device->unlock();
+
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
+{
+       int result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MAX_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MAX_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MIN_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MIN_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MAX_DISTANCE, distance);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
 
-       /// The OpenAL buffer.
-       ALuint buffer;
-};
+       alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
 
-typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator;
-typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
+       m_device->unlock();
+
+       return true;
+}
 
 /******************************************************************************/
 /**************************** Threading Code **********************************/
@@ -127,15 +794,15 @@ void AUD_OpenALDevice::start()
 
 void AUD_OpenALDevice::updateStreams()
 {
-       AUD_OpenALHandle* sound;
+       AUD_Reference<AUD_OpenALHandle> sound;
 
        int length;
 
        ALint info;
        AUD_DeviceSpecs specs = m_specs;
        ALCenum cerr;
-       std::list<AUD_OpenALHandle*> stopSounds;
-       std::list<AUD_OpenALHandle*> pauseSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds;
        AUD_HandleIterator it;
 
        while(1)
@@ -147,45 +814,45 @@ void AUD_OpenALDevice::updateStreams()
                if(cerr == ALC_NO_ERROR)
                {
                        // for all sounds
-                       for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
+                       for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
                        {
                                sound = *it;
 
                                // is it a streamed sound?
-                               if(!sound->isBuffered)
+                               if(!sound->m_isBuffered)
                                {
                                        // check for buffer refilling
-                                       alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info);
+                                       alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
 
                                        if(info)
                                        {
-                                               specs.specs = sound->reader->getSpecs();
+                                               specs.specs = sound->m_reader->getSpecs();
                                                m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
 
                                                // for all empty buffers
                                                while(info--)
                                                {
                                                        // if there's still data to play back
-                                                       if(!sound->eos)
+                                                       if(!sound->m_eos)
                                                        {
                                                                // read data
                                                                length = m_buffersize;
-                                                               sound->reader->read(length, sound->eos, m_buffer.getBuffer());
+                                                               sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
 
                                                                // looping necessary?
-                                                               if(length == 0 && sound->loopcount)
+                                                               if(length == 0 && sound->m_loopcount)
                                                                {
-                                                                       if(sound->loopcount > 0)
-                                                                               sound->loopcount--;
+                                                                       if(sound->m_loopcount > 0)
+                                                                               sound->m_loopcount--;
 
-                                                                       sound->reader->seek(0);
+                                                                       sound->m_reader->seek(0);
 
                                                                        length = m_buffersize;
-                                                                       sound->reader->read(length, sound->eos, m_buffer.getBuffer());
+                                                                       sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
                                                                }
 
-                                                               if(sound->loopcount != 0)
-                                                                       sound->eos = false;
+                                                               if(sound->m_loopcount != 0)
+                                                                       sound->m_eos = false;
 
                                                                // read nothing?
                                                                if(length == 0)
@@ -194,39 +861,39 @@ void AUD_OpenALDevice::updateStreams()
                                                                }
 
                                                                // unqueue buffer
-                                                               alSourceUnqueueBuffers(sound->source, 1,
-                                                                                               &sound->buffers[sound->current]);
+                                                               alSourceUnqueueBuffers(sound->m_source, 1,
+                                                                                               &sound->m_buffers[sound->m_current]);
                                                                ALenum err;
                                                                if((err = alGetError()) != AL_NO_ERROR)
                                                                {
-                                                                       sound->eos = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
                                                                // fill with new data
-                                                               alBufferData(sound->buffers[sound->current],
-                                                                                        sound->format,
+                                                               alBufferData(sound->m_buffers[sound->m_current],
+                                                                                        sound->m_format,
                                                                                         m_buffer.getBuffer(), length *
                                                                                         AUD_DEVICE_SAMPLE_SIZE(specs),
                                                                                         specs.rate);
 
                                                                if((err = alGetError()) != AL_NO_ERROR)
                                                                {
-                                                                       sound->eos = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
                                                                // and queue again
-                                                               alSourceQueueBuffers(sound->source, 1,
-                                                                                               &sound->buffers[sound->current]);
+                                                               alSourceQueueBuffers(sound->m_source, 1,
+                                                                                               &sound->m_buffers[sound->m_current]);
                                                                if(alGetError() != AL_NO_ERROR)
                                                                {
-                                                                       sound->eos = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
-                                                               sound->current = (sound->current+1) %
-                                                                                                AUD_OPENAL_CYCLE_BUFFERS;
+                                                               sound->m_current = (sound->m_current+1) %
+                                                                                                AUD_OpenALHandle::CYCLE_BUFFERS;
                                                        }
                                                        else
                                                                break;
@@ -235,18 +902,18 @@ void AUD_OpenALDevice::updateStreams()
                                }
 
                                // check if the sound has been stopped
-                               alGetSourcei(sound->source, AL_SOURCE_STATE, &info);
+                               alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
 
                                if(info != AL_PLAYING)
                                {
                                        // if it really stopped
-                                       if(sound->eos)
+                                       if(sound->m_eos)
                                        {
-                                               if(sound->stop)
-                                                       sound->stop(sound->stop_data);
+                                               if(sound->m_stop)
+                                                       sound->m_stop(sound->m_stop_data);
 
                                                // pause or
-                                               if(sound->keep)
+                                               if(sound->m_keep)
                                                        pauseSounds.push_back(sound);
                                                // stop
                                                else
@@ -254,15 +921,15 @@ void AUD_OpenALDevice::updateStreams()
                                        }
                                        // continue playing
                                        else
-                                               alSourcePlay(sound->source);
+                                               alSourcePlay(sound->m_source);
                                }
                        }
 
                        for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
-                               pause(*it);
+                               (*it)->pause();
 
                        for(it = stopSounds.begin(); it != stopSounds.end(); it++)
-                               stop(*it);
+                               (*it)->stop();
 
                        pauseSounds.clear();
                        stopSounds.clear();
@@ -271,7 +938,7 @@ void AUD_OpenALDevice::updateStreams()
                }
 
                // stop thread
-               if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR))
+               if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
                {
                        unlock();
                        m_playing = false;
@@ -292,19 +959,6 @@ void AUD_OpenALDevice::updateStreams()
 /**************************** IDevice Code ************************************/
 /******************************************************************************/
 
-bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
-{
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-               if(*i == handle)
-                       return true;
-       for(AUD_HandleIterator i = m_pausedSounds->begin();
-               i != m_pausedSounds->end(); i++)
-               if(*i == handle)
-                       return true;
-       return false;
-}
-
 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
 
 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
@@ -357,9 +1011,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
        m_buffersize = buffersize;
        m_playing = false;
 
-       m_playingSounds = new std::list<AUD_OpenALHandle*>();
-       m_pausedSounds = new std::list<AUD_OpenALHandle*>();
-       m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
+//     m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
 
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
@@ -372,44 +1024,23 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
 
 AUD_OpenALDevice::~AUD_OpenALDevice()
 {
-       AUD_OpenALHandle* sound;
-
        lock();
        alcSuspendContext(m_context);
 
-       // delete all playing sounds
-       while(!m_playingSounds->empty())
-       {
-               sound = *(m_playingSounds->begin());
-               alDeleteSources(1, &sound->source);
-               if(!sound->isBuffered)
-               {
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               }
-               delete sound;
-               m_playingSounds->erase(m_playingSounds->begin());
-       }
+       while(!m_playingSounds.empty())
+               m_playingSounds.front()->stop();
+
+       while(!m_pausedSounds.empty())
+               m_pausedSounds.front()->stop();
 
-       // delete all paused sounds
-       while(!m_pausedSounds->empty())
-       {
-               sound = *(m_pausedSounds->begin());
-               alDeleteSources(1, &sound->source);
-               if(!sound->isBuffered)
-               {
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               }
-               delete sound;
-               m_pausedSounds->erase(m_pausedSounds->begin());
-       }
 
        // delete all buffered factories
-       while(!m_bufferedFactories->empty())
+       /*while(!m_bufferedFactories->empty())
        {
                alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
                delete *m_bufferedFactories->begin();
                m_bufferedFactories->erase(m_bufferedFactories->begin());
-       }
+       }*/
 
        alcProcessContext(m_context);
 
@@ -422,9 +1053,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
        else
                unlock();
 
-       delete m_playingSounds;
-       delete m_pausedSounds;
-       delete m_bufferedFactories;
+       //delete m_bufferedFactories;
 
        // quit OpenAL
        alcMakeContextCurrent(NULL);
@@ -530,116 +1159,52 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
        return valid;
 }
 
-static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
-                                                                        "generated.";
-static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
-                                                                        "generated.";
-static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
-                                                                "queued to the source.";
-static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
-                                                                         "filled with data.";
-
-AUD_Handle* AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
+AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
 {
-       AUD_OpenALHandle* sound = NULL;
-
-       AUD_DeviceSpecs specs = m_specs;
-       specs.specs = reader->getSpecs();
+       AUD_Specs specs = reader->getSpecs();
 
        // check format
-       bool valid = specs.channels != AUD_CHANNELS_INVALID;
+       if(specs.channels == AUD_CHANNELS_INVALID)
+               return NULL;
 
        if(m_specs.format != AUD_FORMAT_FLOAT32)
                reader = new AUD_ConverterReader(reader, m_specs);
 
-       // create the handle
-       sound = new AUD_OpenALHandle;
-       sound->keep = keep;
-       sound->reader = reader;
-       sound->current = 0;
-       sound->isBuffered = false;
-       sound->loopcount = 0;
-       sound->stop = NULL;
-       sound->stop_data = NULL;
-
-       valid &= getFormat(sound->format, specs.specs);
+       ALenum format;
 
-       if(!valid)
-       {
-               delete sound;
+       if(!getFormat(format, specs))
                return NULL;
-       }
 
        lock();
        alcSuspendContext(m_context);
 
-       // OpenAL playback code
+       AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound;
+
        try
        {
-               alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               if(alGetError() != AL_NO_ERROR)
-                       AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
-
-               try
-               {
-                       m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
-                       int length;
-
-                       for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
-                       {
-                               length = m_buffersize;
-                               reader->read(length,sound->eos, m_buffer.getBuffer());
-                               alBufferData(sound->buffers[i], sound->format, m_buffer.getBuffer(),
-                                                        length * AUD_DEVICE_SAMPLE_SIZE(specs),
-                                                        specs.rate);
-                               if(alGetError() != AL_NO_ERROR)
-                                       AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
-                       }
-
-                       alGenSources(1, &sound->source);
-                       if(alGetError() != AL_NO_ERROR)
-                               AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
-
-                       try
-                       {
-                               alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS,
-                                                                        sound->buffers);
-                               if(alGetError() != AL_NO_ERROR)
-                                       AUD_THROW(AUD_ERROR_OPENAL, queue_error);
-                       }
-                       catch(AUD_Exception&)
-                       {
-                               alDeleteSources(1, &sound->source);
-                               throw;
-                       }
-               }
-               catch(AUD_Exception&)
-               {
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                       throw;
-               }
+               // create the handle
+               sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep);
        }
        catch(AUD_Exception&)
        {
-               delete sound;
                alcProcessContext(m_context);
                unlock();
                throw;
        }
 
+       alcProcessContext(m_context);
+
        // play sound
-       m_playingSounds->push_back(sound);
-       alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
+       m_playingSounds.push_back(sound);
 
        start();
 
-       alcProcessContext(m_context);
        unlock();
 
-       return sound;
+       return AUD_Reference<AUD_IHandle>(sound);
 }
 
-AUD_Handle* AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
+AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
 {
        /* AUD_XXX disabled
        AUD_OpenALHandle* sound = NULL;
@@ -702,373 +1267,40 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool kee
                        }
                }
        }
-       catch(AUD_Exception&)
-       {
-               unlock();
-               throw;
-       }
-
-       unlock();
-
-       if(sound)
-               return sound;*/
-
-       return play(factory->createReader(), keep);
-}
-
-bool AUD_OpenALDevice::pause(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are played can be paused
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_pausedSounds->push_back(*i);
-                       alSourcePause((*i)->source);
-                       m_playingSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::resume(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are paused can be resumed
-       for(AUD_HandleIterator i = m_pausedSounds->begin();
-               i != m_pausedSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_playingSounds->push_back(*i);
-                       start();
-                       m_pausedSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::stop(AUD_Handle* handle)
-{
-       AUD_OpenALHandle* sound;
-
-       bool result = false;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       sound = *i;
-                       alDeleteSources(1, &sound->source);
-                       if(!sound->isBuffered)
-                       {
-                               alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                       }
-                       delete *i;
-                       m_playingSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-       if(!result)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds->begin();
-                       i != m_pausedSounds->end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               sound = *i;
-                               alDeleteSources(1, &sound->source);
-                               if(!sound->isBuffered)
-                               {
-                                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                               }
-                               delete *i;
-                               m_pausedSounds->erase(i);
-                               result = true;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::getKeep(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-               result = ((AUD_OpenALHandle*)handle)->keep;
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               ((AUD_OpenALHandle*)handle)->keep = keep;
-               result = true;
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle;
-               if(alhandle->isBuffered)
-                       alSourcef(alhandle->source, AL_SEC_OFFSET, position);
-               else
-               {
-                       alhandle->reader->seek((int)(position *
-                                                                                alhandle->reader->getSpecs().rate));
-                       alhandle->eos = false;
-
-                       ALint info;
-
-                       alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info);
-
-                       if(info != AL_PLAYING)
-                       {
-                               if(info == AL_PAUSED)
-                                       alSourceStop(alhandle->source);
-
-                               alSourcei(alhandle->source, AL_BUFFER, 0);
-                               alhandle->current = 0;
-
-                               ALenum err;
-                               if((err = alGetError()) == AL_NO_ERROR)
-                               {
-                                       int length;
-                                       AUD_DeviceSpecs specs = m_specs;
-                                       specs.specs = alhandle->reader->getSpecs();
-                                       m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
-
-                                       for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
-                                       {
-                                               length = m_buffersize;
-                                               alhandle->reader->read(length, alhandle->eos, m_buffer.getBuffer());
-                                               alBufferData(alhandle->buffers[i], alhandle->format,
-                                                                        m_buffer.getBuffer(),
-                                                                        length * AUD_DEVICE_SAMPLE_SIZE(specs),
-                                                                        specs.rate);
-
-                                               if(alGetError() != AL_NO_ERROR)
-                                                       break;
-                                       }
-
-                                       if(alhandle->loopcount != 0)
-                                               alhandle->eos = false;
-
-                                       alSourceQueueBuffers(alhandle->source,
-                                                                                AUD_OPENAL_CYCLE_BUFFERS,
-                                                                                alhandle->buffers);
-                               }
-
-                               alSourceRewind(alhandle->source);
-                       }
-               }
-               result = true;
-       }
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getPosition(AUD_Handle* handle)
-{
-       float position = 0.0f;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
-               alGetSourcef(h->source, AL_SEC_OFFSET, &position);
-               if(!h->isBuffered)
-               {
-                       AUD_Specs specs = h->reader->getSpecs();
-                       position += (h->reader->getPosition() - m_buffersize *
-                                                                       AUD_OPENAL_CYCLE_BUFFERS) /
-                                          (float)specs.rate;
-               }
-       }
-
-       unlock();
-       return position;
-}
-
-AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle)
-{
-       AUD_Status status = AUD_STATUS_INVALID;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       status = AUD_STATUS_PLAYING;
-                       break;
-               }
-       }
-       if(status == AUD_STATUS_INVALID)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds->begin();
-                       i != m_pausedSounds->end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               status = AUD_STATUS_PAUSED;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
-
-       return status;
-}
-
-void AUD_OpenALDevice::lock()
-{
-       pthread_mutex_lock(&m_mutex);
-}
-
-void AUD_OpenALDevice::unlock()
-{
-       pthread_mutex_unlock(&m_mutex);
-}
-
-float AUD_OpenALDevice::getVolume() const
-{
-       float result;
-       alGetListenerf(AL_GAIN, &result);
-       return result;
-}
-
-void AUD_OpenALDevice::setVolume(float volume)
-{
-       alListenerf(AL_GAIN, volume);
-}
+       catch(AUD_Exception&)
+       {
+               unlock();
+               throw;
+       }
 
-float AUD_OpenALDevice::getVolume(AUD_Handle* handle)
-{
-       lock();
-       float result = std::numeric_limits<float>::quiet_NaN();
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result);
        unlock();
-       return result;
-}
 
-bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume)
-{
-       lock();
-       bool result = isValid(handle);
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume);
-       unlock();
-       return result;
-}
+       if(sound)
+               return sound;*/
 
-float AUD_OpenALDevice::getPitch(AUD_Handle* handle)
-{
-       lock();
-       float result = std::numeric_limits<float>::quiet_NaN();
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result);
-       unlock();
-       return result;
+       return play(factory->createReader(), keep);
 }
 
-bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch)
+void AUD_OpenALDevice::lock()
 {
-       lock();
-       bool result = isValid(handle);
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch);
-       unlock();
-       return result;
+       pthread_mutex_lock(&m_mutex);
 }
 
-int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle)
+void AUD_OpenALDevice::unlock()
 {
-       lock();
-       int result = 0;
-       if(isValid(handle))
-               result = ((AUD_OpenALHandle*)handle)->loopcount;
-       unlock();
-       return result;
+       pthread_mutex_unlock(&m_mutex);
 }
 
-bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
+float AUD_OpenALDevice::getVolume() const
 {
-       lock();
-       bool result = isValid(handle);
-       if(result)
-       {
-               ((AUD_OpenALHandle*)handle)->loopcount = count;
-               ((AUD_OpenALHandle*)handle)->eos = false;
-       }
-       unlock();
+       float result;
+       alGetListenerf(AL_GAIN, &result);
        return result;
 }
 
-bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
+void AUD_OpenALDevice::setVolume(float volume)
 {
-       lock();
-       bool result = isValid(handle);
-       if(result)
-       {
-               AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
-               h->stop = callback;
-               h->stop_data = data;
-       }
-       unlock();
-       return result;
+       alListenerf(AL_GAIN, volume);
 }
 
 /* AUD_XXX Temorary disabled
@@ -1308,333 +1540,3 @@ void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
                alDistanceModel(AL_NONE);
        }
 }
-
-AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle)
-{
-       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
-       ALfloat p[3];
-       lock();
-
-       if(isValid(handle))
-       {
-               alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p);
-               result = AUD_Vector3(p[0], p[1], p[2]);
-       }
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION,
-                                  (ALfloat*)location.get());
-
-       unlock();
-       return result;
-}
-
-AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle)
-{
-       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
-       ALfloat v[3];
-       lock();
-
-       if(isValid(handle))
-       {
-               alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v);
-               result = AUD_Vector3(v[0], v[1], v[2]);
-       }
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY,
-                                  (ALfloat*)velocity.get());
-
-       unlock();
-       return result;
-}
-
-AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle)
-{
-       // AUD_XXX not implemented yet
-       return AUD_Quaternion(0, 0, 0, 0);
-}
-
-bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-       {
-               ALfloat direction[3];
-               direction[0] = -2 * (orientation.w() * orientation.y() +
-                                                        orientation.x() * orientation.z());
-               direction[1] = 2 * (orientation.x() * orientation.w() -
-                                                       orientation.z() * orientation.y());
-               direction[2] = 2 * (orientation.x() * orientation.x() +
-                                                       orientation.y() * orientation.y()) - 1;
-               alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION,
-                                  direction);
-       }
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::isRelative(AUD_Handle* handle)
-{
-       int result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
-                                 relative);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
-                                 volume);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
-                                 volume);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
-                                 distance);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
-                                 distance);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
-                                 factor);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
-                                 angle);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
-                                 angle);
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
-                                        &result);
-
-       unlock();
-       return result;
-}
-
-bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
-                                 volume);
-
-       unlock();
-       return result;
-}
index d5db5989fe779aef7030a158262ba5c121d56c72..6bf04a363292db5250643d1fe7e623564a83ea0b 100644 (file)
 #define AUD_OPENALDEVICE
 
 #include "AUD_IDevice.h"
+#include "AUD_IHandle.h"
 #include "AUD_I3DDevice.h"
+#include "AUD_I3DHandle.h"
 #include "AUD_Buffer.h"
-struct AUD_OpenALHandle;
-struct AUD_OpenALBufferedFactory;
+//struct AUD_OpenALBufferedFactory;
 
 #include <AL/al.h>
 #include <AL/alc.h>
@@ -49,6 +50,99 @@ struct AUD_OpenALBufferedFactory;
 class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice
 {
 private:
+       /// Saves the data for playback.
+       class AUD_OpenALHandle : public AUD_IHandle, public AUD_I3DHandle
+       {
+       public:
+               static const int CYCLE_BUFFERS = 3;
+
+               /// Whether it's a buffered or a streamed source.
+               bool m_isBuffered;
+
+               /// The reader source.
+               AUD_Reference<AUD_IReader> m_reader;
+
+               /// Whether to keep the source if end of it is reached.
+               bool m_keep;
+
+               /// OpenAL sample format.
+               ALenum m_format;
+
+               /// OpenAL source.
+               ALuint m_source;
+
+               /// OpenAL buffers.
+               ALuint m_buffers[CYCLE_BUFFERS];
+
+               /// The first buffer to be read next.
+               int m_current;
+
+               /// Whether the stream doesn't return any more data.
+               bool m_eos;
+
+               /// The loop count of the source.
+               int m_loopcount;
+
+               /// The stop callback.
+               stopCallback m_stop;
+
+               /// Stop callback data.
+               void* m_stop_data;
+
+               /// Current status of the handle
+               AUD_Status m_status;
+
+               /// Own device.
+               AUD_OpenALDevice* m_device;
+
+       public:
+
+               AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep);
+
+               virtual ~AUD_OpenALHandle() {}
+               virtual bool pause();
+               virtual bool resume();
+               virtual bool stop();
+               virtual bool getKeep();
+               virtual bool setKeep(bool keep);
+               virtual bool seek(float position);
+               virtual float getPosition();
+               virtual AUD_Status getStatus();
+               virtual float getVolume();
+               virtual bool setVolume(float volume);
+               virtual float getPitch();
+               virtual bool setPitch(float pitch);
+               virtual int getLoopCount();
+               virtual bool setLoopCount(int count);
+               virtual bool setStopCallback(stopCallback callback = 0, void* data = 0);
+
+               virtual AUD_Vector3 getSourceLocation();
+               virtual bool setSourceLocation(const AUD_Vector3& location);
+               virtual AUD_Vector3 getSourceVelocity();
+               virtual bool setSourceVelocity(const AUD_Vector3& velocity);
+               virtual AUD_Quaternion getSourceOrientation();
+               virtual bool setSourceOrientation(const AUD_Quaternion& orientation);
+               virtual bool isRelative();
+               virtual bool setRelative(bool relative);
+               virtual float getVolumeMaximum();
+               virtual bool setVolumeMaximum(float volume);
+               virtual float getVolumeMinimum();
+               virtual bool setVolumeMinimum(float volume);
+               virtual float getDistanceMaximum();
+               virtual bool setDistanceMaximum(float distance);
+               virtual float getDistanceReference();
+               virtual bool setDistanceReference(float distance);
+               virtual float getAttenuation();
+               virtual bool setAttenuation(float factor);
+               virtual float getConeAngleOuter();
+               virtual bool setConeAngleOuter(float angle);
+               virtual float getConeAngleInner();
+               virtual bool setConeAngleInner(float angle);
+               virtual float getConeVolumeOuter();
+               virtual bool setConeVolumeOuter(float volume);
+       };
+
+
        /**
         * The OpenAL device handle.
         */
@@ -72,17 +166,17 @@ private:
        /**
         * The list of sounds that are currently playing.
         */
-       std::list<AUD_OpenALHandle*>* m_playingSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > m_playingSounds;
 
        /**
         * The list of sounds that are currently paused.
         */
-       std::list<AUD_OpenALHandle*>* m_pausedSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > m_pausedSounds;
 
        /**
         * The list of buffered factories.
         */
-       std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
+       //std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
 
        /**
         * The mutex for locking.
@@ -114,13 +208,6 @@ private:
         */
        void start();
 
-       /**
-        * Checks if a handle is valid.
-        * \param handle The handle to check.
-        * \return Whether the handle is valid.
-        */
-       bool isValid(AUD_Handle* handle);
-
        /**
         * Gets the format according to the specs.
         * \param format The variable to put the format into.
@@ -153,27 +240,12 @@ public:
        virtual ~AUD_OpenALDevice();
 
        virtual AUD_DeviceSpecs getSpecs() const;
-       virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false);
-       virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
-       virtual bool pause(AUD_Handle* handle);
-       virtual bool resume(AUD_Handle* handle);
-       virtual bool stop(AUD_Handle* handle);
-       virtual bool getKeep(AUD_Handle* handle);
-       virtual bool setKeep(AUD_Handle* handle, bool keep);
-       virtual bool seek(AUD_Handle* handle, float position);
-       virtual float getPosition(AUD_Handle* handle);
-       virtual AUD_Status getStatus(AUD_Handle* handle);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
        virtual void lock();
        virtual void unlock();
        virtual float getVolume() const;
        virtual void setVolume(float volume);
-       virtual float getVolume(AUD_Handle* handle);
-       virtual bool setVolume(AUD_Handle* handle, float volume);
-       virtual float getPitch(AUD_Handle* handle);
-       virtual bool setPitch(AUD_Handle* handle, float pitch);
-       virtual int getLoopCount(AUD_Handle* handle);
-       virtual bool setLoopCount(AUD_Handle* handle, int count);
-       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
 
        virtual AUD_Vector3 getListenerLocation() const;
        virtual void setListenerLocation(const AUD_Vector3& location);
@@ -187,30 +259,6 @@ public:
        virtual void setDopplerFactor(float factor);
        virtual AUD_DistanceModel getDistanceModel() const;
        virtual void setDistanceModel(AUD_DistanceModel model);
-       virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle);
-       virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location);
-       virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle);
-       virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity);
-       virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle);
-       virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation);
-       virtual bool isRelative(AUD_Handle* handle);
-       virtual bool setRelative(AUD_Handle* handle, bool relative);
-       virtual float getVolumeMaximum(AUD_Handle* handle);
-       virtual bool setVolumeMaximum(AUD_Handle* handle, float volume);
-       virtual float getVolumeMinimum(AUD_Handle* handle);
-       virtual bool setVolumeMinimum(AUD_Handle* handle, float volume);
-       virtual float getDistanceMaximum(AUD_Handle* handle);
-       virtual bool setDistanceMaximum(AUD_Handle* handle, float distance);
-       virtual float getDistanceReference(AUD_Handle* handle);
-       virtual bool setDistanceReference(AUD_Handle* handle, float distance);
-       virtual float getAttenuation(AUD_Handle* handle);
-       virtual bool setAttenuation(AUD_Handle* handle, float factor);
-       virtual float getConeAngleOuter(AUD_Handle* handle);
-       virtual bool setConeAngleOuter(AUD_Handle* handle, float angle);
-       virtual float getConeAngleInner(AUD_Handle* handle);
-       virtual bool setConeAngleInner(AUD_Handle* handle, float angle);
-       virtual float getConeVolumeOuter(AUD_Handle* handle);
-       virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume);
 };
 
 #endif //AUD_OPENALDEVICE
index b6e336eb329875086b89ed5932b88313c30b77b5..2a4cee4dd0e645cd175c7fd94e4483c85a2349f0 100644 (file)
@@ -33,6 +33,7 @@
 #include "structmember.h"
 
 #include "AUD_I3DDevice.h"
+#include "AUD_I3DHandle.h"
 #include "AUD_NULLDevice.h"
 #include "AUD_DelayFactory.h"
 #include "AUD_DoubleFactory.h"
@@ -1033,7 +1034,8 @@ static PyTypeObject FactoryType = {
 static void
 Handle_dealloc(Handle* self)
 {
-       Py_XDECREF(self->device);
+       if(self->handle)
+               delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle);
        Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
@@ -1046,11 +1048,9 @@ PyDoc_STRVAR(M_aud_Handle_pause_doc,
 static PyObject *
 Handle_pause(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->pause(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->pause());
        }
        catch(AUD_Exception& e)
        {
@@ -1068,11 +1068,9 @@ PyDoc_STRVAR(M_aud_Handle_resume_doc,
 static PyObject *
 Handle_resume(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->resume(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->resume());
        }
        catch(AUD_Exception& e)
        {
@@ -1091,11 +1089,9 @@ PyDoc_STRVAR(M_aud_Handle_stop_doc,
 static PyObject *
 Handle_stop(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->stop(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->stop());
        }
        catch(AUD_Exception& e)
        {
@@ -1123,11 +1119,9 @@ PyDoc_STRVAR(M_aud_Handle_position_doc,
 static PyObject *
 Handle_get_position(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getPosition(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPosition());
        }
        catch(AUD_Exception& e)
        {
@@ -1144,11 +1138,9 @@ Handle_set_position(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:position", &position))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->seek(self->handle, position))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->seek(position))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't seek the sound!");
        }
@@ -1172,11 +1164,9 @@ PyDoc_STRVAR(M_aud_Handle_keep_doc,
 static PyObject *
 Handle_get_keep(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getKeep(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getKeep());
        }
        catch(AUD_Exception& e)
        {
@@ -1195,11 +1185,10 @@ Handle_set_keep(Handle *self, PyObject* args, void* nothing)
        }
 
        bool keep = args == Py_True;
-       Device* device = (Device*)self->device;
 
        try
        {
-               if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setKeep(self->handle, keep))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setKeep(keep))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
        }
@@ -1217,11 +1206,9 @@ PyDoc_STRVAR(M_aud_Handle_status_doc,
 static PyObject *
 Handle_get_status(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getStatus(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getStatus());
        }
        catch(AUD_Exception& e)
        {
@@ -1236,11 +1223,9 @@ PyDoc_STRVAR(M_aud_Handle_volume_doc,
 static PyObject *
 Handle_get_volume(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getVolume(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getVolume());
        }
        catch(AUD_Exception& e)
        {
@@ -1257,11 +1242,9 @@ Handle_set_volume(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume", &volume))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setVolume(self->handle, volume))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setVolume(volume))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the sound volume!");
        }
@@ -1279,11 +1262,9 @@ PyDoc_STRVAR(M_aud_Handle_pitch_doc,
 static PyObject *
 Handle_get_pitch(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getPitch(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPitch());
        }
        catch(AUD_Exception& e)
        {
@@ -1300,11 +1281,9 @@ Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:pitch", &pitch))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setPitch(self->handle, pitch))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setPitch(pitch))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
        }
@@ -1322,11 +1301,9 @@ PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
 static PyObject *
 Handle_get_loop_count(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getLoopCount(self->handle));
+               return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getLoopCount());
        }
        catch(AUD_Exception& e)
        {
@@ -1343,11 +1320,9 @@ Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "i:loop_count", &loops))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setLoopCount(self->handle, loops))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setLoopCount(loops))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the loop count!");
        }
@@ -1365,14 +1340,12 @@ PyDoc_STRVAR(M_aud_Handle_location_doc,
 static PyObject *
 Handle_get_location(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Vector3 v = device->getSourceLocation(self->handle);
+                       AUD_Vector3 v = handle->getSourceLocation();
                        return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
                }
                else
@@ -1396,15 +1369,13 @@ Handle_set_location(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Vector3 location(x, y, z);
-                       if(device->setSourceLocation(self->handle, location))
+                       if(handle->setSourceLocation(location))
                                return 0;
                        PyErr_SetString(AUDError, "Location couldn't be set!");
                }
@@ -1425,14 +1396,12 @@ PyDoc_STRVAR(M_aud_Handle_velocity_doc,
 static PyObject *
 Handle_get_velocity(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Vector3 v = device->getSourceVelocity(self->handle);
+                       AUD_Vector3 v = handle->getSourceVelocity();
                        return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
                }
                else
@@ -1456,15 +1425,13 @@ Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Vector3 velocity(x, y, z);
-                       if(device->setSourceVelocity(self->handle, velocity))
+                       if(handle->setSourceVelocity(velocity))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the velocity!");
                }
@@ -1485,14 +1452,12 @@ PyDoc_STRVAR(M_aud_Handle_orientation_doc,
 static PyObject *
 Handle_get_orientation(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Quaternion o = device->getSourceOrientation(self->handle);
+                       AUD_Quaternion o = handle->getSourceOrientation();
                        return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
                }
                else
@@ -1516,15 +1481,13 @@ Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Quaternion orientation(w, x, y, z);
-                       if(device->setSourceOrientation(self->handle, orientation))
+                       if(handle->setSourceOrientation(orientation))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the orientation!");
                }
@@ -1545,14 +1508,12 @@ PyDoc_STRVAR(M_aud_Handle_relative_doc,
 static PyObject *
 Handle_get_relative(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return PyBool_FromLong((long)device->isRelative(self->handle));
+                       return PyBool_FromLong((long)handle->isRelative());
                }
                else
                {
@@ -1577,14 +1538,13 @@ Handle_set_relative(Handle *self, PyObject* args, void* nothing)
        }
 
        bool relative = (args == Py_True);
-       Device* dev = (Device*)self->device;
 
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setRelative(self->handle, relative))
+                       if(handle->setRelative(relative))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the relativeness!");
                }
@@ -1606,14 +1566,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
 static PyObject *
 Handle_get_volume_minimum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
+                       return Py_BuildValue("f", handle->getVolumeMinimum());
                }
                else
                {
@@ -1636,14 +1594,12 @@ Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume_minimum", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setVolumeMinimum(self->handle, volume))
+                       if(handle->setVolumeMinimum(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
                }
@@ -1665,14 +1621,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
 static PyObject *
 Handle_get_volume_maximum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
+                       return Py_BuildValue("f", handle->getVolumeMaximum());
                }
                else
                {
@@ -1695,14 +1649,12 @@ Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume_maximum", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setVolumeMaximum(self->handle, volume))
+                       if(handle->setVolumeMaximum(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
                }
@@ -1725,14 +1677,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
 static PyObject *
 Handle_get_distance_reference(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getDistanceReference(self->handle));
+                       return Py_BuildValue("f", handle->getDistanceReference());
                }
                else
                {
@@ -1755,14 +1705,12 @@ Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:distance_reference", &distance))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setDistanceReference(self->handle, distance))
+                       if(handle->setDistanceReference(distance))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the reference distance!");
                }
@@ -1785,14 +1733,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
 static PyObject *
 Handle_get_distance_maximum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
+                       return Py_BuildValue("f", handle->getDistanceMaximum());
                }
                else
                {
@@ -1815,14 +1761,12 @@ Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:distance_maximum", &distance))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setDistanceMaximum(self->handle, distance))
+                       if(handle->setDistanceMaximum(distance))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
                }
@@ -1845,14 +1789,12 @@ PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
 static PyObject *
 Handle_get_attenuation(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getAttenuation(self->handle));
+                       return Py_BuildValue("f", handle->getAttenuation());
                }
                else
                {
@@ -1875,14 +1817,12 @@ Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:attenuation", &factor))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setAttenuation(self->handle, factor))
+                       if(handle->setAttenuation(factor))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the attenuation!");
                }
@@ -1910,14 +1850,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
 static PyObject *
 Handle_get_cone_angle_inner(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeAngleInner(self->handle));
+                       return Py_BuildValue("f", handle->getConeAngleInner());
                }
                else
                {
@@ -1940,14 +1878,12 @@ Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeAngleInner(self->handle, angle))
+                       if(handle->setConeAngleInner(angle))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
                }
@@ -1969,14 +1905,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
 static PyObject *
 Handle_get_cone_angle_outer(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
+                       return Py_BuildValue("f", handle->getConeAngleOuter());
                }
                else
                {
@@ -1999,14 +1933,12 @@ Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeAngleOuter(self->handle, angle))
+                       if(handle->setConeAngleOuter(angle))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
                }
@@ -2028,14 +1960,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
 static PyObject *
 Handle_get_cone_volume_outer(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
+                       return Py_BuildValue("f", handle->getConeVolumeOuter());
                }
                else
                {
@@ -2058,14 +1988,12 @@ Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get());
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeVolumeOuter(self->handle, volume))
+                       if(handle->setConeVolumeOuter(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
                }
@@ -2302,12 +2230,9 @@ Device_play(Device *self, PyObject *args, PyObject *kwds)
        handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
        if(handle != NULL)
        {
-               handle->device = (PyObject*)self;
-               Py_INCREF(self);
-
                try
                {
-                       handle->handle = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->factory), keep);
+                       handle->handle = new AUD_Reference<AUD_IHandle>((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->factory), keep));
                }
                catch(AUD_Exception& e)
                {
index 822aec069762a2632c2608f4f533d0428be6ca21..e234ad4ddede11b306eea23b7f4c2b0887d389e6 100644 (file)
 
 #ifdef __cplusplus
 extern "C" {
-struct AUD_Handle;
 #else
 typedef void AUD_IFactory;
 typedef void AUD_IDevice;
-typedef void AUD_Handle;
+typedef void AUD_IHandle;
 #endif
 
 typedef void AUD_Reference_AUD_IFactory;
 typedef void AUD_Reference_AUD_IDevice;
+typedef void AUD_Reference_AUD_IHandle;
 
 typedef struct {
        PyObject_HEAD
@@ -54,8 +54,7 @@ typedef struct {
 
 typedef struct {
        PyObject_HEAD
-       AUD_Handle* handle;
-       PyObject* device;
+       AUD_Reference_AUD_IHandle* handle;
 } Handle;
 
 typedef struct {
index 852b93d24a8ee023377bc40c3ff244698883caff..b7690d55383bdaac82f9a07dcb9cbc80a3d1cca5 100644 (file)
@@ -432,7 +432,7 @@ void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
                                pkgbuf_pos-data_size);
        }
 
-       if(eos = (left > 0))
+       if((eos = (left > 0)))
                length -= left;
 
        m_position += length;
index 3ab226558acd510b922d8376afdc5e395d0099fb..99a99069378040d61557789115787a6577b6fc32 100644 (file)
@@ -68,6 +68,8 @@ AUD_Specs AUD_BufferReader::getSpecs() const
 
 void AUD_BufferReader::read(int& length, bool& eos, sample_t* buffer)
 {
+       eos = false;
+
        int sample_size = AUD_SAMPLE_SIZE(m_specs);
 
        sample_t* buf = m_buffer->getBuffer() + m_position * m_specs.channels;
index 0b2e782925ce7e78485901ca6bbb5e19793f46dc..fc693be12d5dc9c14cbd42ba42b36a9f3e63e49c 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "AUD_NULLDevice.h"
 #include "AUD_I3DDevice.h"
+#include "AUD_I3DHandle.h"
 #include "AUD_FileFactory.h"
 #include "AUD_StreamBufferFactory.h"
 #include "AUD_DelayFactory.h"
@@ -89,7 +90,7 @@ extern "C" {
 
 typedef AUD_Reference<AUD_IFactory> AUD_Sound;
 typedef AUD_Reference<AUD_ReadDevice> AUD_Device;
-typedef AUD_Handle AUD_Channel;
+typedef AUD_Reference<AUD_IHandle> AUD_Channel;
 typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry;
 
 #define AUD_CAPI_IMPLEMENTATION
@@ -375,16 +376,16 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound)
 
 int AUD_setLoop(AUD_Channel* handle, int loops)
 {
-       if(handle)
+       assert(handle);
+
+       try
+       {
+               return (*handle)->setLoopCount(loops);
+       }
+       catch(AUD_Exception&)
        {
-               try
-               {
-                       return AUD_device->setLoopCount(handle, loops);
-               }
-               catch(AUD_Exception&)
-               {
-               }
        }
+
        return false;
 }
 
@@ -413,49 +414,58 @@ AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
        assert(sound);
        try
        {
-               return AUD_device->play(*sound, keep);
+               AUD_Channel channel = AUD_device->play(*sound, keep);
+               if(!channel.isNull())
+                       return new AUD_Channel(channel);
        }
        catch(AUD_Exception&)
        {
-               return NULL;
        }
+       return NULL;
 }
 
 int AUD_pause(AUD_Channel* handle)
 {
-       return AUD_device->pause(handle);
+       assert(handle);
+       return (*handle)->pause();
 }
 
 int AUD_resume(AUD_Channel* handle)
 {
-       return AUD_device->resume(handle);
+       assert(handle);
+       return (*handle)->resume();
 }
 
 int AUD_stop(AUD_Channel* handle)
 {
-       if(!AUD_device.isNull())
-               return AUD_device->stop(handle);
-       return false;
+       assert(handle);
+       int result = (*handle)->stop();
+       delete handle;
+       return result;
 }
 
 int AUD_setKeep(AUD_Channel* handle, int keep)
 {
-       return AUD_device->setKeep(handle, keep);
+       assert(handle);
+       return (*handle)->setKeep(keep);
 }
 
 int AUD_seek(AUD_Channel* handle, float seekTo)
 {
-       return AUD_device->seek(handle, seekTo);
+       assert(handle);
+       return (*handle)->seek(seekTo);
 }
 
 float AUD_getPosition(AUD_Channel* handle)
 {
-       return AUD_device->getPosition(handle);
+       assert(handle);
+       return (*handle)->getPosition();
 }
 
 AUD_Status AUD_getStatus(AUD_Channel* handle)
 {
-       return AUD_device->getStatus(handle);
+       assert(handle);
+       return (*handle)->getStatus();
 }
 
 int AUD_setListenerLocation(const float* location)
@@ -529,10 +539,13 @@ int AUD_setDistanceModel(AUD_DistanceModel model)
 
 int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
                AUD_Vector3 v(location[0], location[1], location[2]);
-               return AUD_3ddevice->setSourceLocation(handle, v);
+               return h->setSourceLocation(v);
        }
 
        return false;
@@ -540,10 +553,13 @@ int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
 
 int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
                AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
-               return AUD_3ddevice->setSourceVelocity(handle, v);
+               return h->setSourceVelocity(v);
        }
 
        return false;
@@ -551,10 +567,13 @@ int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
 
 int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
                AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
-               return AUD_3ddevice->setSourceOrientation(handle, q);
+               return h->setSourceOrientation(q);
        }
 
        return false;
@@ -562,9 +581,12 @@ int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
 
 int AUD_setRelative(AUD_Channel* handle, int relative)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setRelative(handle, relative);
+               return h->setRelative(relative);
        }
 
        return false;
@@ -572,9 +594,12 @@ int AUD_setRelative(AUD_Channel* handle, int relative)
 
 int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setVolumeMaximum(handle, volume);
+               return h->setVolumeMaximum(volume);
        }
 
        return false;
@@ -582,9 +607,12 @@ int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
 
 int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setVolumeMinimum(handle, volume);
+               return h->setVolumeMinimum(volume);
        }
 
        return false;
@@ -592,9 +620,12 @@ int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
 
 int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setDistanceMaximum(handle, distance);
+               return h->setDistanceMaximum(distance);
        }
 
        return false;
@@ -602,9 +633,12 @@ int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
 
 int AUD_setDistanceReference(AUD_Channel* handle, float distance)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setDistanceReference(handle, distance);
+               return h->setDistanceReference(distance);
        }
 
        return false;
@@ -612,9 +646,12 @@ int AUD_setDistanceReference(AUD_Channel* handle, float distance)
 
 int AUD_setAttenuation(AUD_Channel* handle, float factor)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setAttenuation(handle, factor);
+               return h->setAttenuation(factor);
        }
 
        return false;
@@ -622,9 +659,12 @@ int AUD_setAttenuation(AUD_Channel* handle, float factor)
 
 int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setConeAngleOuter(handle, angle);
+               return h->setConeAngleOuter(angle);
        }
 
        return false;
@@ -632,9 +672,12 @@ int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
 
 int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setConeAngleInner(handle, angle);
+               return h->setConeAngleInner(angle);
        }
 
        return false;
@@ -642,9 +685,12 @@ int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
 
 int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
 {
-       if(AUD_3ddevice)
+       assert(handle);
+       AUD_Reference<AUD_I3DHandle> h(*handle);
+
+       if(!h.isNull())
        {
-               return AUD_3ddevice->setConeVolumeOuter(handle, volume);
+               return h->setConeVolumeOuter(volume);
        }
 
        return false;
@@ -652,27 +698,23 @@ int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
 
 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
 {
-       if(handle)
+       assert(handle);
+       try
        {
-               try
-               {
-                       return AUD_device->setVolume(handle, volume);
-               }
-               catch(AUD_Exception&) {}
+               return (*handle)->setVolume(volume);
        }
+       catch(AUD_Exception&) {}
        return false;
 }
 
 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
 {
-       if(handle)
+       assert(handle);
+       try
        {
-               try
-               {
-                       return AUD_device->setPitch(handle, pitch);
-               }
-               catch(AUD_Exception&) {}
+               return (*handle)->setPitch(pitch);
        }
+       catch(AUD_Exception&) {}
        return false;
 }
 
@@ -695,14 +737,17 @@ AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
 
        try
        {
-               AUD_Channel* handle = (*device)->play(*sound);
-               (*device)->seek(handle, seek);
-               return handle;
+               AUD_Channel channel = (*device)->play(*sound);
+               if(!channel.isNull())
+               {
+                       channel->seek(seek);
+                       return new AUD_Channel(channel);
+               }
        }
        catch(AUD_Exception&)
        {
-               return NULL;
        }
+       return NULL;
 }
 
 int AUD_setDeviceVolume(AUD_Device* device, float volume)
@@ -719,22 +764,6 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume)
        return false;
 }
 
-int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
-                                                        float volume)
-{
-       if(handle)
-       {
-               assert(device);
-
-               try
-               {
-                       return (*device)->setVolume(handle, volume);
-               }
-               catch(AUD_Exception&) {}
-       }
-       return false;
-}
-
 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
 {
        assert(device);
@@ -821,7 +850,8 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
 
 static void pauseSound(AUD_Channel* handle)
 {
-       AUD_device->pause(handle);
+       assert(handle);
+       (*handle)->pause();
 }
 
 AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
@@ -829,16 +859,25 @@ AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
        AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory;
        AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds);
 
+       AUD_device->lock();
+
        try
        {
-               AUD_Channel* channel = AUD_device->play(limiter);
-               AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
-               return channel;
+               AUD_Channel channel = AUD_device->play(limiter);
+               if(!channel.isNull())
+               {
+                       channel->setStopCallback((stopCallback)pauseSound, handle);
+                       AUD_device->unlock();
+                       return new AUD_Channel(channel);
+               }
        }
        catch(AUD_Exception&)
        {
-               return NULL;
        }
+
+       AUD_device->unlock();
+
+       return NULL;
 }
 
 AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume)
@@ -966,7 +1005,8 @@ void AUD_seekSequencer(AUD_Channel* handle, float time)
        else
 #endif
        {
-               AUD_device->seek(handle, time);
+               assert(handle);
+               (*handle)->seek(time);
        }
 }
 
@@ -979,7 +1019,8 @@ float AUD_getSequencerPosition(AUD_Channel* handle)
        else
 #endif
        {
-               return AUD_device->getPosition(handle);
+               assert(handle);
+               return (*handle)->getPosition();
        }
 }
 
@@ -1006,3 +1047,8 @@ AUD_Sound* AUD_copy(AUD_Sound* sound)
 {
        return new AUD_Reference<AUD_IFactory>(*sound);
 }
+
+void AUD_freeChannel(AUD_Channel* channel)
+{
+       delete channel;
+}
index 3fdb9e7bca3c2c741393a1ad1224580092947abe..945faa50070976a404de1fde1a7bee235c30e8fd 100644 (file)
@@ -417,17 +417,6 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
  */
 extern AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
 
-/**
- * Sets the volume of a played back sound of a read device.
- * \param device The read device.
- * \param handle The handle to the sound.
- * \param volume The new volume, must be between 0.0 and 1.0.
- * \return Whether the action succeeded.
- */
-extern int AUD_setDeviceSoundVolume(AUD_Device* device,
-                                                                       AUD_Channel* handle,
-                                                                       float volume);
-
 /**
  * Reads the next samples into the supplied buffer.
  * \param device The read device.
@@ -498,6 +487,8 @@ extern int AUD_doesPlayback(void);
 
 extern AUD_Sound* AUD_copy(AUD_Sound* sound);
 
+extern void AUD_freeChannel(AUD_Channel* channel);
+
 #ifdef WITH_PYTHON
 extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
 
index df341dbb319a62bf3f0e701a4558698875fbd8c3..036f7b1fa94c5f40225cced8616bb1a33877ad87 100644 (file)
@@ -35,8 +35,6 @@
 #include "AUD_Space.h"
 #include "AUD_3DMath.h"
 
-struct AUD_Handle;
-
 /**
  * This class represents an output device for 3D sound.
  */
@@ -121,200 +119,6 @@ public:
         * \param model distance model.
         */
        virtual void setDistanceModel(AUD_DistanceModel model)=0;
-
-
-
-       /**
-        * Retrieves the location of a source.
-        * \param handle The handle of the source.
-        * \return The location.
-        */
-       virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the location of a source.
-        * \param handle The handle of the source.
-        * \param location The new location.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)=0;
-
-       /**
-        * Retrieves the velocity of a source.
-        * \param handle The handle of the source.
-        * \return The velocity.
-        */
-       virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the velocity of a source.
-        * \param handle The handle of the source.
-        * \param velocity The new velocity.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)=0;
-
-       /**
-        * Retrieves the orientation of a source.
-        * \param handle The handle of the source.
-        * \return The orientation as quaternion.
-        */
-       virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the orientation of a source.
-        * \param handle The handle of the source.
-        * \param orientation The new orientation as quaternion.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)=0;
-
-
-       /**
-        * Checks whether the source location, velocity and orientation are relative
-        * to the listener.
-        * \param handle The handle of the source.
-        * \return Whether the source is relative.
-        */
-       virtual bool isRelative(AUD_Handle* handle)=0;
-
-       /**
-        * Sets whether the source location, velocity and orientation are relative
-        * to the listener.
-        * \param handle The handle of the source.
-        * \param relative Whether the source is relative.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setRelative(AUD_Handle* handle, bool relative)=0;
-
-       /**
-        * Retrieves the maximum volume of a source.
-        * \param handle The handle of the source.
-        * \return The maximum volume.
-        */
-       virtual float getVolumeMaximum(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the maximum volume of a source.
-        * \param handle The handle of the source.
-        * \param volume The new maximum volume.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setVolumeMaximum(AUD_Handle* handle, float volume)=0;
-
-       /**
-        * Retrieves the minimum volume of a source.
-        * \param handle The handle of the source.
-        * \return The minimum volume.
-        */
-       virtual float getVolumeMinimum(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the minimum volume of a source.
-        * \param handle The handle of the source.
-        * \param volume The new minimum volume.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setVolumeMinimum(AUD_Handle* handle, float volume)=0;
-
-       /**
-        * Retrieves the maximum distance of a source.
-        * If a source is further away from the reader than this distance, the
-        * volume will automatically be set to 0.
-        * \param handle The handle of the source.
-        * \return The maximum distance.
-        */
-       virtual float getDistanceMaximum(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the maximum distance of a source.
-        * If a source is further away from the reader than this distance, the
-        * volume will automatically be set to 0.
-        * \param handle The handle of the source.
-        * \param distance The new maximum distance.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setDistanceMaximum(AUD_Handle* handle, float distance)=0;
-
-       /**
-        * Retrieves the reference distance of a source.
-        * \param handle The handle of the source.
-        * \return The reference distance.
-        */
-       virtual float getDistanceReference(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the reference distance of a source.
-        * \param handle The handle of the source.
-        * \param distance The new reference distance.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setDistanceReference(AUD_Handle* handle, float distance)=0;
-
-       /**
-        * Retrieves the attenuation of a source.
-        * \param handle The handle of the source.
-        * \return The attenuation.
-        */
-       virtual float getAttenuation(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the attenuation of a source.
-        * This value is used for distance calculation.
-        * \param handle The handle of the source.
-        * \param factor The new attenuation.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setAttenuation(AUD_Handle* handle, float factor)=0;
-
-       /**
-        * Retrieves the outer angle of the cone of a source.
-        * \param handle The handle of the source.
-        * \return The outer angle of the cone.
-        */
-       virtual float getConeAngleOuter(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the outer angle of the cone of a source.
-        * \param handle The handle of the source.
-        * \param angle The new outer angle of the cone.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setConeAngleOuter(AUD_Handle* handle, float angle)=0;
-
-       /**
-        * Retrieves the inner angle of the cone of a source.
-        * \param handle The handle of the source.
-        * \return The inner angle of the cone.
-        */
-       virtual float getConeAngleInner(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the inner angle of the cone of a source.
-        * \param handle The handle of the source.
-        * \param angle The new inner angle of the cone.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setConeAngleInner(AUD_Handle* handle, float angle)=0;
-
-       /**
-        * Retrieves the outer volume of the cone of a source.
-        * The volume between inner and outer angle is interpolated between inner
-        * volume and this value.
-        * \param handle The handle of the source.
-        * \return The outer volume of the cone.
-        */
-       virtual float getConeVolumeOuter(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the outer volume of the cone of a source.
-        * The volume between inner and outer angle is interpolated between inner
-        * volume and this value.
-        * \param handle The handle of the source.
-        * \param volume The new outer volume of the cone.
-        * \return Whether the action succeeded.
-        */
-       virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume)=0;
 };
 
 #endif //AUD_I3DDEVICE
diff --git a/intern/audaspace/intern/AUD_I3DHandle.h b/intern/audaspace/intern/AUD_I3DHandle.h
new file mode 100644 (file)
index 0000000..259c702
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_I3DHandle.h
+ *  \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_I3DHANDLE
+#define AUD_I3DHANDLE
+
+#include "AUD_Space.h"
+#include "AUD_3DMath.h"
+
+/**
+ * This class represents an output device for 3D sound.
+ */
+class AUD_I3DHandle
+{
+public:
+       /**
+        * Retrieves the location of a source.
+        * \return The location.
+        */
+       virtual AUD_Vector3 getSourceLocation()=0;
+
+       /**
+        * Sets the location of a source.
+        * \param location The new location.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setSourceLocation(const AUD_Vector3& location)=0;
+
+       /**
+        * Retrieves the velocity of a source.
+        * \return The velocity.
+        */
+       virtual AUD_Vector3 getSourceVelocity()=0;
+
+       /**
+        * Sets the velocity of a source.
+        * \param velocity The new velocity.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setSourceVelocity(const AUD_Vector3& velocity)=0;
+
+       /**
+        * Retrieves the orientation of a source.
+        * \return The orientation as quaternion.
+        */
+       virtual AUD_Quaternion getSourceOrientation()=0;
+
+       /**
+        * Sets the orientation of a source.
+        * \param orientation The new orientation as quaternion.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setSourceOrientation(const AUD_Quaternion& orientation)=0;
+
+
+       /**
+        * Checks whether the source location, velocity and orientation are relative
+        * to the listener.
+        * \return Whether the source is relative.
+        */
+       virtual bool isRelative()=0;
+
+       /**
+        * Sets whether the source location, velocity and orientation are relative
+        * to the listener.
+        * \param relative Whether the source is relative.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setRelative(bool relative)=0;
+
+       /**
+        * Retrieves the maximum volume of a source.
+        * \return The maximum volume.
+        */
+       virtual float getVolumeMaximum()=0;
+
+       /**
+        * Sets the maximum volume of a source.
+        * \param volume The new maximum volume.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setVolumeMaximum(float volume)=0;
+
+       /**
+        * Retrieves the minimum volume of a source.
+        * \return The minimum volume.
+        */
+       virtual float getVolumeMinimum()=0;
+
+       /**
+        * Sets the minimum volume of a source.
+        * \param volume The new minimum volume.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setVolumeMinimum(float volume)=0;
+
+       /**
+        * Retrieves the maximum distance of a source.
+        * If a source is further away from the reader than this distance, the
+        * volume will automatically be set to 0.
+        * \return The maximum distance.
+        */
+       virtual float getDistanceMaximum()=0;
+
+       /**
+        * Sets the maximum distance of a source.
+        * If a source is further away from the reader than this distance, the
+        * volume will automatically be set to 0.
+        * \param distance The new maximum distance.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setDistanceMaximum(float distance)=0;
+
+       /**
+        * Retrieves the reference distance of a source.
+        * \return The reference distance.
+        */
+       virtual float getDistanceReference()=0;
+
+       /**
+        * Sets the reference distance of a source.
+        * \param distance The new reference distance.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setDistanceReference(float distance)=0;
+
+       /**
+        * Retrieves the attenuation of a source.
+        * \return The attenuation.
+        */
+       virtual float getAttenuation()=0;
+
+       /**
+        * Sets the attenuation of a source.
+        * This value is used for distance calculation.
+        * \param factor The new attenuation.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setAttenuation(float factor)=0;
+
+       /**
+        * Retrieves the outer angle of the cone of a source.
+        * \return The outer angle of the cone.
+        */
+       virtual float getConeAngleOuter()=0;
+
+       /**
+        * Sets the outer angle of the cone of a source.
+        * \param angle The new outer angle of the cone.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setConeAngleOuter(float angle)=0;
+
+       /**
+        * Retrieves the inner angle of the cone of a source.
+        * \return The inner angle of the cone.
+        */
+       virtual float getConeAngleInner()=0;
+
+       /**
+        * Sets the inner angle of the cone of a source.
+        * \param angle The new inner angle of the cone.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setConeAngleInner(float angle)=0;
+
+       /**
+        * Retrieves the outer volume of the cone of a source.
+        * The volume between inner and outer angle is interpolated between inner
+        * volume and this value.
+        * \return The outer volume of the cone.
+        */
+       virtual float getConeVolumeOuter()=0;
+
+       /**
+        * Sets the outer volume of the cone of a source.
+        * The volume between inner and outer angle is interpolated between inner
+        * volume and this value.
+        * \param volume The new outer volume of the cone.
+        * \return Whether the action succeeded.
+        */
+       virtual bool setConeVolumeOuter(float volume)=0;
+};
+
+#endif //AUD_I3DHANDLE
index 88c9aa5e8d9e445f0dfb4b0738ca3230a9578a81..992e3347366a9fc6c9d6391e17c5d2fdd840da99 100644 (file)
 #include "AUD_Reference.h"
 class AUD_IFactory;
 class AUD_IReader;
-
-/// Handle structure, for inherition.
-struct AUD_Handle
-{
-};
-
-typedef void (*stopCallback)(void*);
+class AUD_IHandle;
 
 /**
  * This class represents an output device for sound sources.
@@ -75,7 +69,7 @@ public:
         * \exception AUD_Exception Thrown if there's an unexpected (from the
         *            device side) error during creation of the reader.
         */
-       virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false)=0;
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false)=0;
 
        /**
         * Plays a sound source.
@@ -87,87 +81,7 @@ public:
         * \exception AUD_Exception Thrown if there's an unexpected (from the
         *            device side) error during creation of the reader.
         */
-       virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false)=0;
-
-       /**
-        * Pauses a played back sound.
-        * \param handle The handle returned by the play function.
-        * \return
-        *        - true if the sound has been paused.
-        *        - false if the sound isn't playing back or the handle is invalid.
-        */
-       virtual bool pause(AUD_Handle* handle)=0;
-
-       /**
-        * Resumes a paused sound.
-        * \param handle The handle returned by the play function.
-        * \return
-        *        - true if the sound has been resumed.
-        *        - false if the sound isn't paused or the handle is invalid.
-        */
-       virtual bool resume(AUD_Handle* handle)=0;
-
-       /**
-        * Stops a played back or paused sound. The handle is definitely invalid
-        * afterwards.
-        * \param handle The handle returned by the play function.
-        * \return
-        *        - true if the sound has been stopped.
-        *        - false if the handle is invalid.
-        */
-       virtual bool stop(AUD_Handle* handle)=0;
-
-       /**
-        * Gets the behaviour of the device for a played back sound when the sound
-        * doesn't return any more samples.
-        * \param handle The handle returned by the play function.
-        * \return
-        *        - true if the source will be paused when it's end is reached
-        *        - false if the handle won't kept or is invalid.
-        */
-       virtual bool getKeep(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the behaviour of the device for a played back sound when the sound
-        * doesn't return any more samples.
-        * \param handle The handle returned by the play function.
-        * \param keep True when the source should be paused and not deleted.
-        * \return
-        *        - true if the behaviour has been changed.
-        *        - false if the handle is invalid.
-        */
-       virtual bool setKeep(AUD_Handle* handle, bool keep)=0;
-
-       /**
-        * Seeks in a played back sound.
-        * \param handle The handle returned by the play function.
-        * \param position The new position from where to play back, in seconds.
-        * \return
-        *        - true if the handle is valid.
-        *        - false if the handle is invalid.
-        * \warning Whether the seek works or not depends on the sound source.
-        */
-       virtual bool seek(AUD_Handle* handle, float position)=0;
-
-       /**
-        * Retrieves the current playback position of a sound.
-        * \param handle The handle returned by the play function.
-        * \return The playback position in seconds, or 0.0 if the handle is
-        *         invalid.
-        */
-       virtual float getPosition(AUD_Handle* handle)=0;
-
-       /**
-        * Returns the status of a played back sound.
-        * \param handle The handle returned by the play function.
-        * \return
-        *        - AUD_STATUS_INVALID if the sound has stopped or the handle is
-        *.         invalid
-        *        - AUD_STATUS_PLAYING if the sound is currently played back.
-        *        - AUD_STATUS_PAUSED if the sound is currently paused.
-        * \see AUD_Status
-        */
-       virtual AUD_Status getStatus(AUD_Handle* handle)=0;
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false)=0;
 
        /**
         * Locks the device.
@@ -196,69 +110,6 @@ public:
         * \param volume The overall device volume.
         */
        virtual void setVolume(float volume)=0;
-
-       /**
-        * Retrieves the volume of a playing sound.
-        * \param handle The sound handle.
-        * \return The volume.
-        */
-       virtual float getVolume(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the volume of a playing sound.
-        * \param handle The sound handle.
-        * \param volume The volume.
-        * \return
-        *        - true if the handle is valid.
-        *        - false if the handle is invalid.
-        */
-       virtual bool setVolume(AUD_Handle* handle, float volume)=0;
-
-       /**
-        * Retrieves the pitch of a playing sound.
-        * \return The pitch.
-        */
-       virtual float getPitch(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the pitch of a playing sound.
-        * \param handle The sound handle.
-        * \param pitch The pitch.
-        * \return
-        *        - true if the handle is valid.
-        *        - false if the handle is invalid.
-        */
-       virtual bool setPitch(AUD_Handle* handle, float pitch)=0;
-
-       /**
-        * Retrieves the loop count of a playing sound.
-        * A negative value indicates infinity.
-        * \return The remaining loop count.
-        */
-       virtual int getLoopCount(AUD_Handle* handle)=0;
-
-       /**
-        * Sets the loop count of a playing sound.
-        * A negative value indicates infinity.
-        * \param handle The sound handle.
-        * \param count The new loop count.
-        * \return
-        *        - true if the handle is valid.
-        *        - false if the handle is invalid.
-        */
-       virtual bool setLoopCount(AUD_Handle* handle, int count)=0;
-
-       /**
-        * Sets the callback function that's called when the end of a playing sound
-        * is reached.
-        * \param handle The sound handle.
-        * \param callback The callback function.
-        * \param data The data that should be passed to the callback function.
-        * \return
-        *        - true if the handle is valid.
-        *        - false if the handle is invalid.
-        */
-       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0;
 };
 
 #endif //AUD_IDevice
diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h
new file mode 100644 (file)
index 0000000..51d8e0c
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_IHandle.h
+ *  \ingroup audaspaceintern
+ */
+
+#ifndef AUD_IHANDLE
+#define AUD_IHANDLE
+
+//#include "AUD_Space.h"
+//#include "AUD_Reference.h"
+
+typedef void (*stopCallback)(void*);
+
+/**
+ * This class represents a playback handles for specific devices.
+ */
+class AUD_IHandle
+{
+public:
+       /**
+        * Destroys the device.
+        */
+       virtual ~AUD_IHandle() {}
+
+       /**
+        * Pauses a played back sound.
+        * \return
+        *        - true if the sound has been paused.
+        *        - false if the sound isn't playing back or the handle is invalid.
+        */
+       virtual bool pause()=0;
+
+       /**
+        * Resumes a paused sound.
+        * \return
+        *        - true if the sound has been resumed.
+        *        - false if the sound isn't paused or the handle is invalid.
+        */
+       virtual bool resume()=0;
+
+       /**
+        * Stops a played back or paused sound. The handle is definitely invalid
+        * afterwards.
+        * \return
+        *        - true if the sound has been stopped.
+        *        - false if the handle is invalid.
+        */
+       virtual bool stop()=0;
+
+       /**
+        * Gets the behaviour of the device for a played back sound when the sound
+        * doesn't return any more samples.
+        * \return
+        *        - true if the source will be paused when it's end is reached
+        *        - false if the handle won't kept or is invalid.
+        */
+       virtual bool getKeep()=0;
+
+       /**
+        * Sets the behaviour of the device for a played back sound when the sound
+        * doesn't return any more samples.
+        * \param keep True when the source should be paused and not deleted.
+        * \return
+        *        - true if the behaviour has been changed.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setKeep(bool keep)=0;
+
+       /**
+        * Seeks in a played back sound.
+        * \param position The new position from where to play back, in seconds.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        * \warning Whether the seek works or not depends on the sound source.
+        */
+       virtual bool seek(float position)=0;
+
+       /**
+        * Retrieves the current playback position of a sound.
+        * \return The playback position in seconds, or 0.0 if the handle is
+        *         invalid.
+        */
+       virtual float getPosition()=0;
+
+       /**
+        * Returns the status of a played back sound.
+        * \return
+        *        - AUD_STATUS_INVALID if the sound has stopped or the handle is
+        *.         invalid
+        *        - AUD_STATUS_PLAYING if the sound is currently played back.
+        *        - AUD_STATUS_PAUSED if the sound is currently paused.
+        * \see AUD_Status
+        */
+       virtual AUD_Status getStatus()=0;
+
+       /**
+        * Retrieves the volume of a playing sound.
+        * \return The volume.
+        */
+       virtual float getVolume()=0;
+
+       /**
+        * Sets the volume of a playing sound.
+        * \param volume The volume.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setVolume(float volume)=0;
+
+       /**
+        * Retrieves the pitch of a playing sound.
+        * \return The pitch.
+        */
+       virtual float getPitch()=0;
+
+       /**
+        * Sets the pitch of a playing sound.
+        * \param pitch The pitch.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setPitch(float pitch)=0;
+
+       /**
+        * Retrieves the loop count of a playing sound.
+        * A negative value indicates infinity.
+        * \return The remaining loop count.
+        */
+       virtual int getLoopCount()=0;
+
+       /**
+        * Sets the loop count of a playing sound.
+        * A negative value indicates infinity.
+        * \param count The new loop count.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setLoopCount(int count)=0;
+
+       /**
+        * Sets the callback function that's called when the end of a playing sound
+        * is reached.
+        * \param callback The callback function.
+        * \param data The data that should be passed to the callback function.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setStopCallback(stopCallback callback = 0, void* data = 0)=0;
+};
+
+#endif //AUD_IHandle
index 09fc483597850af56aa1bf8adeec9d23cacdc2b8..6cb13111a430fed963fcb3cb46cf3acc3cb22226 100644 (file)
@@ -34,6 +34,7 @@
 #include "AUD_NULLDevice.h"
 #include "AUD_IReader.h"
 #include "AUD_IFactory.h"
+#include "AUD_IHandle.h"
 
 AUD_NULLDevice::AUD_NULLDevice()
 {
@@ -48,56 +49,16 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const
        return specs;
 }
 
-AUD_Handle* AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
+AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
 {
        return 0;
 }
 
-AUD_Handle* AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
+AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
 {
        return 0;
 }
 
-bool AUD_NULLDevice::pause(AUD_Handle* handle)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::resume(AUD_Handle* handle)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::stop(AUD_Handle* handle)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::getKeep(AUD_Handle* handle)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::seek(AUD_Handle* handle, float position)
-{
-       return false;
-}
-
-float AUD_NULLDevice::getPosition(AUD_Handle* handle)
-{
-       return std::numeric_limits<float>::quiet_NaN();
-}
-
-AUD_Status AUD_NULLDevice::getStatus(AUD_Handle* handle)
-{
-       return AUD_STATUS_INVALID;
-}
-
 void AUD_NULLDevice::lock()
 {
 }
@@ -114,38 +75,3 @@ float AUD_NULLDevice::getVolume() const
 void AUD_NULLDevice::setVolume(float volume)
 {
 }
-
-float AUD_NULLDevice::getVolume(AUD_Handle* handle)
-{
-       return std::numeric_limits<float>::quiet_NaN();
-}
-
-bool AUD_NULLDevice::setVolume(AUD_Handle* handle, float volume)
-{
-       return false;
-}
-
-float AUD_NULLDevice::getPitch(AUD_Handle* handle)
-{
-       return std::numeric_limits<float>::quiet_NaN();
-}
-
-bool AUD_NULLDevice::setPitch(AUD_Handle* handle, float pitch)
-{
-       return false;
-}
-
-int AUD_NULLDevice::getLoopCount(AUD_Handle* handle)
-{
-       return 0;
-}
-
-bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count)
-{
-       return false;
-}
-
-bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
-{
-       return false;
-}
index 6a10267bbe03766b4dcbaaff3abbedbe4e31ee67..69ca5b74f3b52fe86fe62094b78c9fe90e6b757f 100644 (file)
@@ -47,27 +47,12 @@ public:
        AUD_NULLDevice();
 
        virtual AUD_DeviceSpecs getSpecs() const;
-       virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false);
-       virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
-       virtual bool pause(AUD_Handle* handle);
-       virtual bool resume(AUD_Handle* handle);
-       virtual bool stop(AUD_Handle* handle);
-       virtual bool getKeep(AUD_Handle* handle);
-       virtual bool setKeep(AUD_Handle* handle, bool keep);
-       virtual bool seek(AUD_Handle* handle, float position);
-       virtual float getPosition(AUD_Handle* handle);
-       virtual AUD_Status getStatus(AUD_Handle* handle);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
        virtual void lock();
        virtual void unlock();
        virtual float getVolume() const;
        virtual void setVolume(float volume);
-       virtual float getVolume(AUD_Handle* handle);
-       virtual bool setVolume(AUD_Handle* handle, float volume);
-       virtual float getPitch(AUD_Handle* handle);
-       virtual bool setPitch(AUD_Handle* handle, float pitch);
-       virtual int getLoopCount(AUD_Handle* handle);
-       virtual bool setLoopCount(AUD_Handle* handle, int count);
-       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0);
 };
 
 #endif //AUD_NULLDEVICE
index 22abb29bdbbeea1ec058ec19d0cebc33488dbcdc..4cc5c51d24d1850235a8ae1101ea4531a6289ccc 100644 (file)
  *  \ingroup audaspaceintern
  */
 
-
 #ifndef AUD_REFERENCE
 #define AUD_REFERENCE
 
+#include <map>
+
+class AUD_ReferenceHandler
+{
+private:
+       static std::map<void*, int> m_references;
+
+public:
+       static inline void incref(void* reference)
+       {
+               std::map<void*, int>::iterator result = m_references.find(reference);
+               if(result != m_references.end())
+               {
+                       m_references[reference]++;
+               }
+               else
+               {
+                       m_references[reference] = 1;
+               }
+       }
+
+       static inline bool decref(void* reference)
+       {
+               if(!--m_references[reference])
+               {
+                       m_references.erase(reference);
+                       return true;
+               }
+               return false;
+       }
+};
+
 template <class T>
 /**
  * This class provides reference counting functionality.
@@ -41,8 +72,7 @@ class AUD_Reference
 private:
        /// The reference.
        T* m_reference;
-       /// The reference counter.
-       int* m_refcount;
+       void* m_original;
 public:
        /**
         * Creates a new reference counter.
@@ -50,9 +80,8 @@ public:
         */
        AUD_Reference(T* reference = 0)
        {
-               m_reference = reference;
-               m_refcount = new int;
-               *m_refcount = 1;
+               m_original = m_reference = reference;
+               AUD_ReferenceHandler::incref(reference);
        }
 
        /**
@@ -61,9 +90,16 @@ public:
         */
        AUD_Reference(const AUD_Reference& ref)
        {
-               m_reference = ref.m_reference;
-               m_refcount = ref.m_refcount;
-               (*m_refcount)++;
+               m_original = m_reference = ref.m_reference;
+               AUD_ReferenceHandler::incref(m_reference);
+       }
+
+       template <class U>
+       explicit AUD_Reference(const AUD_Reference<U>& ref)
+       {
+               m_original = ref.get();
+               m_reference = dynamic_cast<T*>(ref.get());
+               AUD_ReferenceHandler::incref(m_original);
        }
 
        /**
@@ -72,12 +108,8 @@ public:
         */
        ~AUD_Reference()
        {
-               (*m_refcount)--;
-               if(*m_refcount == 0)
-               {
+               if(AUD_ReferenceHandler::decref(m_original))
                        delete m_reference;
-                       delete m_refcount;
-               }
        }
 
        /**
@@ -89,16 +121,12 @@ public:
                if(&ref == this)
                        return *this;
 
-               (*m_refcount)--;
-               if(*m_refcount == 0)
-               {
+               if(AUD_ReferenceHandler::decref(m_original))
                        delete m_reference;
-                       delete m_refcount;
-               }
 
+               m_original = ref.m_original;
                m_reference = ref.m_reference;
-               m_refcount = ref.m_refcount;
-               (*m_refcount)++;
+               AUD_ReferenceHandler::incref(m_original);
 
                return *this;
        }
@@ -106,7 +134,7 @@ public:
        /**
         * Returns whether the reference is NULL.
         */
-       bool isNull() const
+       inline bool isNull() const
        {
                return m_reference == 0;
        }
@@ -114,15 +142,20 @@ public:
        /**
         * Returns the reference.
         */
-       T* get() const
+       inline T* get() const
        {
                return m_reference;
        }
 
+       inline void* getOriginal() const
+       {
+               return m_original;
+       }
+
        /**
         * Returns the reference.
         */
-       T& operator*() const
+       inline T& operator*() const
        {
                return *m_reference;
        }
@@ -130,44 +163,22 @@ public:
        /**
         * Returns the reference.
         */
-       T* operator->() const
+       inline T* operator->() const
        {
                return m_reference;
        }
-
-       template <class U>
-       explicit AUD_Reference(U* reference, int* refcount)
-       {
-               m_reference = dynamic_cast<T*>(reference);
-               if(m_reference)
-               {
-                       m_refcount = refcount;
-                       (*m_refcount)++;
-               }
-               else
-               {
-                       m_refcount = new int;
-                       *m_refcount = 1;
-               }
-       }
-
-       template <class U>
-       AUD_Reference<U> convert()
-       {
-               return AUD_Reference<U>(m_reference, m_refcount);
-       }
 };
 
 template<class T, class U>
-bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
+inline bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
 {
-       return a.get() == b.get();
+       return a.getOriginal() == b.getOriginal();
 }
 
 template<class T, class U>
-bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
+inline bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
 {
-       return a.get() == b.get();
+       return a.getOriginal() != b.getOriginal();
 }
 
 #endif // AUD_REFERENCE
diff --git a/intern/audaspace/intern/AUD_ReferenceHandler.cpp b/intern/audaspace/intern/AUD_ReferenceHandler.cpp
new file mode 100644 (file)
index 0000000..cfc3c94
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_Reference.cpp
+ *  \ingroup audaspaceintern
+ */
+
+#include "AUD_Reference.h"
+
+std::map<void*, int> AUD_ReferenceHandler::m_references;
index 47d5243c04e34b2e389eab84cf502c23db56b7d7..1787dea0ebbfd83e95c37a6c9109bb40c7803040 100644 (file)
@@ -108,7 +108,7 @@ AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
                                                                                                                  m_volume);
        m_readers.push_front(reader);
 
-       return reader.convert<AUD_IReader>();
+       return AUD_Reference<AUD_IReader>(reader);
 }
 
 void AUD_SequencerFactory::removeReader(AUD_Reference<AUD_SequencerReader> reader)
index f522772fc61c3d666e1ab36960884aada950a8ab..8ca735e9ad923f87536383eb261390002b6e6e42 100644 (file)
 #include <cstring>
 #include <limits>
 
-/// Saves the data for playback.
-struct AUD_SoftwareHandle : AUD_Handle
+typedef std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> >::iterator AUD_HandleIterator;
+
+AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, bool keep) :
+       m_reader(reader), m_keep(keep), m_volume(1.0f), m_loopcount(0),
+       m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
+{
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
+{
+       if(m_status)
+       {
+               m_device->lock();
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       m_device->m_playingSounds.remove(this);
+                       m_device->m_pausedSounds.push_back(this);
+
+                       if(m_device->m_playingSounds.empty())
+                               m_device->playing(m_device->m_playback = false);
+                       m_status = AUD_STATUS_PAUSED;
+                       m_device->unlock();
+
+                       return true;
+               }
+
+               m_device->unlock();
+       }
+
+       return false;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume()
+{
+       if(m_status)
+       {
+               m_device->lock();
+
+               if(m_status == AUD_STATUS_PAUSED)
+               {
+                       m_device->m_pausedSounds.remove(this);
+                       m_device->m_playingSounds.push_back(this);
+
+                       if(!m_device->m_playback)
+                               m_device->playing(m_device->m_playback = true);
+                       m_status = AUD_STATUS_PLAYING;
+                       m_device->unlock();
+                       return true;
+               }
+
+               m_device->unlock();
+       }
+
+       return false;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop()
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       if(m_status == AUD_STATUS_PLAYING)
+       {
+               m_device->m_playingSounds.remove(this);
+
+               if(m_device->m_playingSounds.empty())
+                       m_device->playing(m_device->m_playback = false);
+       }
+       else
+               m_device->m_pausedSounds.remove(this);
+
+       m_device->unlock();
+       m_status = AUD_STATUS_INVALID;
+       return true;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep()
+{
+       if(m_status)
+               return m_keep;
+
+       return false;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_keep = keep;
+
+       m_device->unlock();
+
+       return true;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position)
 {
-       /// The reader source.
-       AUD_Reference<AUD_IReader> reader;
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_reader->seek((int)(position * m_reader->getSpecs().rate));
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition()
+{
+       if(!m_status)
+               return 0.0f;
+
+       m_device->lock();
+
+       float position = m_reader->getPosition() / (float)m_device->m_specs.rate;
+
+       m_device->unlock();
+
+       return position;
+}
+
+AUD_Status AUD_SoftwareDevice::AUD_SoftwareHandle::getStatus()
+{
+       return m_status;
+}
+
+float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolume()
+{
+       return m_volume;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume)
+{
+       if(!m_status)
+               return false;
+       m_volume = volume;
+       return true;
+}
+
+float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch()
+{
+       return std::numeric_limits<float>::quiet_NaN();
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch)
+{
+       return false;
+}
+
+int AUD_SoftwareDevice::AUD_SoftwareHandle::getLoopCount()
+{
+       if(!m_status)
+               return 0;
+       return m_loopcount;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count)
+{
+       if(!m_status)
+               return false;
+       m_loopcount = count;
+       return true;
+}
+
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callback, void* data)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_stop = callback;
+       m_stop_data = data;
+
+       m_device->unlock();
+
+       return true;
+}
+
+
+
+
 
-       /// Whether to keep the source if end of it is reached.
-       bool keep;
 
-       /// The volume of the source.
-       float volume;
 
-       /// The loop count of the source.
-       int loopcount;
 
-       /// The stop callback.
-       stopCallback stop;
 
-       /// Stop callback data.
-       void* stop_data;
-};
 
-typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
 
 void AUD_SoftwareDevice::create()
 {
@@ -81,23 +254,11 @@ void AUD_SoftwareDevice::destroy()
        if(m_playback)
                playing(m_playback = false);
 
-       AUD_SoftwareHandle* handle;
-
-       // delete all playing sounds
        while(!m_playingSounds.empty())
-       {
-               handle = m_playingSounds.front();
-               m_playingSounds.pop_front();
-               delete handle;
-       }
+               m_playingSounds.front()->stop();
 
-       // delete all paused sounds
        while(!m_pausedSounds.empty())
-       {
-               handle = m_pausedSounds.front();
-               m_pausedSounds.pop_front();
-               delete handle;
-       }
+               m_pausedSounds.front()->stop();
 
        pthread_mutex_destroy(&m_mutex);
 }
@@ -109,11 +270,11 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
        lock();
 
        {
-               AUD_SoftwareHandle* sound;
+               AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound;
                int len;
                int pos;
                bool eos;
-               std::list<AUD_SoftwareHandle*> stopSounds;
+               std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds;
                sample_t* buf = m_buffer.getBuffer();
 
                m_mixer->clear(length);
@@ -131,39 +292,38 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                        pos = 0;
                        len = length;
 
-                       sound->reader->read(len, eos, buf);
+                       sound->m_reader->read(len, eos, buf);
 
                        // in case of looping
-                       while(pos + len < length && sound->loopcount && eos)
+                       while(pos + len < length && sound->m_loopcount && eos)
                        {
-                               m_mixer->mix(buf, pos, len, sound->volume);
+                               m_mixer->mix(buf, pos, len, sound->m_volume);
 
                                pos += len;
 
-                               if(sound->loopcount > 0)
-                                       sound->loopcount--;
+                               if(sound->m_loopcount > 0)
+                                       sound->m_loopcount--;
 
-                               sound->reader->seek(0);
+                               sound->m_reader->seek(0);
 
                                len = length - pos;
-                               sound->reader->read(len, eos, buf);
+                               sound->m_reader->read(len, eos, buf);
 
                                // prevent endless loop
                                if(!len)
                                        break;
                        }
 
-                       m_mixer->mix(buf, pos, len, sound->volume);
-                       pos += len;
+                       m_mixer->mix(buf, pos, len, sound->m_volume);
 
                        // in case the end of the sound is reached
-                       if(eos && !sound->loopcount)
+                       if(eos && !sound->m_loopcount)
                        {
-                               if(sound->stop)
-                                       sound->stop(sound->stop_data);
+                               if(sound->m_stop)
+                                       sound->m_stop(sound->m_stop_data);
 
-                               if(sound->keep)
-                                       pause(sound);
+                               if(sound->m_keep)
+                                       sound->pause();
                                else
                                        stopSounds.push_back(sound);
                        }
@@ -177,32 +337,19 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                {
                        sound = stopSounds.front();
                        stopSounds.pop_front();
-                       stop(sound);
+                       sound->stop();
                }
        }
 
        unlock();
 }
 
-bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
-{
-       for(AUD_HandleIterator i = m_playingSounds.begin();
-               i != m_playingSounds.end(); i++)
-               if(*i == handle)
-                       return true;
-       for(AUD_HandleIterator i = m_pausedSounds.begin();
-               i != m_pausedSounds.end(); i++)
-               if(*i == handle)
-                       return true;
-       return false;
-}
-
 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
 {
        return m_specs;
 }
 
-AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
+AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
 {
        // prepare the reader
        reader = m_mixer->prepare(reader);
@@ -210,13 +357,7 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool kee
                return NULL;
 
        // play sound
-       AUD_SoftwareHandle* sound = new AUD_SoftwareHandle;
-       sound->keep = keep;
-       sound->reader = reader;
-       sound->volume = 1.0f;
-       sound->loopcount = 0;
-       sound->stop = NULL;
-       sound->stop_data = NULL;
+       AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, keep);
 
        lock();
        m_playingSounds.push_back(sound);
@@ -225,204 +366,14 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool kee
                playing(m_playback = true);
        unlock();
 
-       return sound;
+       return AUD_Reference<AUD_IHandle>(sound);
 }
 
-AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
+AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
 {
        return play(factory->createReader(), keep);
 }
 
-bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are played can be paused
-       for(AUD_HandleIterator i = m_playingSounds.begin();
-               i != m_playingSounds.end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_pausedSounds.push_back(*i);
-                       m_playingSounds.erase(i);
-                       if(m_playingSounds.empty())
-                               playing(m_playback = false);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are paused can be resumed
-       for(AUD_HandleIterator i = m_pausedSounds.begin();
-               i != m_pausedSounds.end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_playingSounds.push_back(*i);
-                       m_pausedSounds.erase(i);
-                       if(!m_playback)
-                               playing(m_playback = true);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds.begin();
-               i != m_playingSounds.end(); i++)
-       {
-               if(*i == handle)
-               {
-                       delete *i;
-                       m_playingSounds.erase(i);
-                       if(m_playingSounds.empty())
-                               playing(m_playback = false);
-                       result = true;
-                       break;
-               }
-       }
-       if(!result)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds.begin();
-                       i != m_pausedSounds.end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               delete *i;
-                               m_pausedSounds.erase(i);
-                               result = true;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-               result = ((AUD_SoftwareHandle*)handle)->keep;
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               ((AUD_SoftwareHandle*)handle)->keep = keep;
-               result = true;
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position)
-{
-       lock();
-
-       bool result = false;
-
-       if(isValid(handle))
-       {
-               AUD_Reference<AUD_IReader> reader = ((AUD_SoftwareHandle*)handle)->reader;
-               reader->seek((int)(position * reader->getSpecs().rate));
-               result = true;
-       }
-
-       unlock();
-
-       return result;
-}
-
-float AUD_SoftwareDevice::getPosition(AUD_Handle* handle)
-{
-       lock();
-
-       float position = 0.0f;
-
-       if(isValid(handle))
-       {
-               AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
-               position = h->reader->getPosition() / (float)m_specs.rate;
-       }
-
-       unlock();
-
-       return position;
-}
-
-AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
-{
-       AUD_Status status = AUD_STATUS_INVALID;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds.begin();
-               i != m_playingSounds.end(); i++)
-       {
-               if(*i == handle)
-               {
-                       status = AUD_STATUS_PLAYING;
-                       break;
-               }
-       }
-       if(status == AUD_STATUS_INVALID)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds.begin();
-                       i != m_pausedSounds.end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               status = AUD_STATUS_PAUSED;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
-
-       return status;
-}
-
 void AUD_SoftwareDevice::lock()
 {
        pthread_mutex_lock(&m_mutex);
@@ -442,67 +393,3 @@ void AUD_SoftwareDevice::setVolume(float volume)
 {
        m_volume = volume;
 }
-
-float AUD_SoftwareDevice::getVolume(AUD_Handle* handle)
-{
-       lock();
-       float result = std::numeric_limits<float>::quiet_NaN();
-       if(isValid(handle))
-               result = ((AUD_SoftwareHandle*)handle)->volume;
-       unlock();
-       return result;
-}
-
-bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume)
-{
-       lock();
-       bool result = isValid(handle);
-       if(result)
-               ((AUD_SoftwareHandle*)handle)->volume = volume;
-       unlock();
-       return result;
-}
-
-float AUD_SoftwareDevice::getPitch(AUD_Handle* handle)
-{
-       return std::numeric_limits<float>::quiet_NaN();
-}
-
-bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch)
-{
-       return false;
-}
-
-int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle)
-{
-       lock();
-       int result = 0;
-       if(isValid(handle))
-               result = ((AUD_SoftwareHandle*)handle)->loopcount;
-       unlock();
-       return result;
-}
-
-bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count)
-{
-       lock();
-       bool result = isValid(handle);
-       if(result)
-               ((AUD_SoftwareHandle*)handle)->loopcount = count;
-       unlock();
-       return result;
-}
-
-bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
-{
-       lock();
-       bool result = isValid(handle);
-       if(result)
-       {
-               AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
-               h->stop = callback;
-               h->stop_data = data;
-       }
-       unlock();
-       return result;
-}
index 6518afe6737e5140c58272551c1217d2ce941f1d..45df48d12be2ddae548067186052cd8d483283a6 100644 (file)
@@ -33,9 +33,9 @@
 #define AUD_SOFTWAREDEVICE
 
 #include "AUD_IDevice.h"
+#include "AUD_IHandle.h"
 #include "AUD_Mixer.h"
 #include "AUD_Buffer.h"
-struct AUD_SoftwareHandle;
 
 #include <list>
 #include <pthread.h>
@@ -51,6 +51,56 @@ struct AUD_SoftwareHandle;
 class AUD_SoftwareDevice : public AUD_IDevice
 {
 protected:
+       /// Saves the data for playback.
+       class AUD_SoftwareHandle : public AUD_IHandle
+       {
+       public:
+               /// The reader source.
+               AUD_Reference<AUD_IReader> m_reader;
+
+               /// Whether to keep the source if end of it is reached.
+               bool m_keep;
+
+               /// The volume of the source.
+               float m_volume;
+
+               /// The loop count of the source.
+               int m_loopcount;
+
+               /// The stop callback.
+               stopCallback m_stop;
+
+               /// Stop callback data.
+               void* m_stop_data;
+
+               /// Current status of the handle
+               AUD_Status m_status;
+
+               /// Own device.
+               AUD_SoftwareDevice* m_device;
+
+       public:
+
+               AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, bool keep);
+
+               virtual ~AUD_SoftwareHandle() {}
+               virtual bool pause();
+               virtual bool resume();
+               virtual bool stop();
+               virtual bool getKeep();
+               virtual bool setKeep(bool keep);
+               virtual bool seek(float position);
+               virtual float getPosition();
+               virtual AUD_Status getStatus();
+               virtual float getVolume();
+               virtual bool setVolume(float volume);
+               virtual float getPitch();
+               virtual bool setPitch(float pitch);
+               virtual int getLoopCount();
+               virtual bool setLoopCount(int count);
+               virtual bool setStopCallback(stopCallback callback = 0, void* data = 0);
+       };
+
        /**
         * The specification of the device.
         */
@@ -93,12 +143,12 @@ private:
        /**
         * The list of sounds that are currently playing.
         */
-       std::list<AUD_SoftwareHandle*> m_playingSounds;
+       std::list<AUD_Reference<AUD_SoftwareHandle> > m_playingSounds;
 
        /**
         * The list of sounds that are currently paused.
         */
-       std::list<AUD_SoftwareHandle*> m_pausedSounds;
+       std::list<AUD_Reference<AUD_SoftwareHandle> > m_pausedSounds;
 
        /**
         * Whether there is currently playback.
@@ -115,36 +165,14 @@ private:
         */
        float m_volume;
 
-       /**
-        * Checks if a handle is valid.
-        * \param handle The handle to check.
-        * \return Whether the handle is valid.
-        */
-       bool isValid(AUD_Handle* handle);
-
 public:
        virtual AUD_DeviceSpecs getSpecs() const;
-       virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false);
-       virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
-       virtual bool pause(AUD_Handle* handle);
-       virtual bool resume(AUD_Handle* handle);
-       virtual bool stop(AUD_Handle* handle);
-       virtual bool getKeep(AUD_Handle* handle);
-       virtual bool setKeep(AUD_Handle* handle, bool keep);
-       virtual bool seek(AUD_Handle* handle, float position);
-       virtual float getPosition(AUD_Handle* handle);
-       virtual AUD_Status getStatus(AUD_Handle* handle);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
        virtual void lock();
        virtual void unlock();
        virtual float getVolume() const;
        virtual void setVolume(float volume);
-       virtual float getVolume(AUD_Handle* handle);
-       virtual bool setVolume(AUD_Handle* handle, float volume);
-       virtual float getPitch(AUD_Handle* handle);
-       virtual bool setPitch(AUD_Handle* handle, float pitch);
-       virtual int getLoopCount(AUD_Handle* handle);
-       virtual bool setLoopCount(AUD_Handle* handle, int count);
-       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
 };
 
 #endif //AUD_SOFTWAREDEVICE
index 9e9df24be320766d21ff3d77e66285472c9df621..18eab71692428c912c6e791e55ec555b82c43ecf 100644 (file)
@@ -51,7 +51,8 @@ static void sound_sync_callback(void* data, int mode, float time)
                                sound_play_scene(scene);
                        else
                                sound_stop_scene(scene);
-                       AUD_seek(scene->sound_scene_handle, time);
+                       if(scene->sound_scene_handle)
+                               AUD_seek(scene->sound_scene_handle, time);
                }
                scene = scene->id.next;
        }
@@ -345,7 +346,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
 
        AUD_setDeviceVolume(mixdown, volume);
 
-       AUD_playDevice(mixdown, scene->sound_scene, start / FPS);
+       AUD_freeChannel(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
 
        return mixdown;
 }
@@ -353,12 +354,16 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
 void sound_create_scene(struct Scene *scene)
 {
        scene->sound_scene = AUD_createSequencer(scene->audio.flag & AUDIO_MUTE, scene, (AUD_volumeFunction)&sound_get_volume);
+       scene->sound_scene_handle = NULL;
+       scene->sound_scrub_handle = NULL;
 }
 
 void sound_destroy_scene(struct Scene *scene)
 {
        if(scene->sound_scene_handle)
                AUD_stop(scene->sound_scene_handle);
+       if(scene->sound_scrub_handle)
+               AUD_stop(scene->sound_scrub_handle);
        if(scene->sound_scene)
                AUD_destroySequencer(scene->sound_scene);
 }
@@ -398,8 +403,10 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i
 
 static void sound_start_play_scene(struct Scene *scene)
 {
-       scene->sound_scene_handle = AUD_play(scene->sound_scene, 1);
-       AUD_setLoop(scene->sound_scene_handle, -1);
+       if(scene->sound_scene_handle)
+               AUD_stop(scene->sound_scene_handle);
+       if((scene->sound_scene_handle = AUD_play(scene->sound_scene, 1)))
+               AUD_setLoop(scene->sound_scene_handle, -1);
 }
 
 void sound_play_scene(struct Scene *scene)
@@ -407,11 +414,17 @@ void sound_play_scene(struct Scene *scene)
        AUD_Status status;
        AUD_lock();
 
-       status = AUD_getStatus(scene->sound_scene_handle);
+       status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID;
 
        if(status == AUD_STATUS_INVALID)
                sound_start_play_scene(scene);
 
+       if(!scene->sound_scene_handle)
+       {
+               AUD_unlock();
+               return;
+       }
+
        if(status != AUD_STATUS_PLAYING)
        {
                AUD_seek(scene->sound_scene_handle, CFRA / FPS);
@@ -426,10 +439,13 @@ void sound_play_scene(struct Scene *scene)
 
 void sound_stop_scene(struct Scene *scene)
 {
-       AUD_pause(scene->sound_scene_handle);
+       if(scene->sound_scene_handle)
+       {
+               AUD_pause(scene->sound_scene_handle);
 
-       if(scene->audio.flag & AUDIO_SYNC)
-               AUD_stopPlayback();
+               if(scene->audio.flag & AUDIO_SYNC)
+                       AUD_stopPlayback();
+       }
 }
 
 void sound_seek_scene(struct bContext *C)
@@ -439,11 +455,18 @@ void sound_seek_scene(struct bContext *C)
 
        AUD_lock();
 
-       status = AUD_getStatus(scene->sound_scene_handle);
+       status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID;
 
        if(status == AUD_STATUS_INVALID)
        {
                sound_start_play_scene(scene);
+
+               if(!scene->sound_scene_handle)
+               {
+                       AUD_unlock();
+                       return;
+               }
+
                AUD_pause(scene->sound_scene_handle);
        }
 
@@ -457,10 +480,14 @@ void sound_seek_scene(struct bContext *C)
                else
                        AUD_seek(scene->sound_scene_handle, CFRA / FPS);
                AUD_resume(scene->sound_scene_handle);
-               if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
+               if(scene->sound_scrub_handle && AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
                        AUD_seek(scene->sound_scrub_handle, 0);
                else
+               {
+                       if(scene->sound_scrub_handle)
+                               AUD_stop(scene->sound_scrub_handle);
                        scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS);
+               }
        }
        else
        {
@@ -478,10 +505,14 @@ void sound_seek_scene(struct bContext *C)
 
 float sound_sync_scene(struct Scene *scene)
 {
-       if(scene->audio.flag & AUDIO_SYNC)
-               return AUD_getSequencerPosition(scene->sound_scene_handle);
-       else
-               return AUD_getPosition(scene->sound_scene_handle);
+       if(scene->sound_scene_handle)
+       {
+               if(scene->audio.flag & AUDIO_SYNC)
+                       return AUD_getSequencerPosition(scene->sound_scene_handle);
+               else
+                       return AUD_getPosition(scene->sound_scene_handle);
+       }
+       return 0.0f;
 }
 
 int sound_scene_playing(struct Scene *scene)
index 5a19337e7a2570f1e143e11618e89f93ecab2fd2..6f8bb4bf087b4a7fe465f315dc69ce530e1b2918 100644 (file)
@@ -75,7 +75,10 @@ KX_SoundActuator::~KX_SoundActuator()
 void KX_SoundActuator::play()
 {
        if(m_handle)
+       {
                AUD_stop(m_handle);
+               m_handle = NULL;
+       }
 
        if(!m_sound)
                return;
@@ -103,11 +106,16 @@ void KX_SoundActuator::play()
                break;
        }
 
+       m_handle = AUD_play(sound, 0);
+
+       if(sound2)
+               AUD_unload(sound2);
+
+       if(!m_handle)
+               return;
+
        if(m_is3d)
        {
-               // sound shall be played 3D
-               m_handle = AUD_play(sound, 0);
-
                AUD_setRelative(m_handle, false);
                AUD_setVolumeMaximum(m_handle, m_3d.max_gain);
                AUD_setVolumeMinimum(m_handle, m_3d.min_gain);
@@ -118,17 +126,12 @@ void KX_SoundActuator::play()
                AUD_setConeAngleOuter(m_handle, m_3d.cone_outer_angle);
                AUD_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain);
        }
-       else
-               m_handle = AUD_play(sound, 0);
 
        if(loop)
                AUD_setLoop(m_handle, -1);
        AUD_setSoundPitch(m_handle, m_pitch);
        AUD_setSoundVolume(m_handle, m_volume);
        m_isplaying = true;
-
-       if(sound2)
-               AUD_unload(sound2);
 }
 
 CValue* KX_SoundActuator::GetReplica()
@@ -160,7 +163,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
                return false;
 
        // actual audio device playing state
-       bool isplaying = AUD_getStatus(m_handle) == AUD_STATUS_PLAYING;
+       bool isplaying = m_handle ? (AUD_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
 
        if (bNegativeEvent)
        {
@@ -174,7 +177,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
                        case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
                                {
                                        // stop immediately
-                                       AUD_stop(m_handle);
+                                       if(m_handle)
+                                               AUD_stop(m_handle);
+                                       m_handle = NULL;
                                        break;
                                }
                        case KX_SOUNDACT_PLAYEND:
@@ -186,7 +191,8 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
                        case KX_SOUNDACT_LOOPBIDIRECTIONAL:
                                {
                                        // stop the looping so that the sound stops when it finished
-                                       AUD_setLoop(m_handle, 0);
+                                       if(m_handle)
+                                               AUD_setLoop(m_handle, 0);
                                        break;
                                }
                        default:
@@ -212,7 +218,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
                        play();
        }
        // verify that the sound is still playing
-       isplaying = AUD_getStatus(m_handle) == AUD_STATUS_PLAYING ? true : false;
+       isplaying = m_handle ? (AUD_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
 
        if (isplaying)
        {
@@ -301,15 +307,18 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound,
 "startSound()\n"
 "\tStarts the sound.\n")
 {
-       switch(AUD_getStatus(m_handle))
+       if(m_handle)
        {
-       case AUD_STATUS_PLAYING:
-               break;
-       case AUD_STATUS_PAUSED:
-               AUD_resume(m_handle);
-               break;
-       default:
-               play();
+               switch(AUD_getStatus(m_handle))
+               {
+               case AUD_STATUS_PLAYING:
+                       break;
+               case AUD_STATUS_PAUSED:
+                       AUD_resume(m_handle);
+                       break;
+               default:
+                       play();
+               }
        }
        Py_RETURN_NONE;
 }
@@ -318,7 +327,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound,
 "pauseSound()\n"
 "\tPauses the sound.\n")
 {
-       AUD_pause(m_handle);
+       if(m_handle)
+               AUD_pause(m_handle);
        Py_RETURN_NONE;
 }
 
@@ -326,7 +336,9 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
 "stopSound()\n"
 "\tStops the sound.\n")
 {
-       AUD_stop(m_handle);
+       if(m_handle)
+               AUD_stop(m_handle);
+       m_handle = NULL;
        Py_RETURN_NONE;
 }