Index: code/branches/presentation2/src/libraries/core/XMLPort.h
===================================================================
--- code/branches/presentation2/src/libraries/core/XMLPort.h	(revision 6116)
+++ code/branches/presentation2/src/libraries/core/XMLPort.h	(revision 6117)
@@ -184,5 +184,5 @@
         ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
     } \
-    containername->port(static_cast<BaseObject*>(this), object, xmlelement, mode)
+    containername->port(dynamic_cast<BaseObject*>(this), object, xmlelement, mode)
 
 // --------------------
Index: code/branches/presentation2/src/orxonox/CMakeLists.txt
===================================================================
--- code/branches/presentation2/src/orxonox/CMakeLists.txt	(revision 6116)
+++ code/branches/presentation2/src/orxonox/CMakeLists.txt	(revision 6117)
@@ -28,4 +28,5 @@
   LevelManager.cc
   Main.cc
+  MoodManager.cc
   PawnManager.cc
   PlayerManager.cc
@@ -55,4 +56,5 @@
   TOLUA_FILES
     LevelManager.h
+    MoodManager.h
     pickup/BaseItem.h
     pickup/PickupInventory.h
Index: code/branches/presentation2/src/orxonox/MoodManager.cc
===================================================================
--- code/branches/presentation2/src/orxonox/MoodManager.cc	(revision 6117)
+++ code/branches/presentation2/src/orxonox/MoodManager.cc	(revision 6117)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin 'youngk' Young
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MoodManager.h"
+
+#include "core/ConsoleCommand.h"
+#include "core/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/ScopedSingletonManager.h"
+
+namespace orxonox
+{
+    MoodManager* MoodManager::singletonPtr_s = 0;
+    ManageScopedSingleton(MoodManager, ScopeID::Root, false);
+
+    MoodManager::MoodManager()
+    {
+        RegisterRootObject(MoodManager);
+        moodOld_ = "default";
+        this->setConfigValues();
+        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(createFunctor(&MoodManager::setMood, this), "setMood"));
+    }
+
+    MoodManager::~MoodManager()
+    {
+    }
+
+    void MoodManager::setConfigValues()
+    {
+        SetConfigValue(mood_, "default")
+            .description("Sets the mood for the current level.")
+            .callback(this, &MoodManager::checkMoodValidity);
+    }
+
+    /**
+     *  Sets the mood
+     *  @note TODO: Inform dependent classes of mood change
+     */
+    void MoodManager::setMood(const std::string& mood)
+    {
+        ModifyConfigValue(mood_, set, mood);
+    }
+    
+    // gets the current mood
+    const std::string& MoodManager::getMood()
+    {
+        return mood_;
+    }
+
+    void MoodManager::checkMoodValidity()
+    {
+        if(mood_ != "default" && mood_ != "dnb")        // Insert new moods here
+        {
+            ResetConfigValue(mood_);
+        }
+        COUT(0) << "MoodManager: Mood now set to " << mood_ << std::endl;
+        return;
+    }
+}
Index: code/branches/presentation2/src/orxonox/MoodManager.h
===================================================================
--- code/branches/presentation2/src/orxonox/MoodManager.h	(revision 6117)
+++ code/branches/presentation2/src/orxonox/MoodManager.h	(revision 6117)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin 'youngk' Young
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MoodManager_H__
+#define _MoodManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <cassert>
+#include <list>
+#include <string>
+
+#include "util/Singleton.h"
+#include "core/OrxonoxClass.h"
+
+// tolua_begin
+namespace orxonox
+{
+    class _OrxonoxExport MoodManager
+    // tolua_end
+        : public Singleton<MoodManager>, public OrxonoxClass
+    { // tolua_export
+            friend class Singleton<MoodManager>;
+        public:
+            MoodManager();
+            ~MoodManager();
+
+            void setConfigValues();
+
+            void setMood(const std::string& mood);
+            const std::string& getMood();
+
+            static MoodManager& getInstance()    { return Singleton<MoodManager>::getInstance(); } // tolua_export
+
+        private:
+
+            // config values
+            std::string mood_;
+            std::string moodOld_;
+
+            void checkMoodValidity();
+
+            static MoodManager* singletonPtr_s;
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _MoodManager_H__ */
Index: code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.cc
===================================================================
--- code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.cc	(revision 6116)
+++ code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.cc	(revision 6117)
@@ -36,4 +36,5 @@
 #include "core/Game.h"
 #include "core/ConsoleCommand.h"
+#include "core/ConfigValueIncludes.h"
 #include "core/GraphicsManager.h"
 #include "core/GUIManager.h"
@@ -49,4 +50,5 @@
         , inputState_(0)
     {
+        RegisterRootObject(GSMainMenu);
         inputState_ = InputManager::getInstance().createInputState("mainMenu");
         inputState_->setMouseMode(MouseMode::Nonexclusive);
@@ -64,5 +66,4 @@
             // Load sound
             this->ambient_ = new AmbientSound(0);
-            this->ambient_->setSource("ambient/mainmenu.wav");
         }
     }
@@ -91,4 +92,7 @@
         CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(createFunctor(&GSMainMenu::startDedicated), "startDedicated"));
         CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(createFunctor(&GSMainMenu::startMainMenu), "startMainMenu"));
