Index: build/premake/premake4.lua
===================================================================
--- build/premake/premake4.lua	(revision 11718)
+++ build/premake/premake4.lua	(working copy)
@@ -519,7 +519,10 @@
 		"ps/Network",
 		"ps/GameSetup",
 		"ps/XML",
-		"sound",
+		"soundmanager",
+		"soundmanager/data",
+		"soundmanager/items",
+		"soundmanager/js",
 		"scripting",
 		"maths",
 		"maths/scripting",
@@ -533,6 +536,8 @@
 		"boost",
 		"enet",
 		"libcurl",
+		"vorbis",
+		"openal"
 	}
 	setup_static_lib_project("engine", source_dirs, extern_libs, {})
 
@@ -553,7 +558,6 @@
 	end
 	setup_static_lib_project("graphics", source_dirs, extern_libs, {})
 
-
 	source_dirs = {
 		"tools/atlas/GameInterface",
 		"tools/atlas/GameInterface/Handlers"
Index: source/ps/GameSetup/Config.cpp
===================================================================
--- source/ps/GameSetup/Config.cpp	(revision 11718)
+++ source/ps/GameSetup/Config.cpp	(working copy)
@@ -23,8 +23,8 @@
 #include "lib/timer.h"
 #include "lib/res/sound/snd_mgr.h"
 #include "Config.h"
+#include "soundmanager/CSoundManager.h"
 
-
 // (these variables are documented in the header.)
 
 CStrW g_CursorName = L"test";
@@ -81,9 +81,26 @@
 	CFG_GET_USER_VAL("particles", Bool, g_Particles);
 
 	float gain = -1.0f;
+	float musicGain = -1.0f;
+	float ambientGain = -1.0f;
+	float actionGain = -1.0f;
+	int	bufferCount = 50;
+	unsigned long	bufferSize = 65536;
+	
 	CFG_GET_USER_VAL("sound.mastergain", Float, gain);
-	if(gain >= 0.0f)
-		WARN_IF_ERR(snd_set_master_gain(gain));
+	CFG_GET_USER_VAL("sound.musicgain", Float, musicGain);
+	CFG_GET_USER_VAL("sound.ambientgain", Float, ambientGain);
+	CFG_GET_USER_VAL("sound.actiongain", Float, actionGain);
+
+	CFG_GET_USER_VAL("sound.bufferCount", Int, bufferCount);
+	CFG_GET_USER_VAL("sound.bufferSize", UnsignedLong, bufferSize);
+
+    g_SoundManager->setMasterGain( gain );
+    g_SoundManager->setMusicGain( musicGain );
+    g_SoundManager->setAmbientGain( ambientGain );
+    g_SoundManager->setActionGain( actionGain );
+
+    g_SoundManager->setMemoryUsage( bufferSize, bufferCount);
 }
 
 
Index: source/ps/GameSetup/GameSetup.cpp
===================================================================
--- source/ps/GameSetup/GameSetup.cpp	(revision 11718)
+++ source/ps/GameSetup/GameSetup.cpp	(working copy)
@@ -102,6 +102,7 @@
 #include "tools/atlas/GameInterface/GameLoop.h"
 #include "tools/atlas/GameInterface/View.h"
 
+#include "soundmanager/CSoundManager.h"
 
 #if !(OS_WIN || OS_MACOSX || OS_ANDROID) // assume all other platforms use X11 for wxWidgets
 #define MUST_INIT_X11 1
@@ -203,6 +204,8 @@
 {
 	PROFILE3("render");
 
+	g_SoundManager->idleTask();
+
 	ogl_WarnIfError();
 
 	g_Profiler2.RecordGPUFrameStart();
@@ -330,7 +333,8 @@
 {
 	// maths
 	JSI_Vector3D::init();
-
+	
+	CSoundManager::ScriptingInit();
 	// graphics
 	CGameView::ScriptingInit();
 
@@ -338,7 +342,7 @@
 	CRenderer::ScriptingInit();
 
 	// sound
-	JSI_Sound::ScriptingInit();
+//	JSI_Sound::ScriptingInit();
 
 	// ps
 	JSI_Console::init();
@@ -476,6 +480,9 @@
 		g_VFS->Mount(L"", modLoosePath / modName/"", flags, priority);
 		g_VFS->Mount(L"", modArchivePath / modName/"", flags, priority);
 	}
+	
+	OsPath apth = paths.RData()/"mods/public";
+	g_SoundManager = new CSoundManager( apth );
 
 	// note: don't bother with g_VFS->TextRepresentation - directories
 	// haven't yet been populated and are empty.
@@ -691,7 +698,7 @@
 	// resource
 	// first shut down all resource owners, and then the handle manager.
 	TIMER_BEGIN(L"resource modules");
-		snd_shutdown();
+		delete g_SoundManager;
 
 		g_VFS.reset();
 
@@ -930,7 +937,7 @@
 		// speed up startup by disabling all sound
 		// (OpenAL init will be skipped).
 		// must be called before first snd_open.
-		snd_disable(true);
+		g_SoundManager->setEnabled( false );
 	}
 
 	g_GUI = new CGUIManager(g_ScriptingHost.GetScriptInterface());
Index: source/ps/Game.cpp
===================================================================
--- source/ps/Game.cpp	(revision 11718)
+++ source/ps/Game.cpp	(working copy)
@@ -45,6 +45,7 @@
 #include "simulation2/components/ICmpPlayerManager.h"
 
 #include "gui/GUIManager.h"
+#include "soundmanager/CSoundManager.h"
 
 extern bool g_GameRestarted;
 
@@ -299,6 +300,7 @@
 	if (doInterpolate)
 	{
 		m_TurnManager->Interpolate(deltaTime);
+		g_SoundManager->idleTask();
 	}
 	
 	// TODO: maybe we should add a CCmpParticleInterface that passes the interpolation commands
