Quellcode durchsuchen

Error handling improvements (2 of 7 - Animation and Audio systems).
Adds AL_CHECK and AL_LAST_ERROR macros (similar to the GL macros).

Chris Culy vor 13 Jahren
Ursprung
Commit
97e0defd80

+ 38 - 6
gameplay/src/Animation.cpp

@@ -45,7 +45,10 @@ Animation::~Animation()
     if (_defaultClip)
     {
         if (_defaultClip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
+        {
+            GP_ASSERT(_controller);
             _controller->unschedule(_defaultClip);
+        }
         SAFE_RELEASE(_defaultClip);
     }
 
@@ -56,8 +59,12 @@ Animation::~Animation()
         while (clipIter != _clips->end())
         {   
             AnimationClip* clip = *clipIter;
+            GP_ASSERT(clip);
             if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
+            {
+                GP_ASSERT(_controller);
                 _controller->unschedule(clip);
+            }
             SAFE_RELEASE(clip);
             clipIter++;
         }
@@ -69,6 +76,10 @@ Animation::~Animation()
 Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
     : _animation(animation), _target(target), _propertyId(propertyId), _curve(curve), _duration(duration)
 {
+    GP_ASSERT(_animation);
+    GP_ASSERT(_target);
+    GP_ASSERT(_curve);
+
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
     GP_ASSERT(_target->getAnimationPropertyComponentCount(propertyId));
     _curve->addRef();
@@ -79,6 +90,10 @@ Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int p
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
     : _animation(animation), _target(target), _propertyId(copy._propertyId), _curve(copy._curve), _duration(copy._duration)
 {
+    GP_ASSERT(_curve);
+    GP_ASSERT(_target);
+    GP_ASSERT(_animation);
+
     _curve->addRef();
     _target->addChannel(this);
     _animation->addRef();
@@ -107,8 +122,6 @@ unsigned long Animation::getDuration() const
 
 void Animation::createClips(const char* url)
 {
-    GP_ASSERT(url);
-
     Properties* properties = Properties::create(url);
     GP_ASSERT(properties);
 
@@ -116,7 +129,8 @@ void Animation::createClips(const char* url)
     GP_ASSERT(pAnimation);
     
     int frameCount = pAnimation->getInt("frameCount");
-    GP_ASSERT(frameCount > 0);
+    if (frameCount <= 0)
+        GP_ERROR("The animation's frame count must be greater than 0.");
 
     createClips(pAnimation, (unsigned int)frameCount);
 
@@ -171,7 +185,7 @@ void Animation::play(const char* clipId)
     }
     else
     {
-        // Find animation clip.. and play.
+        // Find animation clip and play.
         AnimationClip* clip = findClip(clipId);
         if (clip != NULL)
             clip->play();
@@ -188,7 +202,7 @@ void Animation::stop(const char* clipId)
     }
     else
     {
-        // Find animation clip.. and play.
+        // Find animation clip and play.
         AnimationClip* clip = findClip(clipId);
         if (clip != NULL)
             clip->stop();
@@ -214,6 +228,7 @@ bool Animation::targets(AnimationTarget* target) const
 {
     for (std::vector<Animation::Channel*>::const_iterator itr = _channels.begin(); itr != _channels.end(); ++itr)
     {
+        GP_ASSERT(*itr);
         if ((*itr)->_target == target)
         {
             return true;
@@ -272,6 +287,7 @@ void Animation::addClip(AnimationClip* clip)
     if (_clips == NULL)
         _clips = new std::vector<AnimationClip*>;
 
+    GP_ASSERT(clip);
     _clips->push_back(clip);
 }
 
@@ -284,9 +300,10 @@ AnimationClip* Animation::findClip(const char* id) const
         for (unsigned int i = 0; i < clipCount; i++)
         {
             clip = _clips->at(i);
+            GP_ASSERT(clip);
             if (clip->_id.compare(id) == 0)
             {
-                return _clips->at(i);
+                return clip;
             }
         }
     }
@@ -295,10 +312,15 @@ AnimationClip* Animation::findClip(const char* id) const
 
 Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type)
 {
+    GP_ASSERT(target);
+    GP_ASSERT(keyTimes);
+    GP_ASSERT(keyValues);
+
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     GP_ASSERT(propertyComponentCount > 0);
 
     Curve* curve = Curve::create(keyCount, propertyComponentCount);
+    GP_ASSERT(curve);
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
 
@@ -332,10 +354,15 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
 Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
 {
+    GP_ASSERT(target);
+    GP_ASSERT(keyTimes);
+    GP_ASSERT(keyValues);
+
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     GP_ASSERT(propertyComponentCount > 0);
 
     Curve* curve = Curve::create(keyCount, propertyComponentCount);
+    GP_ASSERT(curve);
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
     
@@ -369,6 +396,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
 void Animation::addChannel(Channel* channel)
 {
+    GP_ASSERT(channel);
     _channels.push_back(channel);
     
     if (channel->_duration > _duration)
@@ -395,6 +423,8 @@ void Animation::removeChannel(Channel* channel)
 
 void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId)
 {
+    GP_ASSERT(curve);
+
     switch (propertyId)
     {
     case Transform::ANIMATE_ROTATE:
@@ -411,6 +441,8 @@ void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId
 
 Animation* Animation::clone(Channel* channel, AnimationTarget* target)
 {
+    GP_ASSERT(channel);
+
     Animation* animation = new Animation(getId());
 
     Animation::Channel* channelCopy = new Animation::Channel(*channel, animation, target);

+ 35 - 3
gameplay/src/AnimationClip.cpp

@@ -14,11 +14,14 @@ AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long
       _elapsedTime(0), _crossFadeToClip(NULL), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), 
       _beginListeners(NULL), _endListeners(NULL), _listeners(NULL), _listenerItr(NULL)
 {
-    GP_ASSERT(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
+    GP_ASSERT(_animation);
+    GP_ASSERT(0 <= startTime && startTime <= _animation->_duration && 0 <= endTime && endTime <= _animation->_duration);
     
-    unsigned int channelCount = _animation->_channels.size();    
+    unsigned int channelCount = _animation->_channels.size();
     for (unsigned int i = 0; i < channelCount; i++)
     {
+        GP_ASSERT(_animation->_channels[i]);
+        GP_ASSERT(_animation->_channels[i]->getCurve());
         _values.push_back(new AnimationValue(_animation->_channels[i]->getCurve()->getComponentCount()));
     }
 }
@@ -180,6 +183,8 @@ void AnimationClip::play()
     else
     {
         setClipStateBit(CLIP_IS_PLAYING_BIT);
+        GP_ASSERT(_animation);
+        GP_ASSERT(_animation->_controller);
         _animation->_controller->schedule(this);
     }
     
@@ -268,6 +273,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
     {
         for (std::list<ListenerEvent*>::iterator itr = _listeners->begin(); itr != _listeners->end(); itr++)
         {
+            GP_ASSERT(*itr);
             if (eventTime < (*itr)->_eventTime)
             {
                 itr = _listeners->insert(itr, listenerEvent);
@@ -277,6 +283,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
                 if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
                 {
                     unsigned long currentTime = _elapsedTime % _duration;
+                    GP_ASSERT(**_listenerItr);
                     if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_eventTime)) || 
                         (_speed <= 0 && currentTime > eventTime && (*_listenerItr == _listeners->begin() || eventTime > (**_listenerItr)->_eventTime)))
                         *_listenerItr = itr;
@@ -293,6 +300,7 @@ void AnimationClip::addBeginListener(AnimationClip::Listener* listener)
     if (!_beginListeners)
         _beginListeners = new std::vector<Listener*>;
 
+    GP_ASSERT(listener);
     _beginListeners->push_back(listener);
 }
 
@@ -301,6 +309,7 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
     if (!_endListeners)
         _endListeners = new std::vector<Listener*>;
 
+    GP_ASSERT(listener);
     _endListeners->push_back(listener);
 }
 
@@ -365,10 +374,17 @@ bool AnimationClip::update(unsigned long elapsedTime)
     // Notify any listeners of Animation events.
     if (_listeners)
     {
+        GP_ASSERT(_listenerItr);
+        GP_ASSERT(**_listenerItr);
+
         if (_speed >= 0.0f)
         {
             while (*_listenerItr != _listeners->end() && _elapsedTime >= (long) (**_listenerItr)->_eventTime)
             {
+                GP_ASSERT(_listenerItr);
+                GP_ASSERT(**_listenerItr);
+                GP_ASSERT((**_listenerItr)->_listener);
+
                 (**_listenerItr)->_listener->animationEvent(this, Listener::DEFAULT);
                 ++*_listenerItr;
             }
@@ -377,6 +393,10 @@ bool AnimationClip::update(unsigned long elapsedTime)
         {
             while (*_listenerItr != _listeners->begin() && _elapsedTime <= (long) (**_listenerItr)->_eventTime)
             {
+                GP_ASSERT(_listenerItr);
+                GP_ASSERT(**_listenerItr);
+                GP_ASSERT((**_listenerItr)->_listener);
+
                 (**_listenerItr)->_listener->animationEvent(this, Listener::DEFAULT);
                 --*_listenerItr;
             }
@@ -384,12 +404,18 @@ bool AnimationClip::update(unsigned long elapsedTime)
     }
 
     // Add back in start time, and divide by the total animation's duration to get the actual percentage complete
+    GP_ASSERT(_animation);
+    GP_ASSERT(_animation->_duration > 0);
     float percentComplete = (float)(_startTime + currentTime) / (float) _animation->_duration;
     
     if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT))
     {
+        GP_ASSERT(_crossFadeToClip);
+        GP_ASSERT(_crossFadeOutDuration > 0);
+
         if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin.
         {
+            GP_ASSERT(_crossFadeToClip);
             _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * abs(_speed); 
             resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT);
         }
@@ -436,10 +462,14 @@ bool AnimationClip::update(unsigned long elapsedTime)
     for (unsigned int i = 0; i < channelCount; i++)
     {
         channel = _animation->_channels[i];
+        GP_ASSERT(channel);
         target = channel->_target;
+        GP_ASSERT(target);
         value = _values[i];
+        GP_ASSERT(value);
 
         // Evaluate the point on Curve
+        GP_ASSERT(channel->getCurve());
         channel->getCurve()->evaluate(percentComplete, value->_value);
         // Set the animation value on the target property.
         target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight);
@@ -474,12 +504,13 @@ void AnimationClip::onBegin()
             *_listenerItr = _listeners->end();
     }
     
-    // Notify begin listeners.. if any.
+    // Notify begin listeners if any.
     if (_beginListeners)
     {
         std::vector<Listener*>::iterator listener = _beginListeners->begin();
         while (listener != _beginListeners->end())
         {
+            GP_ASSERT(*listener);
             (*listener)->animationEvent(this, Listener::BEGIN);
             listener++;
         }
@@ -497,6 +528,7 @@ void AnimationClip::onEnd()
         std::vector<Listener*>::iterator listener = _endListeners->begin();
         while (listener != _endListeners->end())
         {
+            GP_ASSERT(*listener);
             (*listener)->animationEvent(this, Listener::END);
             listener++;
         }

+ 3 - 0
gameplay/src/AnimationController.cpp

@@ -21,6 +21,7 @@ void AnimationController::stopAllAnimations()
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = *clipIter;
+        GP_ASSERT(clip);
         clip->stop();
         clipIter++;
     }
@@ -68,6 +69,7 @@ void AnimationController::schedule(AnimationClip* clip)
         _state = RUNNING;
     }
 
+    GP_ASSERT(clip);
     clip->addRef();
     _runningClips.push_back(clip);
 }
@@ -103,6 +105,7 @@ void AnimationController::update(long elapsedTime)
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = (*clipIter);
+        GP_ASSERT(clip);
         if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_RESTARTED_BIT))
         {   // If the CLIP_IS_RESTARTED_BIT is set, we should end the clip and 
             // move it from where it is in the running clips list to the back.

+ 60 - 10
gameplay/src/AnimationTarget.cpp

@@ -20,6 +20,8 @@ AnimationTarget::~AnimationTarget()
         while (itr != _animationChannels->end())
         {
             Animation::Channel* channel = (*itr);
+            GP_ASSERT(channel);
+            GP_ASSERT(channel->_animation);
             channel->_animation->removeChannel(channel);
             SAFE_DELETE(channel);
             itr++;
@@ -49,8 +51,6 @@ Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsi
 
 Animation* AnimationTarget::createAnimation(const char* id, const char* url)
 {
-    GP_ASSERT(url);
-    
     Properties* p = Properties::create(url);
     GP_ASSERT(p);
 
@@ -63,7 +63,11 @@ Animation* AnimationTarget::createAnimation(const char* id, const char* url)
 
 Animation* AnimationTarget::createAnimationFromTo(const char* id, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration)
 {
+    GP_ASSERT(from);
+    GP_ASSERT(to);
+
     const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    GP_ASSERT(propertyComponentCount > 0);
     float* keyValues = new float[2 * propertyComponentCount];
 
     memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
@@ -83,7 +87,11 @@ Animation* AnimationTarget::createAnimationFromTo(const char* id, int propertyId
 
 Animation* AnimationTarget::createAnimationFromBy(const char* id, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration)
 {
+    GP_ASSERT(from);
+    GP_ASSERT(by);
+
     const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    GP_ASSERT(propertyComponentCount > 0);
     float* keyValues = new float[2 * propertyComponentCount];
 
     memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
@@ -104,26 +112,54 @@ Animation* AnimationTarget::createAnimationFromBy(const char* id, int propertyId
 Animation* AnimationTarget::createAnimation(const char* id, Properties* animationProperties)
 {
     GP_ASSERT(animationProperties);
-    GP_ASSERT(std::strcmp(animationProperties->getNamespace(), "animation") == 0);
+    if (std::strcmp(animationProperties->getNamespace(), "animation") != 0)
+    {
+        GP_ERROR("Invalid animation namespace '%s'.", animationProperties->getNamespace());
+        return NULL;
+    }
     
     const char* propertyIdStr = animationProperties->getString("property");
-    GP_ASSERT(propertyIdStr);
+    if (propertyIdStr == NULL)
+    {
+        GP_ERROR("Attribute \'property\' must be specified for an animation.");
+        return NULL;
+    }
     
     // Get animation target property id
     int propertyId = AnimationTarget::getPropertyId(_targetType, propertyIdStr);
-    GP_ASSERT(propertyId != -1);
+    if (propertyId == -1)
+    {
+        GP_ERROR("Property ID is invalid.");
+        return NULL;
+    }
     
     unsigned int keyCount = animationProperties->getInt("keyCount");
-    GP_ASSERT(keyCount > 0);
+    if (keyCount == 0)
+    {
+        GP_ERROR("Attribute \'keyCount\' must be specified for an animation.");
+        return NULL;
+    }
 
     const char* keyTimesStr = animationProperties->getString("keyTimes");
-    GP_ASSERT(keyTimesStr);
+    if (keyTimesStr == NULL)
+    {
+        GP_ERROR("Attribute \'keyTimes\' must be specified for an animation.");
+        return NULL;
+    }
     
     const char* keyValuesStr = animationProperties->getString("keyValues");
-    GP_ASSERT(keyValuesStr);
+    if (keyValuesStr == NULL)
+    {
+        GP_ERROR("Attribute \'keyValues\' must be specified for an animation.");
+        return NULL;
+    }
     
     const char* curveStr = animationProperties->getString("curve");
-    GP_ASSERT(curveStr);
+    if (curveStr == NULL)
+    {
+        GP_ERROR("Attribute \'curve\' must be specified for an animation.");
+        return NULL;
+    }
     
     char delimeter = ' ';
     unsigned int startOffset = 0;
@@ -232,7 +268,11 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
     if (pClip && std::strcmp(pClip->getNamespace(), "clip") == 0)
     {
         int frameCount = animationProperties->getInt("frameCount");
-        GP_ASSERT(frameCount > 0);
+        if (frameCount <= 0)
+        {
+            GP_ERROR("Frame count must be greater than zero for a clip.");
+            return animation;
+        }
         animation->createClips(animationProperties, (unsigned int) frameCount);
     }
 
@@ -247,6 +287,7 @@ void AnimationTarget::destroyAnimation(const char* id)
         return;
 
     // Remove this target's channel from animation, and from the target's list of channels.
+    GP_ASSERT(channel->_animation);
     channel->_animation->removeChannel(channel);
     removeChannel(channel);
 
@@ -258,6 +299,7 @@ Animation* AnimationTarget::getAnimation(const char* id) const
     if (_animationChannels)
     {
         std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+        GP_ASSERT(*itr);
 
         if (id == NULL)
             return (*itr)->_animation;
@@ -266,6 +308,8 @@ Animation* AnimationTarget::getAnimation(const char* id) const
         for (; itr != _animationChannels->end(); itr++)
         {
             channel = (Animation::Channel*)(*itr);
+            GP_ASSERT(channel);
+            GP_ASSERT(channel->_animation);
             if (channel->_animation->_id.compare(id) == 0)
             {
                 return channel->_animation;
@@ -278,6 +322,8 @@ Animation* AnimationTarget::getAnimation(const char* id) const
 
 int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
 {
+    GP_ASSERT(propertyIdStr);
+    
     if (type == AnimationTarget::TRANSFORM)
     {
         if (strcmp(propertyIdStr, "ANIMATE_SCALE") == 0)
@@ -341,6 +387,7 @@ void AnimationTarget::addChannel(Animation::Channel* channel)
     if (_animationChannels == NULL)
         _animationChannels = new std::vector<Animation::Channel*>;
 
+    GP_ASSERT(channel);
     _animationChannels->push_back(channel);
 }
 
@@ -370,6 +417,7 @@ Animation::Channel* AnimationTarget::getChannel(const char* id) const
     if (_animationChannels)
     {
         std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+        GP_ASSERT(*itr);
 
         if (id == NULL)
             return (*itr);
@@ -378,6 +426,7 @@ Animation::Channel* AnimationTarget::getChannel(const char* id) const
         for (; itr != _animationChannels->end(); itr++)
         {
             channel = (Animation::Channel*)(*itr);
+            GP_ASSERT(channel);
             if (channel->_animation->_id.compare(id) == 0)
             {
                 return channel;
@@ -395,6 +444,7 @@ void AnimationTarget::cloneInto(AnimationTarget* target, NodeCloneContext &conte
         for (std::vector<Animation::Channel*>::const_iterator it = _animationChannels->begin(); it != _animationChannels->end(); ++it)
         {
             Animation::Channel* channel = *it;
+            GP_ASSERT(channel);
             GP_ASSERT(channel->_animation);
 
             Animation* animation = context.findClonedAnimation(channel->_animation);

+ 5 - 2
gameplay/src/AnimationValue.cpp

@@ -7,6 +7,7 @@ namespace gameplay
 AnimationValue::AnimationValue(unsigned int componentCount)
   : _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
 {
+    GP_ASSERT(_componentCount > 0);
     _value = new float[_componentCount];
 }
 
@@ -18,6 +19,7 @@ AnimationValue::~AnimationValue()
 float AnimationValue::getFloat(unsigned int index) const
 {
     GP_ASSERT(index < _componentCount);
+    GP_ASSERT(_value);
 
     return _value[index];
 }
@@ -25,20 +27,21 @@ float AnimationValue::getFloat(unsigned int index) const
 void AnimationValue::setFloat(unsigned int index, float value)
 {
     GP_ASSERT(index < _componentCount);
+    GP_ASSERT(_value);
 
     _value[index] = value;
 }
 
 void AnimationValue::getFloat(float* value, unsigned int offset, unsigned int length) const
 {
-    GP_ASSERT(value && offset < _componentCount && (offset + length) <= _componentCount);
+    GP_ASSERT(_value && value && offset < _componentCount && (offset + length) <= _componentCount);
 
     memcpy(value + offset, _value, length * sizeof(float));
 }
 
 void AnimationValue::setFloat(float* value, unsigned int offset, unsigned int length)
 {
-    GP_ASSERT(value && offset < _componentCount && (offset + length) <= _componentCount);
+    GP_ASSERT(_value && value && offset < _componentCount && (offset + length) <= _componentCount);
 
     memcpy(_value, value + offset, length * sizeof(float));
 }

+ 70 - 31
gameplay/src/AudioBuffer.cpp

@@ -28,7 +28,7 @@ AudioBuffer::~AudioBuffer()
 
     if (_alBuffer)
     {
-        alDeleteBuffers(1, &_alBuffer);
+        AL_CHECK( alDeleteBuffers(1, &_alBuffer) );
         _alBuffer = 0;
     }
 }
@@ -43,6 +43,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
     for (unsigned int i = 0; i < bufferCount; i++)
     {
         buffer = __buffers[i];
+        GP_ASSERT(buffer);
         if (buffer->_filePath.compare(path) == 0)
         {
             buffer->addRef();
@@ -51,15 +52,13 @@ AudioBuffer* AudioBuffer::create(const char* path)
     }
 
     ALuint alBuffer;
-    ALCenum al_error;
 
     // Load audio data into a buffer.
-    alGenBuffers(1, &alBuffer);
-    al_error = alGetError();
-    if (al_error != AL_NO_ERROR)
+    AL_CHECK( alGenBuffers(1, &alBuffer) );
+    if (AL_LAST_ERROR())
     {
-        GP_ERROR("AudioBuffer alGenBuffers AL error: %d", al_error);
-        alDeleteBuffers(1, &alBuffer);
+        GP_ERROR("Failed to create OpenAL buffer; alGenBuffers error: %d", AL_LAST_ERROR());
+        AL_CHECK( alDeleteBuffers(1, &alBuffer) );
         return NULL;
     }
     
@@ -67,7 +66,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
     FILE* file = FileSystem::openFile(path, "rb");
     if (!file)
     {
-        GP_ERROR("Invalid audio buffer file: %s", path);
+        GP_ERROR("Failed to load audio file %s.", path);
         goto cleanup;
     }
     
@@ -75,7 +74,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
     char header[12];
     if (fread(header, 1, 12, file) != 12)
     {
-        GP_ERROR("Invalid audio buffer file: %s", path);
+        GP_ERROR("Invalid header for audio file %s.", path);
         goto cleanup;
     }
     
@@ -99,6 +98,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
     else
     {
         GP_ERROR("Unsupported audio file: %s", path);
+        goto cleanup;
     }
     
     fclose(file);
@@ -115,17 +115,21 @@ cleanup:
     if (file)
         fclose(file);
     if (alBuffer)
-        alDeleteBuffers(1, &alBuffer);
+        AL_CHECK( alDeleteBuffers(1, &alBuffer) );
     return NULL;
 }
 
 bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
 {
+    GP_ASSERT(file);
     unsigned char stream[12];
     
     // Verify the wave fmt magic value meaning format.
     if (fread(stream, 1, 8, file) != 8 || memcmp(stream, "fmt ", 4) != 0 )
+    {
+        GP_ERROR("Failed to verify the magic value for the wave file format.");
         return false;
+    }
     
     unsigned int section_size;
     section_size  = stream[7]<<24;
@@ -136,21 +140,27 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
     // Check for a valid pcm format.
     if (fread(stream, 1, 2, file) != 2 || stream[1] != 0 || stream[0] != 1)
     {
-        GP_ERROR("Unsupported audio file, not PCM format.");
+        GP_ERROR("Unsupported audio file format (must be a valid PCM format).");
         return false;
     }
     
-    // Get the channel count (16-bit little-endian)
+    // Get the channel count (16-bit little-endian).
     int channels;
     if (fread(stream, 1, 2, file) != 2)
+    {
+        GP_ERROR("Failed to read the wave file's channel count.");
         return false;
+    }
     channels  = stream[1]<<8;
     channels |= stream[0];
     
-    // Get the sample frequency (32-bit little-endian) 
+    // Get the sample frequency (32-bit little-endian).
     ALuint frequency;
     if (fread(stream, 1, 4, file) != 4)
+    {
+        GP_ERROR("Failed to read the wave file's sample frequency.");
         return false;
+    }
 
     frequency  = stream[3]<<24;
     frequency |= stream[2]<<16;
@@ -161,12 +171,18 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
     // We don't need that info, so just read and ignore it. 
     // We could use this later if we need to know the duration.
     if (fread(stream, 1, 6, file) != 6)
+    {
+        GP_ERROR("Failed to read past the wave file's block size and bytes-per-second.");
         return false;
+    }
     
-    // Get the bit depth (16-bit little-endian)
+    // Get the bit depth (16-bit little-endian).
     int bits;
     if (fread(stream, 1, 2, file) != 2)
+    {
+        GP_ERROR("Failed to read the wave file's bit depth.");
         return false;
+    }
     bits  = stream[1]<<8;
     bits |= stream[0];
     
@@ -188,68 +204,91 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
     }
     else
     {
-        GP_ERROR("Incompatible format: (%d, %d)", channels, bits);
+        GP_ERROR("Incompatible wave file format: (%d, %d)", channels, bits);
         return false;
     }
     
-    // Check against the size of the format header as there may be more data that we need to read
+    // Check against the size of the format header as there may be more data that we need to read.
     if (section_size > 16)
     {
         unsigned int length = section_size - 16;
 
-        // extension size is 2 bytes
+        // Extension size is 2 bytes.
         if (fread(stream, 1, length, file) != length)
+        {
+            GP_ERROR("Failed to read extension size from wave file.");
             return false;
+        }
     }
 
+    // Read in the type of the next section of the file.
     if (fread(stream, 1, 4, file) != 4)
+    {
+        GP_ERROR("Failed to read next section type (fact or data) from wave file.");
         return false;
+    }
 
-    // read the next chunk, could be fact section or the data section
+    // Read the fact section if it is there.
     if (memcmp(stream, "fact", 4) == 0)
     {
         if (fread(stream, 1, 4, file) != 4)
+        {
+            GP_ERROR("Failed to read fact section size from wave file.");
             return false;
+        }
 
         section_size  = stream[3]<<24;
         section_size |= stream[2]<<16;
         section_size |= stream[1]<<8;
         section_size |= stream[0];
 
-        // read in the rest of the fact section
+        // Read in the fact section.
         if (fread(stream, 1, section_size, file) != section_size)
+        {
+            GP_ERROR("Failed to read fact section from wave file.");
             return false;
+        }
 
+        // Read in the type of the next section of the file.
         if (fread(stream, 1, 4, file) != 4)
+        {
+            GP_ERROR("Failed to read next section type (should be data) from wave file.");
             return false;
+        }
     }
 
-    // should now be the data section which holds the decoded sample data
+    // Should now be the data section which holds the decoded sample data.
     if (memcmp(stream, "data", 4) != 0)
     {
-        GP_ERROR("WAV file has no data.");
+        GP_ERROR("Failed to load wave file; file appears to have no data.");
         return false;
     }
 
     // Read how much data is remaining and buffer it up.
     unsigned int dataSize;
-    fread(&dataSize, sizeof(int), 1, file);
+    if (fread(&dataSize, sizeof(int), 1, file) != 1)
+    {
+        GP_ERROR("Failed to read size of data section from wave file.");
+        return false;
+    }
 
     char* data = new char[dataSize];
     if (fread(data, sizeof(char), dataSize, file) != dataSize)
     {
-        GP_ERROR("WAV file missing data.");
+        GP_ERROR("Failed to load wave file; file is missing data.");
         SAFE_DELETE_ARRAY(data);
         return false;
     }
 
-    alBufferData(buffer, format, data, dataSize, frequency);
+    AL_CHECK( alBufferData(buffer, format, data, dataSize, frequency) );
     SAFE_DELETE_ARRAY(data);
     return true;
 }
     
 bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
 {
+    GP_ASSERT(file);
+
     OggVorbis_File ogg_file;
     vorbis_info* info;
     ALenum format;
@@ -262,18 +301,18 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
     if ((result = ov_open(file, &ogg_file, NULL, 0)) < 0)
     {
         fclose(file);
-        GP_ERROR("Could not open Ogg stream.");
+        GP_ERROR("Failed to open ogg file.");
         return false;
     }
 
     info = ov_info(&ogg_file, -1);
-
+    GP_ASSERT(info);
     if (info->channels == 1)
         format = AL_FORMAT_MONO16;
     else
         format = AL_FORMAT_STEREO16;
 
-    // size = #samples * #channels * 2 (for 16 bit)
+    // size = #samples * #channels * 2 (for 16 bit).
     unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
     char* data = new char[data_size];
 
@@ -287,7 +326,7 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
         else if (result < 0)
         {
             SAFE_DELETE_ARRAY(data);
-            GP_ERROR("OGG file missing data.");
+            GP_ERROR("Failed to read ogg file; file is missing data.");
             return false;
         }
         else
@@ -299,16 +338,16 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
     if (size == 0)
     {
         SAFE_DELETE_ARRAY(data);
-        GP_ERROR("Unable to read OGG data.");
+        GP_ERROR("Filed to read ogg file; unable to read any data.");
         return false;
     }
 
-    alBufferData(buffer, format, data, data_size, info->rate);
+    AL_CHECK( alBufferData(buffer, format, data, data_size, info->rate) );
 
     SAFE_DELETE_ARRAY(data);
     ov_clear(&ogg_file);
 
-    // ov_clear actually closes the file pointer as well
+    // ov_clear actually closes the file pointer as well.
     file = 0;
 
     return true;

+ 10 - 8
gameplay/src/AudioController.cpp

@@ -18,18 +18,18 @@ AudioController::~AudioController()
 
 void AudioController::initialize()
 {
-    _alcDevice = alcOpenDevice (NULL);
+    _alcDevice = alcOpenDevice(NULL);
     if (!_alcDevice)
     {
         GP_ERROR("Unable to open OpenAL device.\n");
-        return;  
+        return;
     }
-        
+    
     _alcContext = alcCreateContext(_alcDevice, NULL);
     ALCenum alcErr = alcGetError(_alcDevice);
     if (!_alcContext || alcErr != ALC_NO_ERROR)
     {
-        alcCloseDevice (_alcDevice);
+        alcCloseDevice(_alcDevice);
         GP_ERROR("Unable to create OpenAL context. Error: %d\n", alcErr);
         return;
     }
@@ -65,6 +65,7 @@ void AudioController::pause()
     AudioSource* source = NULL;
     while (itr != _playingSources.end())
     {
+        GP_ASSERT(*itr);
         source = *itr;
         _pausingSource = source;
         source->pause();
@@ -83,6 +84,7 @@ void AudioController::resume()
     AudioSource* source = NULL;
     while (itr != _playingSources.end())
     {
+        GP_ASSERT(*itr);
         source = *itr;
         source->resume();
         itr++;
@@ -94,10 +96,10 @@ void AudioController::update(long elapsedTime)
     AudioListener* listener = AudioListener::getInstance();
     if (listener)
     {
-        alListenerf(AL_GAIN, listener->getGain());
-        alListenerfv(AL_ORIENTATION, (ALfloat*)listener->getOrientation());
-        alListenerfv(AL_VELOCITY, (ALfloat*)&listener->getVelocity());
-        alListenerfv(AL_POSITION, (ALfloat*)&listener->getPosition());
+        AL_CHECK( alListenerf(AL_GAIN, listener->getGain()) );
+        AL_CHECK( alListenerfv(AL_ORIENTATION, (ALfloat*)listener->getOrientation()) );
+        AL_CHECK( alListenerfv(AL_VELOCITY, (ALfloat*)&listener->getVelocity()) );
+        AL_CHECK( alListenerfv(AL_POSITION, (ALfloat*)&listener->getPosition()) );
     }
 }
 

+ 2 - 0
gameplay/src/AudioListener.cpp

@@ -89,6 +89,7 @@ void AudioListener::setCamera(Camera* c)
         // Disconnect our current camera.
         if (_camera)
         {
+            GP_ASSERT(_camera->getNode());
             _camera->getNode()->removeListener(this);
             SAFE_RELEASE(_camera);
         }
@@ -98,6 +99,7 @@ void AudioListener::setCamera(Camera* c)
 
         if (_camera)
         {
+            GP_ASSERT(_camera->getNode());
             _camera->addRef();
             _camera->getNode()->addListener(this);
         }

+ 36 - 36
gameplay/src/AudioSource.cpp

@@ -12,18 +12,19 @@ namespace gameplay
 AudioSource::AudioSource(AudioBuffer* buffer, ALuint source) 
     : _alSource(source), _buffer(buffer), _looped(true), _gain(1.0f), _pitch(1.0f), _node(NULL)
 {
-    alSourcei(_alSource, AL_BUFFER, buffer->_alBuffer);
-    alSourcei(_alSource, AL_LOOPING, _looped);
-    alSourcef(_alSource, AL_PITCH, _pitch);
-    alSourcef(_alSource, AL_GAIN, _gain);
-    alSourcefv(_alSource, AL_VELOCITY, (const ALfloat*)&_velocity);
+    GP_ASSERT(buffer);
+    AL_CHECK( alSourcei(_alSource, AL_BUFFER, buffer->_alBuffer) );
+    AL_CHECK( alSourcei(_alSource, AL_LOOPING, _looped) );
+    AL_CHECK( alSourcef(_alSource, AL_PITCH, _pitch) );
+    AL_CHECK( alSourcef(_alSource, AL_GAIN, _gain) );
+    AL_CHECK( alSourcefv(_alSource, AL_VELOCITY, (const ALfloat*)&_velocity) );
 }
 
 AudioSource::~AudioSource()
 {
     if (_alSource)
     {
-        alDeleteSources(1, &_alSource);
+        AL_CHECK( alDeleteSources(1, &_alSource) );
         _alSource = 0;
     }
     SAFE_RELEASE(_buffer);
@@ -57,11 +58,11 @@ AudioSource* AudioSource::create(const char* url)
     // Load the audio source.
     ALuint alSource = 0;
 
-    alGenSources(1, &alSource);
-    if (alGetError() != AL_NO_ERROR)
+    AL_CHECK( alGenSources(1, &alSource) );
+    if (AL_LAST_ERROR())
     {
         SAFE_RELEASE(buffer);
-        GP_ERROR("AudioSource::createAudioSource - Error generating audio source.");
+        GP_ERROR("Error generating audio source.");
         return NULL;
     }
     
@@ -74,14 +75,14 @@ AudioSource* AudioSource::create(Properties* properties)
     GP_ASSERT(properties);
     if (!properties || !(strcmp(properties->getNamespace(), "audio") == 0))
     {
-        GP_WARN("Failed to load audio source from properties object: must be non-null object and have namespace equal to \'audio\'.");
+        GP_ERROR("Failed to load audio source from properties object: must be non-null object and have namespace equal to \'audio\'.");
         return NULL;
     }
 
     const char* path = properties->getString("path");
     if (path == NULL)
     {
-        GP_WARN("Audio file failed to load; the file path was not specified.");
+        GP_ERROR("Audio file failed to load; the file path was not specified.");
         return NULL;
     }
 
@@ -89,20 +90,20 @@ AudioSource* AudioSource::create(Properties* properties)
     AudioSource* audio = AudioSource::create(path);
     if (audio == NULL)
     {
-        GP_WARN("Audio file '%s' failed to load properly.", path);
+        GP_ERROR("Audio file '%s' failed to load properly.", path);
         return NULL;
     }
 
     // Set any properties that the user specified in the .audio file.
-    if (properties->getString("looped") != NULL)
+    if (properties->exists("looped"))
     {
         audio->setLooped(properties->getBool("looped"));
     }
-    if (properties->getString("gain") != NULL)
+    if (properties->exists("gain"))
     {
         audio->setGain(properties->getFloat("gain"));
     }
-    if (properties->getString("pitch") != NULL)
+    if (properties->exists("pitch"))
     {
         audio->setPitch(properties->getFloat("pitch"));
     }
@@ -118,7 +119,7 @@ AudioSource* AudioSource::create(Properties* properties)
 AudioSource::State AudioSource::getState() const
 {
     ALint state;
-    alGetSourcei(_alSource, AL_SOURCE_STATE, &state);
+    AL_CHECK( alGetSourcei(_alSource, AL_SOURCE_STATE, &state) );
 
     switch (state)
     {
@@ -136,29 +137,28 @@ AudioSource::State AudioSource::getState() const
 
 void AudioSource::play()
 {
-    alSourcePlay(_alSource);
+    AL_CHECK( alSourcePlay(_alSource) );
 
     // Add the source to the controller's list of currently playing sources.
     AudioController* audioController = Game::getInstance()->getAudioController();
+    GP_ASSERT(audioController);
     if (audioController->_playingSources.find(this) == audioController->_playingSources.end())
         audioController->_playingSources.insert(this);
 }
 
 void AudioSource::pause()
 {
-    alSourcePause(_alSource);
+    AL_CHECK( alSourcePause(_alSource) );
 
     // Remove the source from the controller's set of currently playing sources
     // if the source is being paused by the user and not the controller itself.
     AudioController* audioController = Game::getInstance()->getAudioController();
+    GP_ASSERT(audioController);
     if (audioController->_pausingSource != this)
     {
         std::set<AudioSource*>::iterator iter = audioController->_playingSources.find(this);
         if (iter != audioController->_playingSources.end())
-        {
-            GP_WARN("\n\nRemoving an audio source from the list of playing sources...\n\n\n");
             audioController->_playingSources.erase(iter);
-        }
     }
 }
 
@@ -172,10 +172,11 @@ void AudioSource::resume()
 
 void AudioSource::stop()
 {
-    alSourceStop(_alSource);
+    AL_CHECK( alSourceStop(_alSource) );
 
     // Remove the source from the controller's set of currently playing sources.
     AudioController* audioController = Game::getInstance()->getAudioController();
+    GP_ASSERT(audioController);
     std::set<AudioSource*>::iterator iter = audioController->_playingSources.find(this);
     if (iter != audioController->_playingSources.end())
         audioController->_playingSources.erase(iter);
@@ -183,7 +184,7 @@ void AudioSource::stop()
 
 void AudioSource::rewind()
 {
-    alSourceRewind(_alSource);
+    AL_CHECK( alSourceRewind(_alSource) );
 }
 
 bool AudioSource::isLooped() const
@@ -193,13 +194,10 @@ bool AudioSource::isLooped() const
 
 void AudioSource::setLooped(bool looped)
 {
-    alGetError();
-    alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE);
-
-    ALCenum error = alGetError();
-    if (error != AL_NO_ERROR)
+    AL_CHECK( alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE) );
+    if (AL_LAST_ERROR())
     {
-        GP_ERROR("AudioSource::setLooped Error: %d", error);
+        GP_ERROR("Failed to set audio source's looped attribute with error: %d", AL_LAST_ERROR());
     }
     _looped = looped;
 }
@@ -211,7 +209,7 @@ float AudioSource::getGain() const
 
 void AudioSource::setGain(float gain)
 {
-    alSourcef(_alSource, AL_GAIN, gain);
+    AL_CHECK( alSourcef(_alSource, AL_GAIN, gain) );
     _gain = gain;
 }
 
@@ -222,7 +220,7 @@ float AudioSource::getPitch() const
 
 void AudioSource::setPitch(float pitch)
 {
-    alSourcef(_alSource, AL_PITCH, pitch);
+    AL_CHECK( alSourcef(_alSource, AL_PITCH, pitch) );
     _pitch = pitch;
 }
 
@@ -233,7 +231,7 @@ const Vector3& AudioSource::getVelocity() const
 
 void AudioSource::setVelocity(const Vector3& velocity)
 {
-    alSourcefv(_alSource, AL_VELOCITY, (ALfloat*)&velocity);
+    AL_CHECK( alSourcefv(_alSource, AL_VELOCITY, (ALfloat*)&velocity) );
     _velocity = velocity;
 }
 
@@ -269,17 +267,19 @@ void AudioSource::transformChanged(Transform* transform, long cookie)
     if (_node)
     {
         Vector3 translation = _node->getTranslationWorld();
-        alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x);
+        AL_CHECK( alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x) );
     }
 }
 
 AudioSource* AudioSource::clone(NodeCloneContext &context) const
 {
+    GP_ASSERT(_buffer);
+
     ALuint alSource = 0;
-    alGenSources(1, &alSource);
-    if (alGetError() != AL_NO_ERROR)
+    AL_CHECK( alGenSources(1, &alSource) );
+    if (AL_LAST_ERROR())
     {
-        GP_ERROR("AudioSource::createAudioSource - Error generating audio source.");
+        GP_ERROR("Error generating audio source.");
         return NULL;
     }
     AudioSource* audioClone = new AudioSource(_buffer, alSource);

+ 26 - 0
gameplay/src/Base.h

@@ -280,6 +280,32 @@ extern GLenum __gl_error_code;
  */
 #define GL_LAST_ERROR() __gl_error_code
 
+/**
+ * Executes the specified AL code and checks the AL error afterwards
+ * to ensure it succeeded.
+ *
+ * The AL_LAST_ERROR macro can be used afterwards to check whether a AL error was
+ * encountered executing the specified code.
+ */
+#define AL_CHECK( al_code ) \
+    { \
+        while (alGetError() != AL_NO_ERROR) ; \
+        al_code; \
+        __al_error_code = alGetError(); \
+        if (__al_error_code != AL_NO_ERROR) \
+        { \
+            GP_ERROR(#al_code ": %d", (int)__al_error_code); \
+        } \
+    }
+
+// Global variable to hold AL errors
+extern ALenum __al_error_code;
+
+/**
+ * Accesses the most recently set global AL error.
+ */
+#define AL_LAST_ERROR() __al_error_code
+
 
 #if defined(WIN32)
     #pragma warning( disable : 4172 )

+ 1 - 0
gameplay/src/Game.cpp

@@ -5,6 +5,7 @@
 
 // Extern global variables
 GLenum __gl_error_code = GL_NO_ERROR;
+ALenum __al_error_code = AL_NO_ERROR;
 
 namespace gameplay
 {