+        
+        // create command to change sound path
+        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(createFunctor(&GSMainMenu::setMainMenuSoundPath, this), "setMMSoundPath"));
 
         KeyBinderManager::getInstance().setToDefault();
@@ -97,7 +101,9 @@
         if (GameMode::playsSound())
         {
-            this->ambient_->setLoop(true);
-            this->ambient_->play();
+            this->ambient_->setLooping(true);
+            this->ambient_->play(); // works without source
         }
+
+        this->setConfigValues();
     }
 
@@ -117,4 +123,29 @@
     void GSMainMenu::update(const Clock& time)
     {
+    }
+
+    void GSMainMenu::setConfigValues()
+    {
+        SetConfigValue(soundPathMain_, "mainmenu.ogg")
+            .description("Contains the path to the main menu sound file.")
+            .callback(this, &GSMainMenu::reloadSound);
+    }
+
+    void GSMainMenu::reloadSound()
+    {
+        if (GameMode::playsSound())
+        {
+            this->ambient_->setAmbientSource(soundPathMain_);
+        }
+    }
+
+    const std::string& GSMainMenu::getMainMenuSoundPath()
+    {
+        return soundPathMain_;
+    }
+
+    void GSMainMenu::setMainMenuSoundPath(const std::string& path)
+    {
+        ModifyConfigValue(soundPathMain_, set, path);
     }
 
Index: code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.h
===================================================================
--- code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.h	(revision 6116)
+++ code/branches/presentation2/src/orxonox/gamestates/GSMainMenu.h	(revision 6117)
@@ -34,8 +34,9 @@
 #include "util/OgreForwardRefs.h"
 #include "core/GameState.h"
+#include "core/OrxonoxClass.h"
 
 namespace orxonox
 {
-    class _OrxonoxExport GSMainMenu : public GameState
+    class _OrxonoxExport GSMainMenu : public GameState, public OrxonoxClass
     {
     public:
@@ -46,4 +47,9 @@
         void deactivate();
         void update(const Clock& time);
+
+        void setConfigValues();
+        void reloadSound();
+        const std::string& getMainMenuSoundPath();
+        void setMainMenuSoundPath(const std::string& path);
 
         static void startStandalone();
@@ -61,4 +67,5 @@
         // ambient sound for the main menu
         AmbientSound*     ambient_;
+        std::string       soundPathMain_;
     };
 }
Index: code/branches/presentation2/src/orxonox/sound/AmbientSound.cc
===================================================================
--- code/branches/presentation2/src/orxonox/sound/AmbientSound.cc	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/AmbientSound.cc	(revision 6117)
@@ -31,5 +31,9 @@
 #include "core/CoreIncludes.h"
 #include "core/EventIncludes.h"
+#include "core/GameMode.h"
+#include "core/Resource.h"
 #include "core/XMLPort.h"
+#include "SoundManager.h"
+#include "MoodManager.h"
 
 namespace orxonox
@@ -41,4 +45,7 @@
     {
         RegisterObject(AmbientSound);
+
+        // Ambient sounds always fade in
+        this->setVolume(0);
     }
 