Index: source/soundmanager/items/CSoundItem.h
===================================================================
--- source/soundmanager/items/CSoundItem.h	(revision 0)
+++ source/soundmanager/items/CSoundItem.h	(revision 0)
@@ -0,0 +1,38 @@
+//
+//  CSoundItem.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CSoundItem_h
+#define SoundTester_CSoundItem_h
+
+#include "CSoundBase.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+class CSoundItem :public CSoundBase
+{
+protected:
+    
+public:
+    CSoundItem      ();
+    CSoundItem      (CSoundData* sndData);
+    
+    virtual ~CSoundItem     ();
+    void    attach          ( CSoundData* itemData );
+    bool    idleTask        ();
+
+protected:
+
+    
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/items/CBufferItem.h
===================================================================
--- source/soundmanager/items/CBufferItem.h	(revision 0)
+++ source/soundmanager/items/CBufferItem.h	(revision 0)
@@ -0,0 +1,30 @@
+//
+//  CMusicItem.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CBufferItem_h
+#define SoundTester_CBufferItem_h
+
+#include "CSoundBase.h"
+
+class CBufferItem : public CSoundBase
+{
+public:
+    CBufferItem             (CSoundData* sndData);
+    virtual ~CBufferItem    ();
+    
+    virtual void    setLooping   ( bool loops );
+    virtual bool    idleTask     ();
+    
+protected:    
+    virtual void    attach       ( CSoundData* itemData );
+
+    
+};
+
+
+#endif
Index: source/soundmanager/items/CStreamItem.h
===================================================================
--- source/soundmanager/items/CStreamItem.h	(revision 0)
+++ source/soundmanager/items/CStreamItem.h	(revision 0)
@@ -0,0 +1,29 @@
+//
+//  CMusicItem.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CStreamItem_h
+#define SoundTester_CStreamItem_h
+
+#include "soundmanager/data/CSoundData.h"
+#include "CSoundBase.h"
+
+class CStreamItem : public CSoundBase
+{
+public:
+    CStreamItem                 (CSoundData* sndData);
+    virtual ~CStreamItem        ();
+    
+    virtual void    setLooping  ( bool loops );
+    virtual bool    idleTask    ();
+    
+protected:    
+    virtual void    attach      ( CSoundData* itemData );
+
+};
+
+#endif
Index: source/soundmanager/items/ISoundItem.h
===================================================================
--- source/soundmanager/items/ISoundItem.h	(revision 0)
+++ source/soundmanager/items/ISoundItem.h	(revision 0)
@@ -0,0 +1,50 @@
+
+//
+//  Header.h
+//  pyrogenesis
+//
+//  Created by Steven Fuchs on 4/15/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+#ifndef SoundTester_ISoundItem_h
+#define SoundTester_ISoundItem_h
+
+#include <string>
+#include "lib/external_libraries/openal.h"
+#include "maths/Vector3D.h"
+
+
+class ISoundItem
+{
+    
+public:
+	virtual ~ISoundItem(){};
+    virtual bool getLooping     () = 0;
+    virtual void    setLooping       (bool loop) = 0;
+    virtual bool    isPlaying        () = 0;
+    
+    
+    virtual std::string    getName         () = 0;
+    virtual bool    idleTask         () = 0;
+    
+    virtual void    play             () = 0;
+    virtual void    stop             () = 0;
+
+    virtual void    ensurePlay     	 () = 0;
+    virtual void    playAsMusic      () = 0;
+    virtual void    playAsAmbient    () = 0;
+
+    virtual void    playAndDelete    () = 0;
+    virtual void    stopAndDelete    () = 0;
+    virtual void    fadeToIn        ( ALfloat newVolume, double fadeDuration) = 0;
+    virtual void    fadeAndDelete    ( double fadeTime ) = 0;
+    virtual void    playLoop         () = 0;
+
+	virtual void	setCone		(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain) = 0;
+	virtual void    setPitch    (ALfloat pitch) = 0;
+    virtual void    setGain     (ALfloat gain) = 0;
+    virtual void    setLocation (const CVector3D& position) = 0;
+};
+
+
+#endif //SoundTester_ISoundItem_h
\ No newline at end of file
Index: source/soundmanager/items/CSoundBase.cpp
===================================================================
--- source/soundmanager/items/CSoundBase.cpp	(revision 0)
+++ source/soundmanager/items/CSoundBase.cpp	(revision 0)
@@ -0,0 +1,255 @@
+//
+//  CSoundBase.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+#include "CSoundBase.h"
+#include "soundmanager/CSoundManager.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include <iostream>
+
+#include "lib/timer.h"
+
+
+CSoundBase::CSoundBase()
+{
+    resetVars();
+}
+
+CSoundBase::~CSoundBase()
+{
+    stop();
+    if ( mALSource != 0 ) {
+        alDeleteSources( 1, &mALSource);
+        mALSource = 0;
+    }
+    if ( mSoundData != 0 ) {
+        CSoundData::releaseSoundData( mSoundData );
+        mSoundData = 0;
+    }
+    if ( mName )
+        delete mName;
+}
+
+void CSoundBase::resetVars()
+{
+    mALSource = 0;
+    mSoundData = 0;
+    mLastPlay = false;
+    mLooping = false;
+    mStartFadeTime = 0;
+    mEndFadeTime = 0;
+    mStartVolume = 0;
+    mEndVolume = 0;
+
+    resetFade();
+    mName = new std::string( "sound name" );
+}
+
+void CSoundBase::resetFade()
+{
+    mStartFadeTime = 0;
+    mEndFadeTime = 0;
+    mStartVolume = 0;
+    mEndVolume = 0;
+	mShouldBePlaying = false;
+}
+
+void CSoundBase::setGain(ALfloat gain)
+{
+    alSourcef(mALSource, AL_GAIN, gain);
+}
+
+void CSoundBase::ensurePlay()
+{
+	if ( mShouldBePlaying && !isPlaying() )
+		play();
+}
+
+void CSoundBase::setCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain)
+{
+    alSourcef( mALSource, innerCone, AL_CONE_INNER_ANGLE);
+    alSourcef( mALSource, outerCone, AL_CONE_OUTER_ANGLE);
+    alSourcef( mALSource, coneGain, AL_CONE_OUTER_GAIN);
+}
+
+void CSoundBase::setPitch(ALfloat pitch)
+{
+    alSourcef( mALSource, AL_PITCH, pitch);
+}
+
+void CSoundBase::setDirection(const CVector3D& direction)
+{
+	alSourcefv( mALSource, AL_DIRECTION, direction.GetFloatArray() );
+}
+
+bool CSoundBase::initOpenAL()
+{
+    alGetError(); /* clear error */
+    alGenSources( 1, &mALSource);
+	long anErr = alGetError();
+    if( anErr != AL_NO_ERROR) 
+    {
+        printf("- Error creating sources %ld !!\n", anErr );
+    }
+    else
+    {
+        ALfloat source0Pos[]={ -2.0, 0.0, 0.0};
+        ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
+        
+        alSourcef( mALSource,AL_PITCH,1.0f);
+        alSourcef( mALSource,AL_GAIN,1.0f);
+        alSourcefv( mALSource,AL_POSITION,source0Pos);
+        alSourcefv( mALSource,AL_VELOCITY,source0Vel);
+        alSourcei( mALSource,AL_LOOPING,AL_FALSE);
+        return true;
+    }
+    return false;
+}
+
+bool CSoundBase::isPlaying()
+{
+    int proc_state;
+    alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+
+    return ( proc_state == AL_PLAYING );
+}
+
+void CSoundBase::setLastPlay( bool last )
+{
+    mLastPlay = last;
+}
+
+bool CSoundBase::idleTask()
+{
+	return true;
+}
+
+void CSoundBase::setLocation (const CVector3D& position)
+{    
+ //   const float*  loatArr = position.GetFloatArray();
+//    debug_printf(L"do upload and play at location:%f, %f, %f\n\n", loatArr[0], loatArr[1], loatArr[2] );
+
+//    alSourcefv( mALSource,AL_POSITION, position.GetFloatArray() );
+}
+
+bool CSoundBase::handleFade()
+{
+    if ( mStartFadeTime != 0 ) {
+        double currTime = timer_Time();
+        double pctDone = std::min( 1.0, (currTime - mStartFadeTime) / (mEndFadeTime - mStartFadeTime) );
+        pctDone = std::max( 0.0, pctDone );
+        ALfloat curGain = ((mEndVolume - mStartVolume ) * pctDone) + mStartVolume;
+
+        if  (curGain == 0 )
+            stop();
+        else if ( curGain == mEndVolume ) {
+            alSourcef( mALSource, AL_GAIN, curGain);     
+            resetFade();
+        }
+        else
+            alSourcef( mALSource, AL_GAIN, curGain);     
+    }
+	return true;
+}
+
+bool CSoundBase::getLooping()
+{
+    return mLooping;
+}
+void CSoundBase::setLooping( bool loops )
+{
+    mLooping = loops;
+    alSourcei( mALSource, AL_LOOPING, loops ? AL_TRUE : AL_FALSE );
+}
+
+void CSoundBase::play()
+{
+	mShouldBePlaying = true;
+    if ( mALSource != 0 )
+        alSourcePlay( mALSource );
+}
+void CSoundBase::playAndDelete()
+{
+    setLastPlay( true );
+    play();
+}
+
+void CSoundBase::fadeAndDelete( double fadeTime )
+{
+    setLastPlay( true );
+    fadeToIn( 0, fadeTime );
+}
+
+void    CSoundBase::stopAndDelete()
+{
+    setLastPlay( true );
+    stop();
+}
+
+void CSoundBase::playLoop()
+{
+    if ( mALSource != 0 ) {
+        setLooping( true );
+        play();
+    }
+}
+
+void CSoundBase::fadeToIn( ALfloat newVolume, double fadeDuration)
+{
+    int proc_state;
+    alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+    if ( proc_state == AL_PLAYING ) {
+        mStartFadeTime = timer_Time();
+        mEndFadeTime = mStartFadeTime + fadeDuration;
+        alGetSourcef( mALSource, AL_GAIN, &mStartVolume);
+        mEndVolume = newVolume;
+    }
+
+}
+
+void CSoundBase::playAsMusic()
+{
+    g_SoundManager->setMusicItem( this );
+}
+
+void CSoundBase::playAsAmbient()
+{
+    g_SoundManager->setAmbientItem( this );
+}
+
+void CSoundBase::stop()
+{
+	mShouldBePlaying = false;
+    if ( mALSource != 0 ) {
+        int proc_state;
+        alSourcei( mALSource, AL_LOOPING, AL_FALSE );
+        alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+        if ( proc_state == AL_PLAYING )
+            alSourceStop( mALSource );
+    }
+}
+
+const char* CSoundBase::Name()
+{
+    return mName->c_str();
+}
+
+std::string CSoundBase::getName()
+{
+    return std::string( mName->c_str() );
+}
+
+void CSoundBase::setNameFromPath(  char* fileLoc )
+{
+    std::string anst( fileLoc );
+    size_t pos = anst.find_last_of("/");
+    if(pos != std::wstring::npos)
+        mName->assign(anst.begin() + pos + 1, anst.end());
+    else
+        mName->assign(anst.begin(), anst.end());
+}
+
Index: source/soundmanager/items/CSoundItem.cpp
===================================================================
--- source/soundmanager/items/CSoundItem.cpp	(revision 0)
+++ source/soundmanager/items/CSoundItem.cpp	(revision 0)
@@ -0,0 +1,55 @@
+//
+//  CSoundItem.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+#include "CSoundItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include <iostream>
+
+
+CSoundItem::CSoundItem()
+{
+    resetVars();
+}
+
+CSoundItem::CSoundItem(CSoundData* sndData)
+{
+    resetVars();
+    if ( initOpenAL() )
+        attach( sndData );
+
+    debug_printf(L"created SoundItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+CSoundItem::~CSoundItem()
+{
+    ALuint al_buf;
+    
+    stop();
+    alSourceUnqueueBuffers(mALSource, 1, &al_buf);
+}
+
+bool CSoundItem::idleTask()
+{
+    handleFade();
+
+    if ( mLastPlay )
+    {
+        int proc_state;
+        alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+        return ( proc_state != AL_STOPPED );
+    }
+    return true;
+}
+
+void CSoundItem::attach( CSoundData* itemData )
+{
+    if ( itemData != NULL ) {
+        mSoundData = itemData->incrementCount();
+        alSourcei( mALSource, AL_BUFFER, mSoundData->getBuffer() );
+    }
+}
Index: source/soundmanager/items/CBufferItem.cpp
===================================================================
--- source/soundmanager/items/CBufferItem.cpp	(revision 0)
+++ source/soundmanager/items/CBufferItem.cpp	(revision 0)
@@ -0,0 +1,75 @@
+//
+//  CBufferItem.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+#include "CBufferItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include <iostream>
+
+CBufferItem::CBufferItem(CSoundData* sndData)
+{
+    resetVars();
+    if ( initOpenAL() )
+        attach( sndData );
+
+    debug_printf(L"created BufferItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+
+CBufferItem::~CBufferItem()
+{
+    stop();
+    int num_processed;
+    alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+    
+    if (num_processed > 0)
+    {
+        ALuint al_buf[num_processed];
+        alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+    }
+}
+
+
+bool CBufferItem::idleTask()
+{
+    handleFade();
+    
+    if ( mLastPlay )
+    {
+        int proc_state;
+        alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+        return ( proc_state != AL_STOPPED );
+    }
+    
+    if ( getLooping() ) {
+        int num_processed;
+        alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+        
+        for ( int i = 0; i < num_processed; i++ )
+        {
+            ALuint al_buf;
+            alSourceUnqueueBuffers(mALSource, 1, &al_buf);
+            alSourceQueueBuffers(mALSource, 1, &al_buf);
+        }
+    }
+
+    return true;
+}
+
+void CBufferItem::attach( CSoundData* itemData )
+{
+    if ( itemData != NULL ) {
+        mSoundData = itemData->incrementCount();
+        alSourceQueueBuffers(mALSource, mSoundData->getBufferCount(),(const ALuint *) mSoundData->getBufferPtr());
+    }
+}
+
+void CBufferItem::setLooping( bool loops )
+{
+    mLooping = loops;
+}
+
Index: source/soundmanager/items/CSoundBase.h
===================================================================
--- source/soundmanager/items/CSoundBase.h	(revision 0)
+++ source/soundmanager/items/CSoundBase.h	(revision 0)
@@ -0,0 +1,84 @@
+//
+//  CSoundBase.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CSoundBase_h
+#define SoundTester_CSoundBase_h
+
+#include <string>
+#include "lib/external_libraries/openal.h"
+#include "soundmanager/items/ISoundItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+class CSoundBase :public ISoundItem
+{
+protected:
+    
+    ALuint              mALSource;
+    CSoundData*         mSoundData;
+
+    std::string*        mName;
+    bool                mLastPlay;
+    bool                mLooping;
+    bool                mShouldBePlaying;
+    
+    double        	mStartFadeTime;
+    double        	mEndFadeTime;
+    ALfloat     	mStartVolume;
+    ALfloat     	mEndVolume;
+
+public:
+    CSoundBase      ();
+    
+    virtual ~CSoundBase      ();
+    
+    virtual bool    initOpenAL();
+    virtual void    resetVars();
+    virtual void    ensurePlay();
+
+    virtual void setGain     (ALfloat gain);
+	virtual	void setPitch(ALfloat pitch);
+	virtual	void setDirection(const CVector3D& direction);
+	virtual	void setCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain);
+    virtual void setLastPlay( bool last );
+
+    void    play            ();
+    void    playAndDelete   ();
+    bool    idleTask        ();
+    void    playLoop        ();
+    void    stop            ();
+    void    stopAndDelete    ();
+    void    fadeToIn        ( ALfloat newVolume, double fadeDuration);
+
+    void    playAsMusic      ();
+    void    playAsAmbient    ();
+
+    const char*   Name();
+    std::string getName();
+
+    virtual bool getLooping     ();
+    virtual void setLooping     ( bool loops );
+    virtual bool isPlaying();
+    virtual void setLocation (const CVector3D& position);
+    virtual void    fadeAndDelete    ( double fadeTime );
+
+protected:
+
+    void setNameFromPath(  char* fileLoc );
+    void resetFade();
+    bool handleFade();
+
+    
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/items/CStreamItem.cpp
===================================================================
--- source/soundmanager/items/CStreamItem.cpp	(revision 0)
+++ source/soundmanager/items/CStreamItem.cpp	(revision 0)
@@ -0,0 +1,82 @@
+//
+//  CStreamItem.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+#include "CStreamItem.h"
+#include "soundmanager/data/COggData.h"
+
+#include <iostream>
+
+CStreamItem::CStreamItem(CSoundData* sndData)
+{
+    resetVars();
+    if ( initOpenAL() )
+        attach( sndData );
+
+    debug_printf(L"created StreamItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+CStreamItem::~CStreamItem()
+{
+    stop();
+
+    int num_processed;
+    alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+    
+    if (num_processed > 0)
+    {
+        ALuint al_buf[num_processed];
+        alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+    }
+}
+
+bool CStreamItem::idleTask()
+{
+    handleFade();
+
+    int proc_state;
+    alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+    
+    if ( proc_state == AL_STOPPED ) {
+        if ( mLastPlay )
+            return ( proc_state != AL_STOPPED );
+    }
+    else {
+        COggData* tmp = (COggData*)mSoundData;
+        
+        if ( ! tmp->isFileFinished() ) {
+            int num_processed;
+            alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+            
+            if (num_processed > 0)
+            {
+                ALuint al_buf[num_processed];
+                alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+                int didWrite = tmp->fetchDataIntoBuffer( num_processed, al_buf);
+                alSourceQueueBuffers( mALSource, didWrite, al_buf);
+            }
+        }
+        else if ( getLooping() )
+        {
+            tmp->resetFile();
+        }
+    }
+    return true;
+}
+
+void CStreamItem::attach( CSoundData* itemData )
+{
+    if ( itemData != NULL ) {
+        mSoundData = itemData->incrementCount();
+        alSourceQueueBuffers(mALSource, mSoundData->getBufferCount(), (const ALuint *)mSoundData->getBufferPtr());
+    }
+}
+
+void CStreamItem::setLooping( bool loops )
+{
+    mLooping = loops;
+}
+
Index: source/soundmanager/CSoundManager.cpp
===================================================================
--- source/soundmanager/CSoundManager.cpp	(revision 0)
+++ source/soundmanager/CSoundManager.cpp	(revision 0)
@@ -0,0 +1,282 @@
+//
+//  CSoundManager.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/21/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#include "CSoundManager.h"
+#include "soundmanager/items/CSoundItem.h"
+#include "soundmanager/items/CBufferItem.h"
+#include "soundmanager/items/CStreamItem.h"
+#include "soundmanager/js/JAmbientSound.h"
+#include "soundmanager/js/JMusicSound.h"
+#include "soundmanager/js/JSound.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+CSoundManager*  g_SoundManager;
+
+void CSoundManager::ScriptingInit()
+{
+    JAmbientSound::ScriptingInit();
+    JMusicSound::ScriptingInit();
+    JSound::ScriptingInit();
+}
+
+CSoundManager::CSoundManager(OsPath& resourcePath)
+{
+    mResourcePath = resourcePath;
+    
+    mItems = new ItemsList;
+    mCurrentEnvirons    = 0;
+    mCurrentTune        = 0;
+    mGain               = 1;
+    mMusicGain          = 1;
+    mAmbientGain        = 1;
+    mActionGain         = 1;
+    mEnabled            = true;
+	mBufferCount		= 50;
+	mBufferSize			= 65536;
+    
+    debug_printf(L"initiate manager at: %ls\n\n", resourcePath.string().c_str());
+
+	alc_init();
+}
+
+CSoundManager::~CSoundManager()
+{    
+    ItemsList::iterator lstr = mItems->begin();
+    while ( lstr != mItems->end() ) {
+		(*lstr)->stop();
+		delete *lstr;
+        lstr++;
+    }
+
+    alcDestroyContext( mContext );
+    alcCloseDevice( mDevice );
+
+    delete mItems;
+	mItems = 0L;
+    mCurrentEnvirons    = 0;
+    mCurrentTune        = 0;
+}
+
+
+Status CSoundManager::alc_init()
+{	
+	Status ret = INFO::OK;
+
+	mDevice = alcOpenDevice(NULL);
+	if(mDevice)
+	{
+		mContext = alcCreateContext(mDevice, 0);	// no attrlist needed
+		if(mContext)
+			alcMakeContextCurrent(mContext);
+	}
+
+	// check if init succeeded.
+	// some OpenAL implementations don't indicate failure here correctly;
+	// we need to check if the device and context pointers are actually valid.
+	ALCenum err = alcGetError(mDevice);
+	if(err != ALC_NO_ERROR || !mDevice || !mContext)
+	{
+#if OS_UNIX
+		ret = INFO::OK;
+#else
+		ret = ERR::FAIL;
+#endif
+	}
+
+	const char* dev_name = (const char*)alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
+	wchar_t buf[200];
+	swprintf(buf, ARRAY_SIZE(buf), L"SND| alc_init: success, using %hs\n", dev_name);
+
+	return ret;
+}
+void CSoundManager::setMemoryUsage( long bufferSize, int bufferCount )
+{
+	mBufferCount = bufferCount;
+	mBufferSize = bufferSize;
+}
+long CSoundManager::getBufferCount()
+{
+	return mBufferCount;
+}
+long CSoundManager::getBufferSize()
+{
+	return mBufferSize;
+}
+
+
+void CSoundManager::setMasterGain( float gain)
+{
+    mGain = gain;
+}
+void CSoundManager::setMusicGain( float gain)
+{
+    mMusicGain = gain;
+}
+void CSoundManager::setAmbientGain( float gain)
+{
+    mAmbientGain = gain;
+}
+void CSoundManager::setActionGain( float gain)
+{
+    mActionGain = gain;
+}
+
+
+ISoundItem* CSoundManager::loadItem( OsPath* itemPath )
+{
+    debug_printf(L"initiate item at: %ls\n\n", itemPath->string().c_str());
+    
+    OsPath thePath = mResourcePath/ *itemPath;
+    
+    CSoundData*   itemData = CSoundData::soundDataFromFile( thePath );
+    ISoundItem*   answer  = NULL;
+    
+    if ( itemData != NULL ) {
+        if ( itemData->isOneShot() ) {
+            if ( itemData->getBufferCount() == 1 )
+                answer = new CSoundItem( itemData );
+            else
+                answer = new CBufferItem( itemData );
+        }
+        else {
+            answer = new CStreamItem( itemData );
+        }
+
+        if ( answer != NULL )
+            mItems->push_back( answer );
+    }
+
+    
+    return answer;
+}
+
+unsigned long CSoundManager::count()
+{
+    return mItems->size();
+}
+
+void CSoundManager::idleTask()
+{
+	if ( mItems )
+	{
+	    ItemsList::iterator lstr = mItems->begin();
+	    ItemsList  deadItemList;
+	    ItemsList* nextItemList = new ItemsList;
+
+
+	    while ( lstr != mItems->end() ) {
+	        if ( (*lstr)->idleTask() )
+	            nextItemList->push_back( *lstr );
+	        else
+	            deadItemList.push_back( *lstr );
+	        lstr++;
+	    }
+	    delete mItems;
+	    mItems = nextItemList;
+
+	    ItemsList::iterator deadItems = deadItemList.begin();
+	    while ( deadItems != deadItemList.end() )
+	    {   
+	        delete *deadItems;
+	        deadItems++;
+	    }
+	}
+	if ( mCurrentTune )
+		mCurrentTune->ensurePlay();
+	if ( mCurrentEnvirons )
+		mCurrentEnvirons->ensurePlay();
+}
+
+void CSoundManager::deleteItem( long itemNum )
+{
+    ItemsList::iterator lstr = mItems->begin();
+    lstr += itemNum;
+    
+    delete *lstr;
+    
+    mItems->erase( lstr );
+}
+
+ISoundItem* CSoundManager::getSoundItem( unsigned long itemRow )
+{
+   return (*mItems)[itemRow];
+}
+
+void CSoundManager::InitListener()
+{
+    ALfloat listenerPos[]={0.0,0.0,4.0};
+    ALfloat listenerVel[]={0.0,0.0,0.0};
+    ALfloat	listenerOri[]={0.0,0.0,1.0, 0.0,1.0,0.0};
+
+    alListenerfv(AL_POSITION,listenerPos);
+    alListenerfv(AL_VELOCITY,listenerVel);
+    alListenerfv(AL_ORIENTATION,listenerOri);
+}
+void CSoundManager::setEnabled( bool doEnable )
+{
+    mEnabled = doEnable;
+}
+
+void CSoundManager::playActionItem( ISoundItem* anItem )
+{
+    if ( anItem )
+    {
+        if ( mEnabled && ( mActionGain > 0 ) ) {
+            anItem->setGain( mGain * mActionGain );
+            anItem->play();
+        }
+    }
+}
+void CSoundManager::playGroupItem( ISoundItem* anItem, ALfloat groupGain)
+{
+    if ( anItem )
+    {
+        if ( mEnabled && ( mActionGain > 0 ) ) {
+            anItem->setGain( mGain * groupGain );
+            anItem->play();
+        }
+    }
+}
+void CSoundManager::setMusicItem( ISoundItem* anItem )
+{
+    if ( mCurrentTune ) {
+        mCurrentTune->fadeAndDelete(3.00);
+        mCurrentTune = 0L;
+    }
+    idleTask();
+    if ( anItem )
+    {
+        if ( mEnabled && ( mMusicGain > 0 ) ) {
+            mCurrentTune = anItem;
+            mCurrentTune->setGain( 0 );
+            mCurrentTune->playLoop();
+            mCurrentTune->fadeToIn( mGain * mMusicGain, 3.00 );
+        }
+    }
+}
+
+void CSoundManager::setAmbientItem( ISoundItem* anItem )
+{
+    if ( mCurrentEnvirons ) {
+        mCurrentEnvirons->fadeAndDelete(3.00);
+        mCurrentEnvirons = 0L;
+    }
+    idleTask();
+    
+    if ( anItem )
+    {
+        if ( mEnabled && ( mAmbientGain > 0 ) ) {
+            mCurrentEnvirons = anItem;
+            mCurrentEnvirons->setGain( 0 );
+            mCurrentEnvirons->playLoop();
+            mCurrentEnvirons->fadeToIn( mGain * mAmbientGain, 3.00 );
+        }
+    }
+}
+
Index: source/soundmanager/data/COggData.h
===================================================================
--- source/soundmanager/data/COggData.h	(revision 0)
+++ source/soundmanager/data/COggData.h	(revision 0)
@@ -0,0 +1,48 @@
+//
+//  CSoundItem.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_COggData_h
+#define SoundTester_COggData_h
+
+#include "CSoundData.h"
+#include "vorbis/vorbisfile.h"
+
+class COggData : public CSoundData
+{
+    ALuint mFormat;
+    long mFrequency;
+
+public:
+    COggData      ();
+    virtual ~COggData      ();                                     
+                                     
+    virtual bool InitOggFile( const wchar_t* fileLoc );
+    virtual bool isFileFinished();
+    virtual bool isOneShot();
+
+    virtual int fetchDataIntoBuffer( int count, ALuint* buffers);
+    virtual void resetFile();
+
+protected:
+  	OggVorbis_File  m_vf;
+    int            m_current_section;
+    bool           mFileFinished;
+    bool           mOneShot;
+    ALuint         mBuffer[100];
+    int            mBuffersUsed;
+
+    bool addDataBuffer( char* data, long length);
+    void setFormatAndFreq( int form, ALsizei freq);
+    ALsizei  getBufferCount();
+    ALuint getBuffer();
+    ALuint* getBufferPtr();  
+};
+
+
+
+#endif
Index: source/soundmanager/data/CSoundData.cpp
===================================================================
--- source/soundmanager/data/CSoundData.cpp	(revision 0)
+++ source/soundmanager/data/CSoundData.cpp	(revision 0)
@@ -0,0 +1,136 @@
+//
+//  CSoundItem.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#import "CSoundData.h"
+
+
+#include <iostream>
+#include "COggData.h"
+
+DataMap* CSoundData::sSoundData = NULL;
+
+CSoundData::CSoundData()
+{
+    initProperties();
+}
+
+CSoundData::~CSoundData()
+{
+    if ( mALBuffer != 0 )
+        alDeleteBuffers( 1, &mALBuffer );
+}
+
+void CSoundData::initProperties()
+{
+    mALBuffer = 0;
+    mRetentionCount = 0;
+}
+
+void CSoundData::releaseSoundData( CSoundData* theData )
+{
+    DataMap::iterator   itemFind;
+
+    if ( theData->decrementCount() ) {
+        if ( ( itemFind = CSoundData::sSoundData->find( theData->getFileName() ) ) != sSoundData->end() )
+        {
+            CSoundData* dier = itemFind->second;
+            CSoundData::sSoundData->erase( itemFind );
+            delete dier;
+        }
+    }
+}
+
+CSoundData* CSoundData::soundDataFromFile( OsPath& itemPath )
+{
+    if ( CSoundData::sSoundData == NULL )
+        CSoundData::sSoundData = new DataMap;
+    
+    Path                fExt = itemPath.Extension();
+    DataMap::iterator   itemFind;
+    CSoundData*         answer;
+
+    
+    debug_printf(L"creating data at: %ls\n\n", itemPath.string().c_str());
+
+    if ( ( itemFind = CSoundData::sSoundData->find( itemPath.string() ) ) != sSoundData->end() )
+    {
+        debug_printf(L"data found in cache at: %ls\n\n", itemPath.string().c_str());
+        answer = itemFind->second;
+    }
+    else
+    {
+       	if ( fExt == ".ogg" )
+            answer = soundDataFromOgg( itemPath );
+// 		else if ( fExt == ".wav" )
+//          answer = soundDataFromWAV( itemPath );
+    
+        if ( answer && answer->isOneShot() )
+            (*CSoundData::sSoundData)[itemPath.string()] = answer;
+    
+    }
+    return answer;
+}
+
+bool CSoundData::isOneShot()
+{
+    return true;
+}
+
+
+CSoundData* CSoundData::soundDataFromOgg(OsPath& itemPath )
+{
+    CSoundData* answer = NULL;
+    COggData*   oggAnswer = new COggData();
+    if ( oggAnswer->InitOggFile( itemPath.string().c_str() ) ) {
+        answer = oggAnswer;
+    }
+    
+    return answer;
+}
+
+
+ALsizei CSoundData::getBufferCount()
+{
+    return 1;
+}
+
+std::wstring     CSoundData::getFileName()
+{
+    return mFileName;
+}
+
+
+
+
+
+
+
+
+
+CSoundData* CSoundData::incrementCount()
+{
+    mRetentionCount++;
+    return this;
+}
+
+bool CSoundData::decrementCount()
+{
+    mRetentionCount--;
+    
+    return ( mRetentionCount <= 0 );
+}
+
+ALuint CSoundData::getBuffer()
+{
+    return mALBuffer;
+}
+ALuint* CSoundData::getBufferPtr()
+{
+    return &mALBuffer;
+}
+
Index: source/soundmanager/data/COggData.cpp
===================================================================
--- source/soundmanager/data/COggData.cpp	(revision 0)
+++ source/soundmanager/data/COggData.cpp	(revision 0)
@@ -0,0 +1,151 @@
+//
+//  CSoundItem.cpp
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#include "COggData.h"
+
+
+#include <wchar.h>
+#include <iostream>
+#include "soundmanager/CSoundManager.h"
+
+COggData::COggData()
+{
+    mOneShot = false;
+}
+
+COggData::~COggData()
+{
+    alDeleteBuffers( mBuffersUsed, mBuffer );
+    ov_clear(&m_vf);
+}
+
+void COggData::setFormatAndFreq( int form, ALsizei freq)
+{
+    mFormat = form;
+    mFrequency = freq;
+}
+
+bool COggData::InitOggFile( const wchar_t* fileLoc )
+{
+	int buffersToStart = g_SoundManager->getBufferCount();
+    
+#ifdef _WIN32
+    _setmode( _fileno( stdin ), _O_BINARY );
+    _setmode( _fileno( stdout ), _O_BINARY );
+#endif
+
+//    fprintf(stderr, "ready to open ogg file at:%ls \r\r", fileLoc); 
+
+    char nameH[300];
+    sprintf( nameH, "%ls", fileLoc );
+    
+    FILE* f = fopen( nameH, "rb");
+    m_current_section = 0;
+    int err = ov_open_callbacks(f, &m_vf, NULL, 0, OV_CALLBACKS_DEFAULT);
+    if ( err < 0) {
+        fprintf(stderr,"Input does not appear to be an Ogg bitstream :%d :%d.\n", err, ferror(f) );
+        return false;
+    }
+
+    mFileName       = std::wstring(fileLoc);
+
+    mFileFinished = false;
+    setFormatAndFreq( (m_vf.vi->channels == 1)? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16 , (ALsizei)m_vf.vi->rate );
+
+    alGetError(); /* clear error */
+    alGenBuffers( buffersToStart, mBuffer);
+    
+    if(alGetError() != AL_NO_ERROR) 
+    {
+        printf("- Error creating initial buffer !!\n");
+        return false;
+    }
+    else
+    {
+        mBuffersUsed = fetchDataIntoBuffer( buffersToStart, mBuffer);
+        if ( mFileFinished ) {
+            mOneShot = true;
+            if ( mBuffersUsed < buffersToStart ) {
+                debug_printf(L"one shot gave back %d buffers\n\n", buffersToStart - mBuffersUsed );
+                alDeleteBuffers( buffersToStart - mBuffersUsed, &mBuffer[mBuffersUsed] );
+            }
+        }
+    }
+    return true;
+}
+
+ALsizei COggData::getBufferCount()
+{
+    return mBuffersUsed;
+}
+
+bool COggData::isFileFinished()
+{
+    return mFileFinished;
+}
+
+void COggData::resetFile()
+{
+    ov_time_seek( &m_vf, 0 );
+    m_current_section = 0;
+    mFileFinished = false;
+}
+
+bool COggData::isOneShot()
+{
+    return mOneShot;
+}
+
+int COggData::fetchDataIntoBuffer( int count, ALuint* buffers)
+{
+	long bufferSize = g_SoundManager->getBufferSize();
+	
+    char pcmout[bufferSize + 5000];
+    int buffersWritten = 0;
+    
+    for(int i = 0; ( i < count ) && !mFileFinished; i++) {
+        char*   readDest = pcmout;
+        long  totalRet = 0;
+        while (totalRet < bufferSize )
+        {
+            long ret=ov_read(&m_vf,readDest, 4096,0,2,1, &m_current_section);
+            if (ret == 0) {
+                mFileFinished=true;
+                break;
+            } else if (ret < 0) {
+                /* error in the stream.  Not a problem, just reporting it in
+                 case we (the app) cares.  In this case, we don't. */
+            } else {
+                totalRet += ret;
+                readDest += ret;
+            }
+        }
+        if ( totalRet > 0 )
+        {
+            buffersWritten++;
+            alBufferData( buffers[i], mFormat, pcmout, (ALsizei)totalRet, (int)mFrequency);
+        }
+    }
+
+    return buffersWritten;
+}
+
+
+ALuint COggData::getBuffer()
+{
+    return mBuffer[0];
+}
+ALuint* COggData::getBufferPtr()
+{
+    return mBuffer;
+}
+
+
+
+
+
Index: source/soundmanager/data/CSoundData.h
===================================================================
--- source/soundmanager/data/CSoundData.h	(revision 0)
+++ source/soundmanager/data/CSoundData.h	(revision 0)
@@ -0,0 +1,62 @@
+//
+//  CSoundItem.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/23/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CSoundData_h
+#define SoundTester_CSoundData_h
+#include "lib/os_path.h"
+
+#include "lib/external_libraries/openal.h"
+#include "string"
+#include "map"
+
+class CSoundData;
+typedef std::map<std::wstring, CSoundData*> DataMap;
+
+
+
+class CSoundData
+{
+public:
+    static CSoundData* soundDataFromFile( OsPath& itemPath );
+    static CSoundData* soundDataFromOgg( OsPath& itemPath );
+//    static CSoundData* soundDataFromWAV( OsPath& itemPath );
+
+    static void releaseSoundData( CSoundData* theData );
+
+    CSoundData      ();
+    CSoundData      (ALuint dataSource);
+    virtual ~CSoundData     ();
+    
+    CSoundData*     incrementCount();
+    bool            decrementCount();
+    void            initProperties();
+    virtual bool isOneShot();
+
+    
+    virtual ALuint      getBuffer();
+    virtual ALsizei     getBufferCount();
+    std::wstring        getFileName();
+    virtual ALuint*     getBufferPtr();
+
+protected:
+    static     DataMap*  sSoundData;
+
+    ALuint          mALBuffer;
+    int             mRetentionCount;
+    std::wstring    mFileName;
+    
+    
+    
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/CSoundManager.h
===================================================================
--- source/soundmanager/CSoundManager.h	(revision 0)
+++ source/soundmanager/CSoundManager.h	(revision 0)
@@ -0,0 +1,89 @@
+//
+//  CSoundManager.h
+//  SoundTester
+//
+//  Created by Steven Fuchs on 3/21/12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SoundTester_CSoundManager_h
+#define SoundTester_CSoundManager_h
+
+#include "vector"
+#include "map"
+#include "lib/external_libraries/openal.h"
+
+#include "soundmanager/items/ISoundItem.h"
+
+typedef std::vector<ISoundItem*> ItemsList;
+
+
+class CSoundManager
+{
+protected:
+
+    ALuint              mALEnvironment;
+    ALCcontext*          mContext;
+    ALCdevice*           mDevice;
+    ISoundItem*         mCurrentTune;
+    ISoundItem*         mCurrentEnvirons;
+    ItemsList*          mItems;
+    OsPath              mResourcePath;
+    float               mGain;
+    float               mMusicGain;
+    float               mAmbientGain;
+    float               mActionGain;
+    bool                mEnabled;
+	long				mBufferSize;
+	int					mBufferCount;
+	
+public:
+     CSoundManager      (OsPath& resourcePath);
+    virtual ~CSoundManager      ();
+
+    ISoundItem* loadItem( OsPath* itemPath );
+
+    static void ScriptingInit();
+
+    
+    
+    ISoundItem*     itemFromWAV     ( OsPath& fname);
+    ISoundItem*     itemFromOgg     ( OsPath& fname);
+
+    ISoundItem*     getSoundItem    ( unsigned long itemRow );
+    unsigned long   count           ();
+    void            idleTask        ();
+    void            deleteItem      ( long itemNum );
+	
+	void 	setMemoryUsage( long bufferSize, int bufferCount );
+	long	getBufferCount();
+	long	getBufferSize();
+
+    void        setMusicItem( ISoundItem* anItem );
+    void        setAmbientItem( ISoundItem* anItem );
+    void        playActionItem( ISoundItem* anItem );
+	void 		playGroupItem( ISoundItem* anItem, ALfloat groupGain);
+
+    void        setMasterGain( float gain);
+    void        setMusicGain( float gain);
+    void        setAmbientGain( float gain);
+    void        setActionGain( float gain);
+	
+    void        setEnabled( bool doEnable );
+protected:
+    void    InitListener();
+	virtual Status alc_init();
+
+};
+
+
+
+extern CSoundManager*  g_SoundManager;
+
+
+
+
+
+
+
+#endif
Index: source/soundmanager/js/JAmbientSound.cpp
===================================================================
--- source/soundmanager/js/JAmbientSound.cpp	(revision 0)
+++ source/soundmanager/js/JAmbientSound.cpp	(revision 0)
@@ -0,0 +1,99 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "JAmbientSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "lib/res/sound/snd_mgr.h"
+#include "lib/res/h_mgr.h"	// h_filename
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+JAmbientSound::JAmbientSound(const VfsPath& pathname)
+{
+	mFileName = new OsPath( pathname.string().c_str() );
+}
+
+JAmbientSound::~JAmbientSound()
+{
+}
+
+
+// start playing the sound, all ambient sounds loop
+bool JAmbientSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+    ISoundItem*	aSnd = g_SoundManager->loadItem( mFileName );
+
+    aSnd->playAsAmbient();
+
+	return true;
+}
+
+// start playing the sound, all ambient sounds loop
+bool JAmbientSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+    ISoundItem*	aSnd = g_SoundManager->loadItem( mFileName );
+
+    aSnd->playAsAmbient();
+	return true;
+}
+bool JAmbientSound::Free(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	g_SoundManager->setAmbientItem( 0L );
+
+	return true;
+}
+
+// Script-bound functions
+
+
+void JAmbientSound::ScriptingInit()
+{
+	AddMethod<CStr, &JAmbientSound::ToString>("toString", 0);
+	AddMethod<bool, &JAmbientSound::Play>("play", 0);
+	AddMethod<bool, &JAmbientSound::Loop>("loop", 0);
+	AddMethod<bool, &JAmbientSound::Free>("free", 0);
+    
+	CJSObject<JAmbientSound>::ScriptingInit("AmbientSound", &JAmbientSound::Construct, 1);
+}
+
+CStr JAmbientSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	std::ostringstream stringStream;
+	stringStream << "[object AmbientSound: ";
+	stringStream << mFileName->string().c_str();
+	
+	return stringStream.str();
+}
+
+JSBool JAmbientSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+//	JSU_REQUIRE_MIN_PARAMS(1);
+    
+	CStrW filename;
+	if (! ToPrimitive<CStrW>(cx, JS_ARGV(cx, vp)[0], filename))
+        return JS_FALSE;
+    
+	JAmbientSound* newObject = new JAmbientSound(filename);
+	newObject->m_EngineOwned = false;
+
+	JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+    
+	return JS_TRUE;
+}
Index: source/soundmanager/js/JSound.cpp
===================================================================
--- source/soundmanager/js/JSound.cpp	(revision 0)
+++ source/soundmanager/js/JSound.cpp	(revision 0)
@@ -0,0 +1,171 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "JSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+
+JSound::JSound(const VfsPath& pathname)
+{
+    OsPath itsPth = OsPath( pathname.string().c_str() );
+    mSndItem = g_SoundManager->loadItem( &itsPth );
+}
+
+JSound::~JSound()
+{
+	if ( mSndItem ) {
+		mSndItem->fadeAndDelete(0.2);
+		mSndItem = 0;
+	}
+}
+
+bool JSound::clearSoundItem()
+{
+	mSndItem = 0L;
+}
+
+bool JSound::SetGain(JSContext* cx, uintN UNUSED(argc), jsval* argv)
+{
+	if (! mSndItem )
+		return false;
+
+	float gain;
+	if (! ToPrimitive<float>(cx, argv[0], gain))
+		return false;
+    
+	mSndItem->setGain( gain );	
+	return true;
+}
+
+bool JSound::SetPitch(JSContext* cx, uintN UNUSED(argc), jsval* argv)
+{
+	if (! mSndItem )
+		return false;
+
+	float pitch;
+	if (! ToPrimitive<float>(cx, argv[0], pitch))
+		return false;
+    
+	mSndItem->setPitch( pitch );
+	return true;
+}
+
+bool JSound::SetPosition(JSContext* cx, uintN argc, jsval* argv)
+{
+	if (! mSndItem )
+		return false;
+    
+	ENSURE(argc >= 1); // FIXME
+    
+	CVector3D pos;
+	// absolute world coords
+	if (!ToPrimitive<CVector3D>(cx, argv[0], pos))
+		return false;
+
+	mSndItem->setLocation( pos );
+    
+	return true;
+}
+
+
+bool JSound::Fade(JSContext* cx, uintN argc, jsval* argv)
+{
+	if (! mSndItem )
+		return false;
+    
+//	ENSURE(argc >= 3); // FIXME
+    float initial_gain, final_gain;
+    float length;
+    if (! (ToPrimitive<float>(cx, argv[0], initial_gain)
+           && ToPrimitive<float>(cx, argv[1], final_gain)
+           && ToPrimitive<float>(cx, argv[2], length)))
+        return false;
+    
+    mSndItem->setGain( initial_gain );
+    mSndItem->fadeToIn( final_gain, length );
+
+	return true;
+}
+
+bool JSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	if (! mSndItem )
+		return false;
+
+	mSndItem->play();
+
+	return true;
+}
+
+bool JSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	if (! mSndItem )
+		return false;
+
+	mSndItem->playLoop();
+
+	return true;
+}
+
+bool JSound::Free(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	if ( mSndItem ) {
+		mSndItem->fadeAndDelete(0.2);
+		mSndItem = 0;
+	}
+
+	return true;
+}
+
+void JSound::ScriptingInit()
+{
+	AddMethod<CStr, &JSound::ToString>("toString", 0);
+	AddMethod<bool, &JSound::Play>("play", 0);
+	AddMethod<bool, &JSound::Loop>("loop", 0);
+	AddMethod<bool, &JSound::Free>("free", 0);
+	AddMethod<bool, &JSound::SetGain>("setGain", 0);
+	AddMethod<bool, &JSound::SetPitch>("setPitch", 0);
+	AddMethod<bool, &JSound::SetPosition>("setPosition", 0);
+	AddMethod<bool, &JSound::Fade>("fade", 0);
+    
+	CJSObject<JSound>::ScriptingInit("Sound", &JSound::Construct, 1);
+}
+
+CStr JSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	return "[object Sound: " + ( mSndItem ? mSndItem->getName() : "(null)" ) + "]";
+}
+
+JSBool JSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+//	JSU_REQUIRE_MIN_PARAMS(1);
+    
+	CStrW filename;
+	if (! ToPrimitive<CStrW>(cx, JS_ARGV(cx, vp)[0], filename))
+        return JS_FALSE;
+    
+	JSound* newObject = new JSound(filename);
+	newObject->m_EngineOwned = false;
+	JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+    
+	return JS_TRUE;
+}
Index: source/soundmanager/js/JMusicSound.cpp
===================================================================
--- source/soundmanager/js/JMusicSound.cpp	(revision 0)
+++ source/soundmanager/js/JMusicSound.cpp	(revision 0)
@@ -0,0 +1,85 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "JMusicSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+
+JMusicSound::JMusicSound(const VfsPath& pathname)
+{
+	mFileName = new OsPath( pathname.string().c_str() );
+}
+
+JMusicSound::~JMusicSound()
+{
+//	disposing of music now handled by SoundManager
+}
+
+bool JMusicSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+    ISoundItem*	aSnd = g_SoundManager->loadItem( mFileName );
+	aSnd->playAsMusic();
+
+	return true;
+}
+
+// request the sound be played until free() is called. returns immediately.
+bool JMusicSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+    ISoundItem*	aSnd = g_SoundManager->loadItem( mFileName );
+	aSnd->playAsMusic();
+
+	return true;
+}
+
+void JMusicSound::ScriptingInit()
+{
+	AddMethod<CStr, &JMusicSound::ToString>("toString", 0);
+	AddMethod<bool, &JMusicSound::Play>("play", 0);
+	AddMethod<bool, &JMusicSound::Loop>("loop", 0);
+    
+	CJSObject<JMusicSound>::ScriptingInit("MusicSound", &JMusicSound::Construct, 1);
+}
+
+CStr JMusicSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+	std::ostringstream stringStream;
+	stringStream << "[object MusicSound: ";
+	stringStream << mFileName->string().c_str();
+	
+	return stringStream.str();
+}
+
+JSBool JMusicSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+//	JSU_REQUIRE_MIN_PARAMS(1);
+    
+	CStrW filename;
+	if (! ToPrimitive<CStrW>(cx, JS_ARGV(cx, vp)[0], filename))
+        return JS_FALSE;
+    
+	JMusicSound* newObject = new JMusicSound(filename);
+	newObject->m_EngineOwned = false;
+	JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+    
+	return JS_TRUE;
+}
Index: source/soundmanager/js/SMSoundGroup.cpp
===================================================================
--- source/soundmanager/js/SMSoundGroup.cpp	(revision 0)
+++ source/soundmanager/js/SMSoundGroup.cpp	(revision 0)
@@ -0,0 +1,295 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+* =========================================================================
+* File        : SoundGroup.cpp
+* Project     : 0 A.D.
+* Description : Loads up a group of sound files with shared properties, 
+*				and provides a simple interface for playing them.        
+* =========================================================================
+*/
+
+#include "precompiled.h"
+#include "soundmanager/CSoundManager.h"
+#include "SMSoundGroup.h"
+
+#include <algorithm>
+
+#include "lib/rand.h"
+
+#include "ps/XML/Xeromyces.h"
+#include "ps/CLogger.h"
+#include "ps/Filesystem.h"
+#include "ps/Util.h"
+
+
+static const bool DISABLE_INTENSITY = true; // disable for now since it's broken
+
+void CSMSoundGroup::SetGain(float gain)
+{
+	gain = std::min(gain, 1.0f);
+	m_Gain = gain;
+}
+
+void CSMSoundGroup::SetDefaultValues()
+{
+	m_index = 0;
+	m_Flags = 0;
+	m_Intensity = 0;
+	m_CurTime = 0.0f;
+
+	// sane defaults; will probably be replaced by the values read during LoadSoundGroup.
+	SetGain(0.7f);
+	m_Pitch = 1.0f;
+	m_Priority = 60;
+	m_PitchUpper = 1.1f;
+	m_PitchLower = 0.9f;
+	m_GainUpper = 1.0f;
+	m_GainLower = 0.8f;
+	m_ConeOuterGain = 0.0f;
+	m_ConeInnerAngle = 360.0f;
+	m_ConeOuterAngle = 360.0f;
+	m_Decay = 3.0f;
+	m_IntensityThreshold = 3;
+	// WARNING: m_TimeWindow is currently unused and uninitialized
+}
+
+CSMSoundGroup::CSMSoundGroup()
+{
+	SetDefaultValues();
+}
+
+CSMSoundGroup::CSMSoundGroup(const VfsPath& pathnameXML)
+{
+	SetDefaultValues();
+	LoadSoundGroup(pathnameXML);
+}
+
+CSMSoundGroup::~CSMSoundGroup()
+{
+	// clean up all the handles from this group.
+	ReleaseGroup();
+}
+
+static float RandFloat(float min, float max)
+{
+	return float(rand(min*100.0f, max*100.0f) / 100.0f);
+}
+
+void CSMSoundGroup::UploadPropertiesAndPlay(ISoundItem* hSound, const CVector3D& position)
+{
+    hSound->setLocation( position );
+
+    if( TestFlag(eRandPitch) )
+    	hSound->setPitch( RandFloat( m_PitchLower, m_PitchUpper ) );
+	else
+    	hSound->setPitch( m_Pitch );
+
+	ALfloat theGain = m_Gain;
+    if( TestFlag(eRandGain) )
+		theGain = RandFloat( m_GainLower, m_GainUpper);
+
+	hSound->setCone( m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
+
+
+    g_SoundManager->playGroupItem( hSound, theGain );
+}
+
+
+static void HandleError(const std::wstring& message, const VfsPath& pathname, Status err)
+{
+	if(err == ERR::AGAIN)
+		return;	// open failed because sound is disabled (don't log this)
+	LOGERROR(L"%ls: pathname=%ls, error=%ls", message.c_str(), pathname.string().c_str(), ErrorString(err));
+}
+
+void CSMSoundGroup::PlayNext(const CVector3D& position)
+{
+    // if no sounds, return
+    if (filenames.size() == 0)
+        return;
+    
+    m_index = (size_t)rand(0, (size_t)filenames.size());
+    UploadPropertiesAndPlay( snd_group[m_index], position);
+}
+
+void CSMSoundGroup::Reload()
+{
+    m_index = 0; // reset our index
+
+	snd_group.clear();
+
+	for(size_t i = 0; i < filenames.size(); i++)
+    {
+        OsPath  thePath = OsPath( m_filepath/filenames[i] );
+        ISoundItem* temp = g_SoundManager->loadItem( &thePath );
+        snd_group.push_back(temp);
+    }
+
+    if(TestFlag(eRandOrder))
+        random_shuffle(snd_group.begin(), snd_group.end());
+}
+
+void CSMSoundGroup::ReleaseGroup()
+{
+
+	for(size_t i = 0; i < filenames.size(); i++)
+    {
+		snd_group[i]->fadeAndDelete(0.2);
+	}
+	snd_group.clear();
+}
+
+void CSMSoundGroup::Update(float TimeSinceLastFrame)
+{
+}
+
+bool CSMSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML)
+{
+//    LOGERROR(L"loading new sound group '%ls'", pathnameXML.string().c_str());
+
+	CXeromyces XeroFile;
+	if (XeroFile.Load(g_VFS, pathnameXML) != PSRETURN_OK)
+		return false;
+
+	// Define elements used in XML file
+	#define EL(x) int el_##x = XeroFile.GetElementID(#x)
+	#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
+	EL(soundgroup);
+	EL(gain);
+	EL(looping);
+	EL(omnipresent);
+	EL(pitch);
+	EL(priority);
+	EL(randorder);
+	EL(randgain);
+	EL(randpitch);
+	EL(conegain);
+	EL(coneinner);
+	EL(coneouter);
+	EL(sound);
+	EL(gainupper);
+	EL(gainlower);
+	EL(pitchupper);
+	EL(pitchlower);
+	EL(path);
+	EL(threshold);
+	EL(decay);
+	EL(replacement);
+	#undef AT
+	#undef EL
+
+	XMBElement root = XeroFile.GetRoot();
+
+	if (root.GetNodeName() != el_soundgroup)
+	{
+		LOGERROR(L"Invalid SoundGroup format (unrecognised root element '%hs')", XeroFile.GetElementString(root.GetNodeName()).c_str());
+		return false;
+	}
+	
+	XERO_ITER_EL(root, child)
+	{
+	
+		int child_name = child.GetNodeName();			
+		
+		if(child_name == el_gain)
+		{
+			SetGain(child.GetText().ToFloat());
+		}
+		else if(child_name == el_looping)
+		{
+			if(child.GetText().ToInt() == 1)
+				SetFlag(eLoop);
+		}
+		else if(child_name == el_omnipresent)
+		{
+			if(child.GetText().ToInt() == 1)
+				SetFlag(eOmnipresent);
+		}
+		else if(child_name == el_pitch)
+		{
+			this->m_Pitch = child.GetText().ToFloat();
+		}
+		else if(child_name == el_priority)
+		{
+			this->m_Priority = child.GetText().ToFloat();
+		}
+		else if(child_name == el_randorder)
+		{
+			if(child.GetText().ToInt() == 1)
+				SetFlag(eRandOrder);
+		}
+		else if(child_name == el_randgain)
+		{
+			if(child.GetText().ToInt() == 1)
+				SetFlag(eRandGain);
+		}
+		else if(child_name == el_gainupper)
+		{
+			this->m_GainUpper = child.GetText().ToFloat();
+		}
+		else if(child_name == el_gainlower)
+		{
+			this->m_GainLower = child.GetText().ToFloat();
+		}
+		else if(child_name == el_randpitch)
+		{
+			if(child.GetText().ToInt() == 1)
+				SetFlag(eRandPitch);
+		}
+		else if(child_name == el_pitchupper)
+		{
+			this->m_PitchUpper = child.GetText().ToFloat();
+		}
+		else if(child_name == el_pitchlower)
+		{
+			this->m_PitchLower = child.GetText().ToFloat();
+		}
+		else if(child_name == el_conegain)
+		{
+			this->m_ConeOuterGain = child.GetText().ToFloat();
+		}
+		else if(child_name == el_coneinner)
+		{
+			this->m_ConeInnerAngle = child.GetText().ToFloat();
+		}
+		else if(child_name == el_coneouter)
+		{
+			this->m_ConeOuterAngle = child.GetText().ToFloat();
+		}
+		else if(child_name == el_sound)
+		{
+			this->filenames.push_back(child.GetText().FromUTF8());
+		}
+		else if(child_name == el_path)
+		{
+			m_filepath = child.GetText().FromUTF8();
+		}
+		else if(child_name == el_threshold)
+		{
+			m_IntensityThreshold = child.GetText().ToFloat();
+		}
+		else if(child_name == el_decay)
+		{
+			m_Decay = child.GetText().ToFloat();
+		}
+	}
+
+	Reload();
+	return true;
+}
Index: source/soundmanager/js/JAmbientSound.h
===================================================================
--- source/soundmanager/js/JAmbientSound.h	(revision 0)
+++ source/soundmanager/js/JAmbientSound.h	(revision 0)
@@ -0,0 +1,51 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_JAMBIENTSOUND
+#define INCLUDED_JAMBIENTSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JAmbientSound : public CJSObject<JAmbientSound>
+{
+public:    
+	 		 JAmbientSound	(const VfsPath& pathname);
+	virtual	~JAmbientSound	();
+
+    
+	CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+    
+	bool Play(JSContext* cx, uintN argc, jsval* argv);
+    
+	bool Loop(JSContext* cx, uintN argc, jsval* argv);
+   	bool Free(JSContext* cx, uintN argc, jsval* argv);
+  
+	bool SetGain(JSContext* cx, uintN argc, jsval* argv);
+	bool SetPitch(JSContext* cx, uintN argc, jsval* argv);    
+	bool Fade(JSContext* cx, uintN argc, jsval* argv);
+    
+	static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+	void clearSoundItem();
+	static void ScriptingInit();
+protected:
+	
+	OsPath*	mFileName;
+
+};
+
+#endif	// #ifndef INCLUDED_JAMBIENTSOUND
Index: source/soundmanager/js/JSound.h
===================================================================
--- source/soundmanager/js/JSound.h	(revision 0)
+++ source/soundmanager/js/JSound.h	(revision 0)
@@ -0,0 +1,67 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// JS sound binding
+
+// interface rationale:
+// - can't just expose fire and forget playSound to script code:
+//   we sometimes need to loop until a certain condition is met
+//   (e.g. building is complete) => need means of access (Handle) to sound.
+//
+// - the current 64-bit Handle can't be stored as-is by JS code;
+//   we could make it 32 bit, but that limits its usefulness
+//   (barely enough tag bits).
+//
+// - instead, we provide a thin class wrapper (using scriptableobject.h)
+//   on top of the snd API that encapsulates the Handle.
+
+#ifndef INCLUDED_JSOUND
+#define INCLUDED_JSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JSound : public CJSObject<JSound>
+{
+public:
+        
+	// note: filename is stored by handle manager; no need to keep a copy here.
+    
+	 		 JSound(const VfsPath& pathname);
+	virtual ~JSound();
+    
+	CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+    
+	bool Play(JSContext* cx, uintN argc, jsval* argv);
+	bool Loop(JSContext* cx, uintN argc, jsval* argv);
+    
+	bool Free(JSContext* cx, uintN argc, jsval* argv);
+	bool SetGain(JSContext* cx, uintN argc, jsval* argv);
+	bool SetPitch(JSContext* cx, uintN argc, jsval* argv);
+	bool SetPosition(JSContext* cx, uintN argc, jsval* argv);
+    bool clearSoundItem();
+    
+	bool Fade(JSContext* cx, uintN argc, jsval* argv);
+    
+	static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+	static void ScriptingInit();
+
+protected:
+    ISoundItem*     mSndItem;
+};
+
+#endif	// #ifndef INCLUDED_JSOUND
Index: source/soundmanager/js/JMusicSound.h
===================================================================
--- source/soundmanager/js/JMusicSound.h	(revision 0)
+++ source/soundmanager/js/JMusicSound.h	(revision 0)
@@ -0,0 +1,59 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// JS sound binding
+
+// interface rationale:
+// - can't just expose fire and forget playSound to script code:
+//   we sometimes need to loop until a certain condition is met
+//   (e.g. building is complete) => need means of access (Handle) to sound.
+//
+// - the current 64-bit Handle can't be stored as-is by JS code;
+//   we could make it 32 bit, but that limits its usefulness
+//   (barely enough tag bits).
+//
+// - instead, we provide a thin class wrapper (using scriptableobject.h)
+//   on top of the snd API that encapsulates the Handle.
+
+#ifndef INCLUDED_JMUSICSOUND
+#define INCLUDED_JMUSICSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JMusicSound : public CJSObject<JMusicSound>
+{
+public:    
+			 JMusicSound(const VfsPath& pathname);
+	virtual ~JMusicSound();
+    
+	// Script-bound functions
+    
+	CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+    
+	bool Play(JSContext* cx, uintN argc, jsval* argv);
+	bool Loop(JSContext* cx, uintN argc, jsval* argv);
+    
+	static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+    
+	static void ScriptingInit();
+    
+protected:
+	OsPath*	mFileName;
+};
+
+#endif	// #ifndef INCLUDED_JMUSICSOUND
Index: source/soundmanager/js/SMSoundGroup.h
===================================================================
--- source/soundmanager/js/SMSoundGroup.h	(revision 0)
+++ source/soundmanager/js/SMSoundGroup.h	(revision 0)
@@ -0,0 +1,137 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. 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.
+ *
+ * 0 A.D. 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 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+* =========================================================================
+* File        : SoundGroup.h
+* Project     : 0 A.D.
+* Description : Loads up a group of sound files with shared properties, 
+*				and provides a simple interface for playing them.        
+* =========================================================================
+*/
+
+/*
+Example usage:
+
+
+Example SoundGroup.xml
+	<?xml version="1.0" encoding="utf-8"?>
+	<SoundGroup>
+		<Gain>1.0</Gain>
+		<Looping>0</Looping>
+		<Pitch>1.0</Pitch>
+		<Priority>100</Priority>
+		<RandOrder>0</RandOrder>
+		<RandGain>0</RandGain>
+		<RandPitch>0</RandPitch>
+		<ConeGain>1.0</ConeGain>
+		<ConeInner>360</ConeInner>
+		<ConeOuter>360</ConeOuter>
+		<Sound>audio/voice/hellenes/soldier/Attack_Attackx.ogg</Sound>
+		<Sound>audio/voice/hellenes/soldier/Attack_Chargex.ogg</Sound>
+		<Sound>audio/voice/hellenes/soldier/Attack_Engagex.ogg</Sound>
+		<Sound>audio/voice/hellenes/soldier/Attack_ForMyFamily.ogg</Sound>
+	</SoundGroup>
+
+*/
+
+#ifndef INCLUDED_SMSOUNDGROUP
+#define INCLUDED_SMSOUNDGROUP
+
+#include "lib/res/handle.h"
+#include "lib/file/vfs/vfs_path.h"
+#include "ps/CStr.h"
+#include "maths/Vector3D.h"
+#include "lib/res/sound/snd_mgr.h"
+#include "soundmanager/items/ISoundItem.h"
+
+#include <vector>
+
+enum eSndGrpFlags
+{
+	eRandOrder     = 0x01,
+	eRandGain      = 0x02,
+	eRandPitch     = 0x04,
+	eLoop          = 0x08,
+	eOmnipresent   = 0x10
+};
+
+
+class CSMSoundGroup
+{
+	NONCOPYABLE(CSMSoundGroup);
+public:
+		CSMSoundGroup(const VfsPath& pathnameXML);
+	CSMSoundGroup(void);
+	~CSMSoundGroup(void);
+
+	// Play next sound in group
+	// @param position world position of the entity generating the sound
+	// (ignored if the eOmnipresent flag is set)
+	void PlayNext(const CVector3D& position);
+
+	// Load a group
+	bool LoadSoundGroup(const VfsPath& pathnameXML);
+
+	void Reload();
+
+	// Release all remaining loaded handles
+	void ReleaseGroup();
+
+	// Update SoundGroup, remove dead sounds from intensity count
+	void Update(float TimeSinceLastFrame);
+
+	// Set a flag using a value from eSndGrpFlags
+	inline void SetFlag(int flag) { m_Flags = (unsigned char)(m_Flags | flag); }
+
+	// Test flag, returns true if flag is set.
+	inline bool TestFlag(int flag) { return (m_Flags & flag) != 0; }
+	
+private:
+	void SetGain(float gain);
+	void UploadPropertiesAndPlay(ISoundItem* hSound, const CVector3D& position);
+	void SetDefaultValues();
+
+	size_t m_index;  // index of the next sound to play
+	
+	Handle m_hReplacement;
+	
+	std::vector<ISoundItem*> snd_group;  // we store the handles so we can load now and play later
+	std::vector<std::wstring> filenames; // we need the filenames so we can reload when necessary.
+
+	VfsPath m_filepath; // the file path for the list of sound file resources
+
+	float m_CurTime; // Time elapsed since soundgroup was created
+	float m_TimeWindow; // The Intensity Threshold Window
+	size_t m_IntensityThreshold; // the allowable intensity before a sound switch	
+	size_t m_Intensity;  // our current intensity(number of sounds played since m_CurTime - m_TimeWindow) 
+	float m_Decay; // 
+	unsigned char m_Flags; // up to eight individual parameters, use with eSndGrpFlags.
+	
+	float m_Gain;  
+	float m_Pitch;
+	float m_Priority;
+	float m_ConeOuterGain; 
+	float m_PitchUpper;
+	float m_PitchLower;
+	float m_GainUpper;
+	float m_GainLower;
+	float m_ConeInnerAngle;
+	float m_ConeOuterAngle;
+};
+
+#endif //#ifndef INCLUDED_SOUNDGROUP
Index: source/main.cpp
===================================================================
--- source/main.cpp	(revision 11718)
+++ source/main.cpp	(working copy)
@@ -383,17 +383,17 @@
 		// coincide in position and orientation.
 		float down[3] = { -up[0], -up[1], -up[2] };
 
