Index: code/branches/sound3/src/orxonox/sound/SoundManager.cc
===================================================================
--- code/branches/sound3/src/orxonox/sound/SoundManager.cc	(revision 6046)
+++ code/branches/sound3/src/orxonox/sound/SoundManager.cc	(revision 6069)
@@ -22,4 +22,5 @@
  *   Author:
  *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
  *   Co-authors:
  *      ...
@@ -30,4 +31,5 @@
 
 #include <AL/alut.h>
+#include <utility>
 
 #include "util/Exception.h"
@@ -53,5 +55,5 @@
         RegisterRootObject(SoundManager);
 
-        if (!alutInitWithoutContext(NULL,NULL))
+        if (!alutInitWithoutContext(NULL, NULL))
             ThrowException(InitialisationFailed, "Sound: OpenAL ALUT error: " << alutGetErrorString(alutGetError()));
         Loki::ScopeGuard alutExitGuard = Loki::MakeGuard(&alutExit);
@@ -103,15 +105,25 @@
     }
 
-    void SoundManager::update(const Clock &time)
-    {
-        this->fadeInAmbientSound(time.getDeltaTime());
-        this->fadeOutAmbientSound(time.getDeltaTime());
+    void SoundManager::update(const Clock& time)
+    {
+        this->processCrossFading(time.getDeltaTime());
     }
 
     void SoundManager::setConfigValues()
     {
-        SetConfigValue(fadeStep_, 0.2f)
+        SetConfigValue(crossFadeStep_, 0.2f)
             .description("Determines how fast sounds should fade, per second.")
             .callback(this, &SoundManager::checkFadeStepValidity);
+    }
+
+    void SoundManager::checkFadeStepValidity()
+    {
+        if (crossFadeStep_ <= 0.0 || crossFadeStep_ >= 1.0 )
+        {
+            COUT(2) << "Sound warning: Sound step out of range, ignoring change." << std::endl;
+            ResetConfigValue(crossFadeStep_);
+        }
+        COUT(3) << "SoundManager: fade step set to " << crossFadeStep_ << std::endl;
+        return;
     }
 
@@ -141,37 +153,51 @@
     void SoundManager::registerAmbientSound(AmbientSound* newAmbient)
     {
-        if(newAmbient != NULL)
-        {
-            if (!(this->ambientSounds_.empty())) 
-            {
-                this->fadeOutList_.push_front(std::make_pair(this->ambientSounds_.front(), 1.0));
-            }
-            this->fadeInList_.push_front(std::make_pair(newAmbient, 0.0));
-            this->ambientSounds_.push_front(newAmbient);
-        }
-    }
-
-    void SoundManager::unregisterAmbientSound(AmbientSound* currentAmbient)
-    {
-        if(currentAmbient == NULL || ambientSounds_.empty())
+        if (newAmbient != NULL)
+        {
+            for (AmbientList::const_iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == newAmbient)
+                {
+                    COUT(2) << "Sound warning: Will not play an AmbientSound twice." << std::endl;
+                    return;
+                }
+            }
+
+            if (!this->ambientSounds_.empty()) 
+            {
+                this->fadeOut(ambientSounds_.front().first);
+            }
+            this->ambientSounds_.push_front(std::make_pair(newAmbient, false));
+            newAmbient->doPlay();
+            this->fadeIn(newAmbient);
+        }
+    }
+
+    void SoundManager::unregisterAmbientSound(AmbientSound* oldAmbient)
+    {
+        if (oldAmbient == NULL || ambientSounds_.empty())
         {
             return;
         }
-        if(this->ambientSounds_.front() == currentAmbient) 
-        {
-            this->fadeOutList_.push_front(std::make_pair(this->ambientSounds_.front(), 1.0));
+        if (this->ambientSounds_.front().first == oldAmbient) 
+        {
+            this->fadeOut(oldAmbient);
             this->ambientSounds_.pop_front();
-            if(!(this->ambientSounds_.empty()))
-            {
-                this->fadeInList_.push_front(std::make_pair(this->ambientSounds_.front(), 0.0));
+            if (!this->ambientSounds_.empty())
+            {
+                if (!this->ambientSounds_.front().second) // Not paused before
+                {
+                    this->ambientSounds_.front().first->doPlay();
+                }
+                this->fadeIn(this->ambientSounds_.front().first);
             }
         }
         else
         {
-            for(std::list<AmbientSound*>::iterator it= this->ambientSounds_.begin(); it != this->ambientSounds_.end(); it++)
-            {
-                if(*it == currentAmbient)
-                {
-                    currentAmbient->doStop();
+            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == oldAmbient)
+                {
+                    this->fadeOut(oldAmbient);
                     this->ambientSounds_.erase(it);
                     break;
@@ -181,74 +207,109 @@
     }
 
-    // Get the current mood and return the full path string to the requested sound.
-    const std::string& SoundManager::getAmbientPath(const std::string& source)
-    {
-        lastReqPath_ = "ambient/" + MoodManager::getInstance().getMood() + "/" + source;
-        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(lastReqPath_);
-        if(fileInfo == NULL)
-        {
-            return BLANKSTRING;
-        }
-        return lastReqPath_;
-    }
-
-    void SoundManager::fadeInAmbientSound(float dt)
-    {
-        if(!(this->fadeInList_.empty()))
-        {
-            for(std::list<std::pair<AmbientSound*, float> >::iterator it= this->fadeInList_.begin(); it != this->fadeInList_.end(); it++)
-            {
-                it->second += fadeStep_ * dt;
-                alSourcef(it->first->getALAudioSource(), AL_GAIN, it->second);
-            }
-            if(this->fadeInList_.back().second >= 1)
-            {
-                this->fadeInList_.pop_back();
-            }
-        }
-    }
-
-    void SoundManager::fadeOutAmbientSound(float dt)
-    {
-        if(!(this->fadeInList_.empty()))
-        {
-            for(std::list<std::pair<AmbientSound*, float> >::iterator it= this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it++)
-            {
-                it->second -= fadeStep_ * dt;
-                alSourcef(it->first->getALAudioSource(), AL_GAIN, it->second);
-            }
-            if(this->fadeOutList_.back().second <= 0)
-            {
-                bool pauseTest = false;
-            
-                for(std::list<AmbientSound*>::iterator it= this->ambientSounds_.begin(); it != this->ambientSounds_.end(); it++)
-                {
-                    if(*it == this->fadeOutList_.back().first)
+    void SoundManager::pauseAmbientSound(AmbientSound* ambient)
+    {
+        if (ambient != NULL)
+        {
+            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == ambient)
+                {
+                    it->second = true;
+                    this->fadeOut(it->first);
+                    return;
+                }
+            }
+        }
+    }
+
+    //! Get the current mood and return the full path string to the requested sound.
+    std::string SoundManager::getAmbientPath(const std::string& source)
+    {
+        std::string path = "ambient/" + MoodManager::getInstance().getMood() + "/" + source;
+        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(path);
+        if (fileInfo == NULL)
+        {
+            return "";
+        }
+        return path;
+    }
+
+    void SoundManager::fadeIn(AmbientSound* sound)
+    {
+        // If we're already fading out --> remove that
+        for (std::list<AmbientSound*>::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeOutList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeInList_.begin(), this->fadeInList_.end(), sound) == this->fadeInList_.end())
+            this->fadeInList_.push_back(sound);
+    }
+
+    void SoundManager::fadeOut(AmbientSound* sound)
+    {
+        // If we're already fading in --> remove that
+        for (std::list<AmbientSound*>::iterator it = this->fadeInList_.begin(); it != this->fadeInList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeInList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeOutList_.begin(), this->fadeOutList_.end(), sound) == this->fadeOutList_.end())
+            this->fadeOutList_.push_back(sound);
+    }
+
+    void SoundManager::processCrossFading(float dt)
+    {
+        // FADE IN
+        for (std::list<AmbientSound*>::iterator it= this->fadeInList_.begin(); it != this->fadeInList_.end(); it)
+        {
+            if ((*it)->getVolume() + this->crossFadeStep_*dt > 1.0f)
+            {
+                (*it)->setVolume(1.0f);
+                this->fadeInList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() + this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
+
+        // FADE OUT
+        for (std::list<AmbientSound*>::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it)
+        {
+            if ((*it)->getVolume() - this->crossFadeStep_*dt < 0.0f)
+            {
+                (*it)->setVolume(0.0f);
+
+                // If sound is in the ambient list --> pause
+                for (AmbientList::const_iterator it2 = this->ambientSounds_.begin(); it2 != this->ambientSounds_.end(); ++it2)
+                {
+                    if (it2->first == *it)
                     {
-                        pauseTest = true;
+                        (*it)->doPause();
                         break;
                     }
                 }
-                if(pauseTest)
-                {
-                    this->fadeOutList_.back().first->pause();
-                }
-                else
-                {
-                    this->fadeOutList_.back().first->doStop();
-                }
-                this->fadeOutList_.pop_back();
-            }
-        }
-    }
-
-    void SoundManager::checkFadeStepValidity()
-    {
-        if(fadeStep_ <= 0.0 || fadeStep_ >= 1.0 )
-        {
-            ResetConfigValue(fadeStep_);
-        }
-        COUT(0) << "SoundManager: fade step now set to " << fadeStep_ << std::endl;
-        return;
+                // If not pause (by loop above for instance) --> stop
+                if (!(*it)->isPaused())
+                    (*it)->doStop();
+
+                this->fadeOutList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() - this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
     }
 }