@@ -50,7 +57,6 @@
     {
         SUPER(AmbientSound, XMLPort, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "source", setSource, getSource, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "loop", setLoop, getLoop, xmlelement, mode);
-        XMLPortParamExtern(AmbientSound, BaseSound, this, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
+        BaseSound::XMLPortExtern(xmlelement, mode);
+        XMLPortParam(AmbientSound, "ambientsource", setAmbientSource, getAmbientSource, xmlelement, mode);
     }
 
@@ -60,3 +66,66 @@
         XMLPortEventState(AmbientSound, BaseObject, "play", play, xmlelement, mode);
     }
+
+    void AmbientSound::play()
+    {
+        if (GameMode::playsSound())
+        {
+            COUT(3) << "Sound: " << this->getSource() << ": Playing" << std::endl;
+            SoundManager::getInstance().registerAmbientSound(this);
+        }
+    }
+
+    void AmbientSound::doPlay()
+    {
+        BaseSound::play();
+    }
+
+    void AmbientSound::stop()
+    {
+        if (GameMode::playsSound())
+        {
+            SoundManager::getInstance().unregisterAmbientSound(this);
+        }
+    }
+
+    void AmbientSound::doStop()
+    {
+        BaseSound::stop();
+    }
+
+    void AmbientSound::pause()
+    {
+        if (GameMode::playsSound())
+        {
+            SoundManager::getInstance().pauseAmbientSound(this);
+        }
+    }
+
+    void AmbientSound::doPause()
+    {
+        BaseSound::pause();
+    }
+
+    void AmbientSound::setAmbientSource(const std::string& source)
+    {
+        this->ambientSource_ = source;
+        if (GameMode::playsSound())
+        {
+            std::string path = "ambient/" + MoodManager::getInstance().getMood() + "/" + source;
+            shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(path);
+            if (fileInfo != NULL)
+                this->setSource(path);
+            else
+                COUT(3) << "Sound: " << source << ": Not a valid name! Ambient sound will not change." << std::endl;       
+        }
+    }
+
+    void AmbientSound::changedActivity() 
+    {
+        SUPER(AmbientSound, changedActivity);
+        if (this->isActive())
+            this->play();
+        else 
+            this->stop();
+    }
 }
Index: code/branches/presentation2/src/orxonox/sound/AmbientSound.h
===================================================================
--- code/branches/presentation2/src/orxonox/sound/AmbientSound.h	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/AmbientSound.h	(revision 6117)
@@ -22,8 +22,10 @@
  *   Author:
  *      Reto Grieder
+ *      Kevin Young
  *   Co-authors:
  *      ...
  *
  */
+
 #ifndef _AmbientSound_H__
 #define _AmbientSound_H__
@@ -43,4 +45,6 @@
     class _OrxonoxExport AmbientSound : public BaseSound, public BaseObject
     {
+        friend class SoundManager;
+
     public:
         AmbientSound(BaseObject* creator);
@@ -49,6 +53,19 @@
         virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
         virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        virtual void changedActivity();
+
+        virtual void play();
+        virtual void stop();
+        virtual void pause();
+
+        virtual void setAmbientSource(const std::string& source);
+        const std::string& getAmbientSource() const { return this->ambientSource_; }
 
     private:
+        void doPlay();
+        void doStop();
+        void doPause();
+
+        std::string ambientSource_; //!< Analogous to source_, but mood independent
     };
 }
Index: code/branches/presentation2/src/orxonox/sound/BaseSound.cc
===================================================================
--- code/branches/presentation2/src/orxonox/sound/BaseSound.cc	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/BaseSound.cc	(revision 6117)
@@ -29,4 +29,5 @@
 #include "BaseSound.h"
 
+#include <cassert>
 #include <vector>
 #include <AL/alut.h>
@@ -36,4 +37,5 @@
 #include "core/GameMode.h"
 #include "core/Resource.h"
+#include "core/XMLPort.h"
 
 namespace orxonox
@@ -42,8 +44,14 @@
         : audioSource_(0)
         , audioBuffer_(0)
-        , bPlayOnLoad_(false)
         , bLoop_(false)
+        , state_(Stopped)
     {
         RegisterRootObject(BaseSound);
+
+        if (GameMode::playsSound())
+        {
+            alGenSources(1, &this->audioSource_);
+            assert(this->audioSource_ != 0);
+        }
     }
 