-		{
-			PROFILE3("sound update");
-			if (snd_update(pos, dir, down) < 0)
-				debug_printf(L"snd_update failed\n");
-		}
+//		{
+//			PROFILE3("sound update");
+//			if (snd_update(pos, dir, down) < 0)
+//				debug_printf(L"snd_update failed\n");
+//		}
 	}
 	else
 	{
-		PROFILE3("sound update (0)");
-		if (snd_update(0, 0, 0) < 0)
-			debug_printf(L"snd_update (pos=0 version) failed\n");
+//		PROFILE3("sound update (0)");
+//		if (snd_update(0, 0, 0) < 0)
+//			debug_printf(L"snd_update (pos=0 version) failed\n");
 	}
 
 	// Immediately flush any messages produced by simulation code
@@ -477,8 +477,6 @@
 	// run non-visual simulation replay if requested
 	if (args.Has("replay"))
 	{
-		snd_disable(true);
-
 		Paths paths(args);
 		g_VFS = CreateVfs(20 * MiB);
 		g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE);
Index: source/simulation2/components/CCmpSoundManager.cpp
===================================================================
--- source/simulation2/components/CCmpSoundManager.cpp	(revision 11718)
+++ source/simulation2/components/CCmpSoundManager.cpp	(working copy)
@@ -24,7 +24,7 @@
 #include "simulation2/MessageTypes.h"
 #include "simulation2/components/ICmpPosition.h"
 #include "simulation2/components/ICmpRangeManager.h"