@@ -51,76 +59,84 @@
     {
         this->setSource("");
+        if (GameMode::playsSound())
+            alDeleteSources(1, &this->audioSource_);
+    }
+
+    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(BaseSound, "volume", setVolume,  getVolume,  xmlelement, mode);
+        XMLPortParam(BaseSound, "loop",   setLooping, getLooping, xmlelement, mode);
+        XMLPortParam(BaseSound, "play",   play,       isPlaying,  xmlelement, mode);
+        XMLPortParam(BaseSound, "source", setSource,  getSource,  xmlelement, mode);
     }
 
     void BaseSound::play()
     {
+        if (!this->isPlaying() && GameMode::showsGraphics())
+        {
+            this->state_ = Playing;
+            alSourcePlay(this->audioSource_);
+
+            if (alGetError() != AL_NO_ERROR)
+                 COUT(2) << "Sound: OpenAL: Error playing sound " << this->audioSource_ << std::endl;
+        }
+    }
+
+    void BaseSound::stop()
+    {
+        this->state_ = Stopped;
+        if (GameMode::playsSound())
+            alSourceStop(this->audioSource_);
+    }
+
+    void BaseSound::pause()
+    {
+        if (this->isStopped())
+            return;
+        this->state_ = Paused;
+        if (GameMode::playsSound())
+            alSourcePause(this->audioSource_);
+    }
+
+    void BaseSound::setVolume(float vol)
+    {
+        if (vol > 1 || vol < 0)
+        {
+            COUT(2) << "Sound warning: volume out of range, cropping value." << std::endl;
+            vol = vol > 1 ? 1 : vol;
+            vol = vol < 0 ? 0 : vol;
+        }
+        this->volume_ = vol;
         if (alIsSource(this->audioSource_))
-        {
-            if (this->bLoop_)
-                alSourcei(this->audioSource_, AL_LOOPING, AL_TRUE);
-            else
-                alSourcei(this->audioSource_, AL_LOOPING, AL_FALSE);
-            alSourcePlay(this->audioSource_);
-
-            if (alGetError() != AL_NO_ERROR)
-            {
-                 COUT(2) << "Sound: OpenAL: Error playin sound " << this->audioSource_ << std::endl;
-            }
-        }
-    }
-
-    void BaseSound::stop()
-    {
-        if (alIsSource(this->audioSource_))
+            alSourcef(this->audioSource_, AL_GAIN, vol);
+    }
+
+    void BaseSound::setLooping(bool val)
+    {
+        this->bLoop_ = val;
+        if (GameMode::playsSound())
+            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
+    }
+
+    void BaseSound::setSource(const std::string& source)
+    {
+        if (!GameMode::playsSound() || source == this->source_) 
+        {
+            this->source_ = source;
+            return;
+        }
+
+        if (this->audioBuffer_ != 0 && alIsBuffer(this->audioBuffer_))
+        {
             alSourceStop(this->audioSource_);
-    }
-
-    void BaseSound::pause()
-    {
-        if (alIsSource(this->audioSource_))
-            alSourcePause(this->audioSource_);
-    }
-
-    bool BaseSound::isPlaying()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_PLAYING;
-        return false;
-    }
-
-    bool BaseSound::isPaused()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_PAUSED;
-        return true;
-    }
-
-    bool BaseSound::isStopped()
-    {
-        if (alIsSource(this->audioSource_))
-            return getSourceState() == AL_INITIAL || getSourceState() == AL_STOPPED;
-        return true;
-    }
-
-    void BaseSound::setPlayOnLoad(bool val)
-    {
-        this->bPlayOnLoad_ = true;
-        this->play();
-    }
-
-    void BaseSound::setSource(const std::string& source)
-    {
+            // Unload old sound first
+            alSourcei(this->audioSource_, AL_BUFFER, 0);
+            alDeleteBuffers(1, &this->audioBuffer_);
+            this->audioBuffer_ = 0;
+        }
+
         this->source_ = source;
-        if (!GameMode::playsSound())
-            return;
-
-        if (source.empty() && alIsSource(this->audioSource_))
-        {
-            // Unload sound
-            alSourcei(this->audioSource_, AL_BUFFER, 0);
-            alDeleteSources(1, &this->audioSource_);
-            alDeleteBuffers(1, &this->audioBuffer_);
-            return;
-        }
+        if (source_.empty()) 
+            return;
 
         COUT(3) << "Sound: OpenAL ALUT: loading file " << source << std::endl;
@@ -129,5 +145,5 @@
         if (fileInfo == NULL)
         {
-            COUT(2) << "Warning: Sound file '" << source << "' not found" << std::endl;
+            COUT(2) << "Sound: Warning: Sound file '" << source << "' not found" << std::endl;
             return;
         }
@@ -147,5 +163,5 @@
             {
                 COUT(2) << "Sound: Trying fallback ogg loader" << std::endl;
-                this->audioBuffer_ = loadOggFile();
+                this->audioBuffer_ = this->loadOggFile();
             }
 
@@ -157,5 +173,4 @@
         }
 
-        alGenSources(1, &this->audioSource_);
         alSourcei(this->audioSource_, AL_BUFFER, this->audioBuffer_);
         if (alGetError() != AL_NO_ERROR)
@@ -166,14 +181,13 @@
 
         alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
-
-        if (this->bPlayOnLoad_)
-            this->play();
-    }
-
-    ALint BaseSound::getSourceState()
-    {
-        ALint state;
-        alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
-        return state;
+        alSourcef (this->audioSource_, AL_GAIN, this->volume_);
+        alSourcei (this->audioSource_, AL_LOOPING, (this->bLoop_ ? AL_TRUE : AL_FALSE));
+        if (this->isPlaying() || this->isPaused())
+            alSourcePlay(this->audioSource_);
+        if (this->isPaused())
+            alSourcePause(this->audioSource_);
+
+        if (alGetError() != AL_NO_ERROR)
+            COUT(2) << "Sound: OpenAL: Error playing sound " << this->audioSource_ << std::endl;
     }
 
@@ -259,4 +273,3 @@
         return buffer;
     }
-
-} // namespace: orxonox
+}
Index: code/branches/presentation2/src/orxonox/sound/BaseSound.h
===================================================================
--- code/branches/presentation2/src/orxonox/sound/BaseSound.h	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/BaseSound.h	(revision 6117)
@@ -26,4 +26,5 @@
  *
  */
+
 #ifndef _BaseSound_H__
 #define _BaseSound_H__
@@ -32,5 +33,4 @@
 
 #include <string>
-#include <OgreSharedPtr.h>
 #include <OgreDataStream.h>
 #include "core/OrxonoxClass.h"
@@ -49,24 +49,27 @@
         virtual ~BaseSound();
 
-        void play();
-        void stop();
-        void pause();
+        void XMLPortExtern(Element& xmlelement, XMLPort::Mode mode);
 
-        bool isPlaying();
-        bool isPaused();
-        bool isStopped();
+        virtual void play();
+        virtual void stop();
+        virtual void pause();
 
-        void setSource(const std::string& source);
-        const std::string& getSource() { return this->source_; }
+        bool isPlaying() { return this->state_ == Playing; }
+        bool isPaused()  { return this->state_ == Paused; }
+        bool isStopped() { return this->state_ == Stopped; }
 
-        bool getPlayOnLoad() { return this->bPlayOnLoad_; }
-        void setPlayOnLoad(bool val);
+        virtual void setSource(const std::string& source);
+        virtual const std::string& getSource() const { return this->source_; }
 
-        bool getLoop() { return this->bLoop_; }
-        void setLoop(bool val) { this->bLoop_ = val; }
+        void setVolume(float vol);
+        float getVolume() const { return this->volume_; }
+
+        bool getLooping() const   { return this->bLoop_; }
+        void setLooping(bool val);
+
+        //ALuint getALAudioSource(void);
 
     protected:
         ALuint loadOggFile();
-        ALint getSourceState();
 
         ALuint audioSource_;
@@ -74,8 +77,16 @@
 
     private:
-        std::string source_;
-        bool bPlayOnLoad_;
-        bool bLoop_;
-        DataStreamPtr dataStream_;
+        enum State
+        {
+            Stopped,
+            Playing,
+            Paused
+        };
+
+        std::string     source_;
+        float           volume_;
+        bool            bLoop_;
+        State           state_;
+        DataStreamPtr   dataStream_;
     };
 }
Index: code/branches/presentation2/src/orxonox/sound/SoundManager.cc
===================================================================
--- code/branches/presentation2/src/orxonox/sound/SoundManager.cc	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/SoundManager.cc	(revision 6117)
@@ -22,4 +22,5 @@
  *   Author:
  *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
  *   Co-authors:
  *      ...
@@ -30,10 +31,16 @@
 
 #include <AL/alut.h>