-#include "sound/SoundGroup.h"
+#include "soundmanager/js/SMSoundGroup.h"
 
 class CCmpSoundManager : public ICmpSoundManager
 {
@@ -36,7 +36,7 @@
 
 	DEFAULT_COMPONENT_ALLOCATOR(SoundManager)
 
-	std::map<std::wstring, CSoundGroup*> m_SoundGroups;
+	std::map<std::wstring, CSMSoundGroup*> m_SoundGroups;
 
 	static std::string GetSchema()
 	{
@@ -49,7 +49,7 @@
 
 	virtual void Deinit()
 	{
-		for (std::map<std::wstring, CSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
+		for (std::map<std::wstring, CSMSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
 			delete it->second;
 		m_SoundGroups.clear();
 	}
@@ -76,7 +76,7 @@
 			// or on some other timer?
 			const CMessageUpdate& msgData = static_cast<const CMessageUpdate&> (msg);
 			float t = msgData.turnLength.ToFloat();
-			for (std::map<std::wstring, CSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
+			for (std::map<std::wstring, CSMSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
 				if (it->second)
 					it->second->Update(t);
 			break;
@@ -87,10 +87,10 @@
 	virtual void PlaySoundGroup(std::wstring name, entity_id_t source)
 	{
 		// Make sure the sound group is loaded
-		CSoundGroup* group;
+		CSMSoundGroup* group;
 		if (m_SoundGroups.find(name) == m_SoundGroups.end())
 		{
-			group = new CSoundGroup();
+			group = new CSMSoundGroup();
 			if (!group->LoadSoundGroup(L"audio/" + name))
 			{
 				LOGERROR(L"Failed to load sound group '%ls'", name.c_str());
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js	(revision 11718)
+++ binaries/data/mods/public/gui/session/session.js	(working copy)
@@ -408,12 +408,11 @@
 //			currentAmbient = newRandomSound("ambient", "temperate_", "dayscape");
 
 			const AMBIENT = "audio/ambient/dayscape/day_temperate_gen_03.ogg";
-			currentAmbient = new Sound(AMBIENT);
+			currentAmbient = new AmbientSound(AMBIENT);
 
 			if (currentAmbient)
 			{
 				currentAmbient.loop();
-				currentAmbient.setGain(0.8);
 			}
 			break;
 
@@ -428,7 +427,7 @@
 {
 	if (currentAmbient)
 	{
-		currentAmbient.fade(-1, 0.0, 5.0);
+		currentAmbient.free();
 		currentAmbient = null;
 	}
 }
Index: binaries/data/mods/public/gui/common/music.js
===================================================================
--- binaries/data/mods/public/gui/common/music.js	(revision 11718)
+++ binaries/data/mods/public/gui/common/music.js	(working copy)
@@ -72,11 +72,6 @@
 		switch (this.currentState)
 		{
 			case this.states.OFF:
-			    	if (this.isPlaying())
-				{
-					this.currentMusic.fade(-1, 0.0, 3.0);
-					this.currentMusic = null;
-				}
 				break;
 
 			case this.states.MENU:
@@ -146,23 +141,14 @@
 
 Music.prototype.switchMusic = function(track, fadeInPeriod, isLooping)
 {
-	if (this.currentMusic)
-	{
-		this.currentMusic.fade(-1, 0.0, 5.0);
-		this.currentMusic = null;
-	}
+	this.currentMusic = new MusicSound(this.RELATIVE_MUSIC_PATH + track);
 
-	this.currentMusic = new Sound(this.RELATIVE_MUSIC_PATH + track);
-
 	if (this.currentMusic)
 	{
 		if (isLooping)
 			this.currentMusic.loop();
 		else
 			this.currentMusic.play();
-
-		if (fadeInPeriod)
-			this.currentMusic.fade(0.0, this.musicGain, fadeInPeriod);
 	}
 };
 
Index: binaries/data/mods/public/gui/common/functions_utility_music.js
===================================================================
--- binaries/data/mods/public/gui/common/functions_utility_music.js	(revision 11718)
+++ binaries/data/mods/public/gui/common/functions_utility_music.js	(working copy)
@@ -66,6 +66,20 @@
 
 	//console.write("Playing " + randomSoundPath + " ...");
 
+	switch (soundType)
+	{
+		case "music":
+			return new MusicSound(randomSoundPath);
+		break;
+		case "ambient":
+			return new AmbientSound(randomSoundPath);
+		break;
+		case "effect":
+            console.write ("am loading effect '*"+randomSoundPath+"*'");
+		break;
+		default:
+		break;
+	}
 	return new Sound(randomSoundPath);
 }
 
Index: binaries/data/mods/public/hwdetect/hwdetect.js
===================================================================
--- binaries/data/mods/public/hwdetect/hwdetect.js	(revision 11718)
+++ binaries/data/mods/public/hwdetect/hwdetect.js	(working copy)
@@ -213,11 +213,11 @@
 	}
 
 	// http://trac.wildfiregames.com/ticket/685
-	if (os_macosx)
-	{
-		warnings.push("Audio has been disabled, due to problems with OpenAL on OS X.");
-		disable_audio = true;
-	}
+//	if (os_macosx)
+//	{
+//		warnings.push("Audio has been disabled, due to problems with OpenAL on OS X.");
+//		disable_audio = true;
+//	}
 
 	// http://trac.wildfiregames.com/ticket/684
 	// https://bugs.freedesktop.org/show_bug.cgi?id=24047
Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg	(revision 11718)
+++ binaries/data/config/default.cfg	(working copy)
@@ -73,7 +73,12 @@
 
 ; GENERAL PREFERENCES:
 
-sound.mastergain = 0.5
+sound.mastergain = 0.9
+sound.musicgain = 0.2
+sound.ambientgain = 0.6
+sound.actiongain = 0.7
+sound.bufferCount = 50
+sound.bufferSize = 65536
 
 ; Camera control settings
 view.scroll.speed = 120.0