+#include <utility>
 
 #include "util/Exception.h"
 #include "util/Math.h"
 #include "util/ScopeGuard.h"
+#include "util/StringUtils.h"
+#include "util/Clock.h"
 #include "core/GameMode.h"
 #include "core/ScopedSingletonManager.h"
+#include "core/ConfigValueIncludes.h"
+#include "BaseSound.h"
+#include "AmbientSound.h"
 
 namespace orxonox
@@ -44,28 +51,30 @@
     SoundManager::SoundManager()
     {
-        if (!alutInitWithoutContext(NULL,NULL))
-            ThrowException(InitialisationFailed, "OpenAL ALUT error: " << alutGetErrorString(alutGetError()));
+        RegisterRootObject(SoundManager);
+
+        if (!alutInitWithoutContext(NULL, NULL))
+            ThrowException(InitialisationFailed, "Sound: OpenAL ALUT error: " << alutGetErrorString(alutGetError()));
         Loki::ScopeGuard alutExitGuard = Loki::MakeGuard(&alutExit);
 
-        COUT(3) << "OpenAL: Opening sound device..." << std::endl;
+        COUT(3) << "Sound: OpenAL: Opening sound device..." << std::endl;
         this->device_ = alcOpenDevice(NULL);
         if (this->device_ == NULL)
         {
-            COUT(0) << "OpenaAL: Could not open sound device. Have you installed OpenAL?" << std::endl;
+            COUT(0) << "Sound: OpenaAL: Could not open sound device. Have you installed OpenAL?" << std::endl;
 #ifdef ORXONOX_PLATFORM_WINDOWS
-            COUT(0) << "Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
+            COUT(0) << "Sound: Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
 #endif
-            ThrowException(InitialisationFailed, "OpenAL error: Could not open sound device.");
+            ThrowException(InitialisationFailed, "Sound: OpenAL error: Could not open sound device.");
         }
         Loki::ScopeGuard closeDeviceGuard = Loki::MakeGuard(&alcCloseDevice, this->device_);
 
-        COUT(3) << "OpenAL: Sound device opened" << std::endl;
+        COUT(3) << "Sound: OpenAL: Sound device opened" << std::endl;
         this->context_ = alcCreateContext(this->device_, NULL);
         if (this->context_ == NULL)
-            ThrowException(InitialisationFailed, "OpenAL error: Could not create sound context");
+            ThrowException(InitialisationFailed, "Sound: OpenAL error: Could not create sound context");
         Loki::ScopeGuard desroyContextGuard = Loki::MakeGuard(&alcDestroyContext, this->context_);
 
         if (alcMakeContextCurrent(this->context_) == AL_TRUE)
-            COUT(3) << "OpenAL: Context " << this->context_ << " loaded" << std::endl;
+            COUT(3) << "Sound: OpenAL: Context " << this->context_ << " loaded" << std::endl;
 
         COUT(4) << "Sound: OpenAL ALUT version: " << alutGetMajorVersion() << "." << alutGetMinorVersion() << std::endl;
@@ -73,7 +82,7 @@
         const char* str = alutGetMIMETypes(ALUT_LOADER_BUFFER);
         if (str == NULL)
-            COUT(2) << "OpenAL ALUT error: " << alutGetErrorString(alutGetError()) << std::endl;
+            COUT(2) << "Sound: OpenAL ALUT error: " << alutGetErrorString(alutGetError()) << std::endl;
         else
-            COUT(4) << "OpenAL ALUT supported MIME types: " << str << std::endl;
+            COUT(4) << "Sound: OpenAL ALUT supported MIME types: " << str << std::endl;
 
         GameMode::setPlaysSound(true);
@@ -82,4 +91,6 @@
         closeDeviceGuard.Dismiss();
         desroyContextGuard.Dismiss();
+
+        this->setConfigValues();
     }
 
@@ -92,4 +103,27 @@
     }
 
+    void SoundManager::update(const Clock& time)
+    {
+        this->processCrossFading(time.getDeltaTime());
+    }
+
+    void SoundManager::setConfigValues()
+    {
+        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;
+    }
+
     void SoundManager::setListenerPosition(const Vector3& position)
     {
@@ -114,3 +148,161 @@
             COUT(2) << "Sound: OpenAL: Invalid listener orientation" << std::endl;
     }
+
+    void SoundManager::registerAmbientSound(AmbientSound* newAmbient)
+    {
+        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().first == oldAmbient) 
+        {
+            this->fadeOut(oldAmbient);
+            this->ambientSounds_.pop_front();
+            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 (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == oldAmbient)
+                {
+                    this->fadeOut(oldAmbient);
+                    this->ambientSounds_.erase(it);
+                    break;
+                }
+            }
+        }
+    }
+
+    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;
+                }
+            }
+        }
+    }
+
+    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)
+    {
+        
+        // Hacky solution to the fade delay while loading a level.
+        if(dt > 0.2)
+        {
+            return;
+        }
+        
+        // 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)
+                    {
+                        (*it)->doPause();
+                        break;
+                    }
+                }
+                // 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;
+            }
+        }
+    }
 }
Index: code/branches/presentation2/src/orxonox/sound/SoundManager.h
===================================================================
--- code/branches/presentation2/src/orxonox/sound/SoundManager.h	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/SoundManager.h	(revision 6117)
@@ -22,7 +22,9 @@
  *   Author:
  *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
  *   Co-authors:
  *      ...
  */
+
 #ifndef _SoundManager_H__
 #define _SoundManager_H__
@@ -30,8 +32,7 @@
 #include "OrxonoxPrereqs.h"
 
-#include <cassert>
 #include <list>
+#include <string>
 #include "util/Singleton.h"
-#include "tools/interfaces/Tickable.h"
 
 namespace orxonox
@@ -42,18 +43,39 @@
      *
      */
-    class _OrxonoxExport SoundManager : public Singleton<SoundManager>
+    class _OrxonoxExport SoundManager : public Singleton<SoundManager>, public OrxonoxClass
     {
         friend class Singleton<SoundManager>;
+
     public:
         SoundManager();
         ~SoundManager();
 
+        void update(const Clock& time);
+        void setConfigValues();
+
         void setListenerPosition(const Vector3& position);
         void setListenerOrientation(const Quaternion& orientation);
 
+        void registerAmbientSound(AmbientSound* newAmbient);
+        void unregisterAmbientSound(AmbientSound* oldAmbient);
+        void pauseAmbientSound(AmbientSound* ambient);
+
     private:
+        void processCrossFading(float dt);
+        void fadeIn(AmbientSound* sound);
+        void fadeOut(AmbientSound* sound);
+
+        void checkFadeStepValidity();
+
         ALCdevice* device_;
         ALCcontext* context_;
-
+       
+        typedef std::list<std::pair<AmbientSound*, bool> > AmbientList;
+        AmbientList ambientSounds_;
+        
+        float crossFadeStep_;       //!< Absolute change per second (0.1 means 10% of the nominal volume) for cross fading
+        std::list<AmbientSound*> fadeInList_;
+        std::list<AmbientSound*> fadeOutList_;
+        
         static SoundManager* singletonPtr_s;
     };
Index: code/branches/presentation2/src/orxonox/sound/WorldSound.cc
===================================================================
--- code/branches/presentation2/src/orxonox/sound/WorldSound.cc	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/WorldSound.cc	(revision 6117)
@@ -53,7 +53,5 @@
     {
         SUPER(WorldSound, XMLPort, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "source", setSource, getSource, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "loop", setLoop, getLoop, xmlelement, mode);
-        XMLPortParamExtern(WorldSound, BaseSound, this, "playOnLoad", setPlayOnLoad, getPlayOnLoad, xmlelement, mode);
+        BaseSound::XMLPortExtern(xmlelement, mode);
     }
 
@@ -89,3 +87,11 @@
     }
 
+    void WorldSound::changedActivity() 
+    {
+        SUPER(WorldSound, changedActivity);
+        if (this->isActive())
+            this->play();
+        else 
+            this->stop();
+    }
 }
Index: code/branches/presentation2/src/orxonox/sound/WorldSound.h
===================================================================
--- code/branches/presentation2/src/orxonox/sound/WorldSound.h	(revision 6116)
+++ code/branches/presentation2/src/orxonox/sound/WorldSound.h	(revision 6117)
@@ -26,4 +26,5 @@
  *
  */
+
 #ifndef _WorldSound_H__
 #define _WorldSound_H__
@@ -49,4 +50,5 @@
         virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
         virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+        virtual void changedActivity();
 
         virtual void tick(float dt);
