Revision: 499
http://python-ogre.svn.sourceforge.net/python-ogre/?rev=499&view=rev
Author: andy_miller
Date: 2007-12-16 06:20:20 -0800 (Sun, 16 Dec 2007)
Log Message:
-----------
General Updates and test of new scripts
Modified Paths:
--------------
trunk/python-ogre/ThirdParty/caelum/CaelumPrerequisites.h
trunk/python-ogre/ThirdParty/caelum/GroundFog.h
trunk/python-ogre/ThirdParty/caelum/LayeredClouds.cpp
trunk/python-ogre/ThirdParty/caelum/LayeredClouds.h
trunk/python-ogre/ThirdParty/caelum/SkyColourModel.cpp
trunk/python-ogre/ThirdParty/caelum/SkyColourModel.h
trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.cpp
trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.h
trunk/python-ogre/ThirdParty/ogreal/OgreALPrereqs.h
trunk/python-ogre/ThirdParty/ogreal/OgreALSound.cpp
trunk/python-ogre/ThirdParty/ogreal/OgreALSound.h
trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.cpp
trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.h
trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.cpp
trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.h
trunk/python-ogre/code_generators/caelum/generate_code.py
Added Paths:
-----------
trunk/python-ogre/ThirdParty/caelum/ImageHelper.cpp
trunk/python-ogre/ThirdParty/caelum/ImageHelper.h
trunk/python-ogre/makeall.py
trunk/python-ogre/scripts_V2/
trunk/python-ogre/scripts_V2/BuildModule.py
trunk/python-ogre/scripts_V2/environment.py
Modified: trunk/python-ogre/ThirdParty/caelum/CaelumPrerequisites.h
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/CaelumPrerequisites.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/CaelumPrerequisites.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -5,19 +5,19 @@
#include "Ogre.h"
// Define the dll export qualifier if compiling for Windows
-#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
- #ifdef CAELUM_LIB
- #define DllExport __declspec (dllexport)
- #else
- #ifdef __MINGW32__
- #define DllExport
- #else
- #define DllExport __declspec (dllimport)
- #endif
- #endif
-#else
+// #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+// #ifdef CAELUM_LIB
+// #define DllExport __declspec (dllexport)
+// #else
+// #ifdef __MINGW32__
+// #define DllExport
+// #else
+// #define DllExport __declspec (dllimport)
+// #endif
+// #endif
+// #else
#define DllExport
-#endif
+// #endif
// Define the version code
#define CAELUM_VERSION_MAIN 0
Modified: trunk/python-ogre/ThirdParty/caelum/GroundFog.h
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/GroundFog.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/GroundFog.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -129,5 +129,4 @@
}
-#endif //GROUNDFOG_H
-
+#endif //GROUNDFOG_H
\ No newline at end of file
Added: trunk/python-ogre/ThirdParty/caelum/ImageHelper.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/ImageHelper.cpp (rev 0)
+++ trunk/python-ogre/ThirdParty/caelum/ImageHelper.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -0,0 +1,48 @@
+#include "CaelumPrecompiled.h"
+#include "ImageHelper.h"
+
+namespace caelum
+{
+ Ogre::ColourValue getInterpolatedColour (
+ float fx, float fy, Ogre::Image *img, bool wrapX)
+ {
+ // Don't -> all the time, and avoid unsigned warnings
+ int imgWidth = static_cast<int>(img->getWidth ());
+ int imgHeight = static_cast<int>(img->getHeight ());
+
+ // Calculate pixel y coord.
+ int py = Ogre::Math::IFloor(Ogre::Math::Abs (fy) * (imgHeight - 1));
+ // Snap to py image bounds.
+ py = std::max(0, std::min(py, imgHeight - 1));
+
+ // Get the two closest pixels on x.
+ // px1 and px2 are the closest integer pixels to px.
+ float px = fx * (img->getWidth () - 1);
+ int px1, px2;
+ px1 = Ogre::Math::IFloor(px);
+ px2 = Ogre::Math::ICeil(px);
+
+ if (wrapX) {
+ // Wrap x coords. The funny addition ensures that it does
+ // "the right thing" for negative values.
+ px1 = (px1 % imgWidth + imgWidth) % imgWidth;
+ px2 = (px2 % imgWidth + imgWidth) % imgWidth;
+ } else {
+ px1 = std::max(0, std::min(px1, imgWidth - 1));
+ px2 = std::max(0, std::min(px2, imgWidth - 1));
+ }
+
+ // Calculate the interpolated pixel
+ Ogre::ColourValue c1, c2, cf;
+ c1 = img->getColourAt (px1, py, 0);
+ c2 = img->getColourAt (px2, py, 0);
+
+ // Blend the two pixels together.
+ // diff is the weight between pixel 1 and pixel 2.
+ float diff = px - px1;
+ cf = c1 * (1 - diff) + c2 * diff;
+
+ return cf;
+ }
+
+}
\ No newline at end of file
Added: trunk/python-ogre/ThirdParty/caelum/ImageHelper.h
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/ImageHelper.h (rev 0)
+++ trunk/python-ogre/ThirdParty/caelum/ImageHelper.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -0,0 +1,24 @@
+#ifndef CAELUM_HEADER__IMAGE_HELPER_H
+#define CAELUM_HEADER__IMAGE_HELPER_H
+
+#include "CaelumPrerequisites.h"
+
+namespace caelum
+{
+ /** Gets the interpolated colour between two pixels from an image.
+ Interpolate a texture pixel by hand. (fx, fy) are in texture coordinates,
+ ranging [0-1] across the entire texture.
+ Smooth blending is only done on the x coordinate.
+ Wrapping is only supported on X as well.
+
+ @param fx Horizontal coordinate.
+ @param fy Vertical coordiate.
+ @param img The lookup image.
+ @param wrapX To wrap the x coordinate.
+ @return The interpolated colour.
+ */
+ DllExport Ogre::ColourValue getInterpolatedColour (float fx, float fy, Ogre::Image *img,
+ bool wrapX = true);
+}
+
+#endif // CAELUM_HEADER__IMAGE_HELPER_H
\ No newline at end of file
Modified: trunk/python-ogre/ThirdParty/caelum/LayeredClouds.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/LayeredClouds.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/LayeredClouds.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -1,6 +1,7 @@
#include "CaelumPrecompiled.h"
#include "LayeredClouds.h"
#include "CaelumExceptions.h"
+#include "ImageHelper.h"
namespace
{
@@ -22,13 +23,14 @@
const Ogre::String &meshName,
const Ogre::String &entityName
):
- mSceneMgr(scene)
+ mSceneMgr(scene),
+ mCloudCoverLookup(0)
{
// Create cloud plane mesh if it doesn't exist.
if (Ogre::MeshManager::getSingleton ().getByName (meshName).isNull ()) {
Ogre::Plane plane = Ogre::Plane(Ogre::Vector3::NEGATIVE_UNIT_Y, -0.1);
Ogre::MeshManager::getSingleton ().createCurvedPlane(
- meshName, resourceGroupName, plane, 2, 2, .4, 16, 16,
+ meshName, resourceGroupName, plane, 2, 2, .4, 64, 64,
false, 1, 1, 1, Ogre::Vector3::UNIT_Z);
}
@@ -54,6 +56,8 @@
getVpParams()->setIgnoreMissingParams(true);
// Default parameter values
+ assert(mCloudCoverLookup.get() == 0);
+ setCloudCoverLookup("CloudCoverLookup.png");
setCloudCover(0.5);
setCloudMassOffset(Ogre::Vector2(0, 0));
setCloudDetailOffset(Ogre::Vector2(0, 0));
@@ -191,10 +195,27 @@
}
void LayeredClouds::setCloudCover(const Ogre::Real cloudCover) {
- getFpParams()->setNamedConstant("cloudCover", mCloudCover = cloudCover);
+ mCloudCover = cloudCover;
+ float cloudCoverageThreshold = 0;
+ if (mCloudCoverLookup.get() != 0) {
+ cloudCoverageThreshold = getInterpolatedColour(cloudCover, 1, mCloudCoverLookup.get(), false).r;
+ } else {
+ cloudCoverageThreshold = 1 - cloudCover;
+ }
+ getFpParams()->setNamedConstant("cloudCoverageThreshold", cloudCoverageThreshold);
}
Ogre::Real LayeredClouds::getCloudCover() const {
return mCloudCover;
}
+
+ void LayeredClouds::setCloudCoverLookup (const Ogre::String& fileName) {
+ mCloudCoverLookup.reset(0);
+ mCloudCoverLookup.reset(new Ogre::Image());
+ mCloudCoverLookup->load (fileName, RESOURCE_GROUP_NAME);
+ }
+
+ void LayeredClouds::disableCloudCoverLookup () {
+ mCloudCoverLookup = 0;
+ }
} // namespace caelum
Modified: trunk/python-ogre/ThirdParty/caelum/LayeredClouds.h
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/LayeredClouds.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/LayeredClouds.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -53,6 +53,26 @@
*/
Ogre::Real getCloudCover () const;
+ /** Set the image used to lookup the cloud coverage threshold.
+ * This image is used to calculate the cloud coverage threshold
+ * based on the desired cloud cover.
+ *
+ * The cloud coverage threshold is substracted from cloud intensity
+ * at any point; to generate fewer or more clouds. That threshold is
+ * not linear, a lookup is required to ensure that setCloudCover(0.1)
+ * will actually have 10% the clouds at setCloudCover(1).
+ *
+ * The lookup is the inverse of the sum on the histogram, and was
+ * calculated with a small hacky tool.
+ */
+ void setCloudCoverLookup (const Ogre::String& fileName);
+
+ /** Disable any cloud cover lookup.
+ * @see setCloudCoverLookup.
+ */
+ void disableCloudCoverLookup ();
+
+
/** Sets blending factor between the two cloud mass layers.
*/
void setCloudMassBlend (const Ogre::Real cloudCover);
@@ -139,7 +159,11 @@
/// Current cloud detail layer offset.
Ogre::Vector2 mCloudDetailOffset;
+ /// Lookup used for cloud coverage.
+ /// see setCloudCoverLookup.
+ std::auto_ptr<Ogre::Image> mCloudCoverLookup;
+
/// If this class controls animation for itself.
bool mAnimating;
Modified: trunk/python-ogre/ThirdParty/caelum/SkyColourModel.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/SkyColourModel.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/SkyColourModel.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -1,5 +1,6 @@
#include "CaelumPrecompiled.h"
#include "SkyColourModel.h"
+#include "ImageHelper.h"
namespace caelum {
@@ -83,44 +84,4 @@
return col;
}
-Ogre::ColourValue SkyColourModel::getInterpolatedColour (float fx, float fy, Ogre::Image *img, bool wrapX) {
- // Don't -> all the time, and avoid unsigned warnings
- int imgWidth = static_cast<int>(img->getWidth ());
- int imgHeight = static_cast<int>(img->getHeight ());
-
- // Calculate pixel y coord.
- int py = Ogre::Math::IFloor(Ogre::Math::Abs (fy) * (imgHeight - 1));
- // Snap to py image bounds.
- py = std::max(0, std::min(py, imgHeight - 1));
-
- // Get the two closest pixels on x.
- // px1 and px2 are the closest integer pixels to px.
- float px = fx * (img->getWidth () - 1);
- int px1, px2;
- px1 = Ogre::Math::IFloor(px);
- px2 = Ogre::Math::ICeil(px);
-
- if (wrapX) {
- // Wrap x coords. The funny addition ensures that it does
- // "the right thing" for negative values.
- px1 = (px1 % imgWidth + imgWidth) % imgWidth;
- px2 = (px2 % imgWidth + imgWidth) % imgWidth;
- } else {
- px1 = std::max(0, std::min(px1, imgWidth - 1));
- px2 = std::max(0, std::min(px2, imgWidth - 1));
- }
-
- // Calculate the interpolated pixel
- Ogre::ColourValue c1, c2, cf;
- c1 = img->getColourAt (px1, py, 0);
- c2 = img->getColourAt (px2, py, 0);
-
- // Blend the two pixels together.
- // diff is the weight between pixel 1 and pixel 2.
- float diff = px - px1;
- cf = c1 * (1 - diff) + c2 * diff;
-
- return cf;
-}
-
} // namespace caelum
Modified: trunk/python-ogre/ThirdParty/caelum/SkyColourModel.h
===================================================================
--- trunk/python-ogre/ThirdParty/caelum/SkyColourModel.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/caelum/SkyColourModel.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -72,22 +72,6 @@
/// Sun colour is taken from this image.
/// 'resources/SunGradient.png' is the default image; but you can supply another
void setSunColoursImage (const Ogre::String &filename);
-
- protected:
- /** Gets the interpolated colour between two pixels from an image.
- Interpolate a texture pixel by hand. (fx, fy) are in texture coordinates,
- ranging [0-1] across the entire texture.
- Smooth blending is only done on the x coordinate.
- Wrapping is only supported on X as well.
-
- @param fx Horizontal coordinate.
- @param fy Vertical coordiate.
- @param img The lookup image.
- @param wrapX To wrap the x coordinate.
- @return The interpolated colour.
- */
- static Ogre::ColourValue getInterpolatedColour (float fx, float fy, Ogre::Image *img,
- bool wrapX = true);
};
} // namespace caelum
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -109,27 +109,7 @@
mLengthInSeconds = ov_time_total(&mOggStream, -1);
- mBuffers = new BufferRef[mNumBuffers];
- alGenBuffers(mNumBuffers, mBuffers);
- CheckError(alGetError(), "Could not generate buffer");
-
- for(int i = 0; i < mNumBuffers; i++)
- {
- CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
- Buffer buffer = bufferData(&mOggStream, mStream ? mBufferSize : 0);
- alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
- CheckError(alGetError(), "Could not load buffer data");
- }
-
- createAndBindSource();
-
- if(mStream)
- {
- // There is an issue with looping and streaming, so we will
- // disable looping and deal with it on our own.
- alSourcei (mSource, AL_LOOPING, AL_FALSE);
- CheckError(alGetError(), "Failed to set looping");
- }
+ generateBuffers();
}
catch(Ogre::Exception e)
{
@@ -153,39 +133,28 @@
ov_clear(&mOggStream);
}
- bool OggSound::play()
+ bool OggSound::loadBuffers()
{
- if(isStopped() && mStream)
+ for(int i = 0; i < mNumBuffers; i++)
{
- for(int i = 0; i < mNumBuffers; i++)
- {
- CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
- Buffer buffer = bufferData(&mOggStream, mStream ? mBufferSize : 0);
- alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
- CheckError(alGetError(), "Could not load buffer data");
- }
-
- alSourceQueueBuffers(mSource, mNumBuffers, mBuffers);
- CheckError(alGetError(), "Failed to queue Buffers");
+ CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
+ Buffer buffer = bufferData(&mOggStream, mStream ? mBufferSize : 0);
+ alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
+ CheckError(alGetError(), "Could not load buffer data");
}
- return Sound::play();
+ return true;
}
- bool OggSound::stop()
+ bool OggSound::unloadBuffers()
{
- if(Sound::stop())
+ if(mStream)
{
- return true;
+ ov_time_seek(&mOggStream, 0);
+ return false;
}
else
{
- if(mStream)
- {
- emptyQueues();
- ov_time_seek(&mOggStream, 0);
- }
-
return true;
}
}
@@ -200,7 +169,7 @@
{
bool wasPlaying = isPlaying();
- stop();
+ pause();
ov_time_seek(&mOggStream, seconds);
if(wasPlaying) play();
@@ -231,14 +200,14 @@
}
}
- bool OggSound::_updateSound()
+ bool OggSound::updateSound()
{
// Call the parent method to update the position
- Sound::_updateSound();
+ Sound::updateSound();
bool eof = false;
- if(mStream)
+ if(mStream && mSource != AL_NONE)
{
// Update the stream
int processed;
@@ -256,7 +225,7 @@
Buffer data = bufferData(&mOggStream, mBufferSize);
alBufferData(buffer, mFormat, &data[0], static_cast<Size>(data.size()), mFreq);
- eof = mSoundStream->eof();
+ eof = (mOggStream.offset == mOggStream.end);
alSourceQueueBuffers(mSource, 1, &buffer);
CheckError(alGetError(), "Failed to queue buffers");
@@ -301,10 +270,12 @@
while(buffer.size() < size)
{
sizeRead = ov_read(&mOggStream, data, mBufferSize, 0, 2, 1, §ion);
+ if(sizeRead == 0) break;
buffer.insert(buffer.end(), data, data + sizeRead);
}
}
-
+
+ delete[] data;
return buffer;
}
} // Namespace
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.h
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALOggSound.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -70,23 +70,23 @@
*/
OggSound(const Ogre::String& name, const Ogre::DataStreamPtr& soundStream, bool loop, bool stream);
- /// This is called each frame to update the position, direction, etc
- virtual bool _updateSound();
-
public:
/** Standard Destructor. */
virtual ~OggSound();
- /** Plays the sound. */
- virtual bool play();
- /** Stops the sound. @note Upon calling play again, the sound will resume from the begining */
- virtual bool stop();
-
/** Sets the offset within the audio stream in seconds */
virtual void setSecondOffset(Ogre::Real seconds);
/** Returns the current offset within the audio stream in seconds */
virtual Ogre::Real getSecondOffset();
+ protected:
+ /// This is called each frame to update the position, direction, etc
+ virtual bool updateSound();
+ /// Loads the buffers to be played. Returns whether the buffer is loaded.
+ virtual bool loadBuffers();
+ /// Unloads the buffers. Returns true if the buffers are still loaded.
+ virtual bool unloadBuffers();
+
private:
/// Returns a buffer containing the next chunk of length size
Buffer bufferData(OggVorbis_File *oggVorbisFile, int size);
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALPrereqs.h
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALPrereqs.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALPrereqs.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -88,6 +88,7 @@
typedef ALsizei Size;
typedef ALchar* ALString;
typedef std::vector<char> Buffer;
+ typedef std::queue<SourceRef> SourcePool;
/// Struct used with STL containers
struct DeleteObject
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALSound.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALSound.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALSound.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -50,7 +50,10 @@
mLengthInSeconds(0),
mBuffers(0),
mBufferSize(0),
- mNumBuffers(1),
+ mBuffersLoaded(false),
+ mBuffersQueued(false),
+ mPriority(NORMAL),
+ mStartTime(0),
mStream(false),
mPitch(1.0),
mGain(1.0),
@@ -83,7 +86,11 @@
mLengthInSeconds(0),
mBuffers(0),
mBufferSize(0),
+ mBuffersLoaded(false),
+ mBuffersQueued(false),
mNumBuffers(stream?2:1),
+ mPriority(NORMAL),
+ mStartTime(0),
mStream(stream),
MovableObject(name),
mPitch(1.0), mGain(1.0),
@@ -116,7 +123,11 @@
mChannels(0),
mLengthInSeconds(0),
mBufferSize(0),
+ mBuffersLoaded(true),
+ mBuffersQueued(false),
mNumBuffers(1),
+ mPriority(NORMAL),
+ mStartTime(0),
mStream(false),
MovableObject(name),
mLoop(loop?AL_TRUE:AL_FALSE),
@@ -150,13 +161,11 @@
// mBufferSize is equal to 1/4 of a second of audio
mLengthInSeconds = mSize / (mBufferSize * 4);
-
- createAndBindSource();
}
Sound::~Sound()
{
- emptyQueues();
+ stop();
try
{
@@ -169,26 +178,64 @@
// Don't die because of this.
}
- alSourcei(mSource, AL_BUFFER, 0);
- CheckError(alGetError(), "Failed to release buffer");
+ if(mSource != AL_NONE)
+ {
+ alSourcei(mSource, AL_BUFFER, 0);
+ CheckError(alGetError(), "Failed to release buffer");
+ }
- alDeleteSources(1, &mSource);
- CheckError(alGetError(), "Failed to release source");
+ delete[] mBuffers;
+
+ SoundManager::getSingleton()._releaseSource(this);
}
bool Sound::play()
{
if(isPlaying()) return true;
- alSourcePlay(mSource);
- CheckError(alGetError(), "Failed to play sound");
+ if(mStartTime == 0)
+ {
+ time(&mStartTime);
+ }
+ else if(!isPaused())
+ {
+ time_t currentTime;
+ time(¤tTime);
+ setSecondOffset(currentTime - mStartTime);
+ }
+
+ if(mSource != AL_NONE || (mSource = SoundManager::getSingleton()._requestSource(this)) != AL_NONE)
+ {
+ if(!mBuffersLoaded)
+ {
+ mBuffersLoaded = loadBuffers();
+ }
+
+ if(!mBuffersQueued)
+ {
+ // Unqueue any buffers that may be left over
+ unqueueBuffers();
+ queueBuffers();
+ }
+
+ initSource();
+
+ alSourcePlay(mSource);
+ CheckError(alGetError(), "Failed to play sound");
+ }
+
return false;
}
bool Sound::isPlaying() const
{
- State state;
+ if(mSource == AL_NONE)
+ {
+ return false;
+ }
+
+ State state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
CheckError(alGetError(), "Failed to get State");
@@ -199,14 +246,22 @@
{
if(!isPlaying()) return true;
- alSourcePause(mSource);
- CheckError(alGetError(), "Failed to pause sound");
+ if(mSource != AL_NONE)
+ {
+ alSourcePause(mSource);
+ CheckError(alGetError(), "Failed to pause sound");
+ }
return false;
}
bool Sound::isPaused() const
{
+ if(mSource == AL_NONE)
+ {
+ return false;
+ }
+
State state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
CheckError(alGetError(), "Failed to get State");
@@ -216,16 +271,39 @@
bool Sound::stop()
{
- if(isStopped()) return true;
+ if(isStopped())
+ {
+ if(mSource != AL_NONE)
+ {
+ mSource = SoundManager::getSingleton()._releaseSource(this);
+ return true;
+ }
+ }
+ else if(mSource != AL_NONE)
+ {
+ // Stop the source
+ alSourceStop(mSource);
+ CheckError(alGetError(), "Failed to stop sound");
- alSourceStop(mSource);
- CheckError(alGetError(), "Failed to stop sound");
+ unqueueBuffers();
- return false;
+ mBuffersLoaded = unloadBuffers();
+ }
+
+ mSource = SoundManager::getSingleton()._releaseSource(this);
+
+ mStartTime = 0;
+
+ return true;
}
bool Sound::isStopped() const
{
+ if(mSource == AL_NONE)
+ {
+ return true;
+ }
+
State state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
CheckError(alGetError(), "Failed to get State");
@@ -235,6 +313,11 @@
bool Sound::isInitial() const
{
+ if(mSource == AL_NONE)
+ {
+ return true;
+ }
+
State state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
CheckError(alGetError(), "Failed to get State");
@@ -245,50 +328,78 @@
void Sound::setPitch(Ogre::Real pitch)
{
mPitch = pitch;
- alSourcef(mSource, AL_PITCH, mPitch);
- CheckError(alGetError(), "Failed to set Pitch");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_PITCH, mPitch);
+ CheckError(alGetError(), "Failed to set Pitch");
+ }
}
void Sound::setGain(Ogre::Real gain)
{
mGain = gain;
- alSourcef(mSource, AL_GAIN, mGain);
- CheckError(alGetError(), "Failed to set Gain");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_GAIN, mGain);
+ CheckError(alGetError(), "Failed to set Gain");
+ }
}
void Sound::setMaxGain(Ogre::Real maxGain)
{
mMaxGain = maxGain;
- alSourcef(mSource, AL_MAX_GAIN, mMaxGain);
- CheckError(alGetError(), "Failed to set Max Gain");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_MAX_GAIN, mMaxGain);
+ CheckError(alGetError(), "Failed to set Max Gain");
+ }
}
void Sound::setMinGain(Ogre::Real minGain)
{
mMinGain = minGain;
- alSourcef(mSource, AL_MIN_GAIN, mMinGain);
- CheckError(alGetError(), "Failed to set Min Gain");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_MIN_GAIN, mMinGain);
+ CheckError(alGetError(), "Failed to set Min Gain");
+ }
}
void Sound::setMaxDistance(Ogre::Real maxDistance)
{
mMaxDistance = maxDistance;
- alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
- CheckError(alGetError(), "Failed to set Max Distance");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
+ CheckError(alGetError(), "Failed to set Max Distance");
+ }
}
void Sound::setRolloffFactor(Ogre::Real rolloffFactor)
{
mRolloffFactor = rolloffFactor;
- alSourcef(mSource, AL_ROLLOFF_FACTOR, mRolloffFactor);
- CheckError(alGetError(), "Failed to set Rolloff Factor");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_ROLLOFF_FACTOR, mRolloffFactor);
+ CheckError(alGetError(), "Failed to set Rolloff Factor");
+ }
}
void Sound::setReferenceDistance(Ogre::Real refDistance)
{
mReferenceDistance = refDistance;
- alSourcef(mSource, AL_REFERENCE_DISTANCE, mReferenceDistance);
- CheckError(alGetError(), "Failed to set Reference Distance");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_REFERENCE_DISTANCE, mReferenceDistance);
+ CheckError(alGetError(), "Failed to set Reference Distance");
+ }
}
void Sound::setDistanceValues(Ogre::Real maxDistance, Ogre::Real rolloffFactor, Ogre::Real refDistance)
@@ -303,8 +414,12 @@
mVelocity.x = x;
mVelocity.y = y;
mVelocity.z = z;
- alSource3f(mSource, AL_VELOCITY, mVelocity.x, mVelocity.y, mVelocity.z);
- CheckError(alGetError(), "Failed to set Velocity");
+
+ if(mSource != AL_NONE)
+ {
+ alSource3f(mSource, AL_VELOCITY, mVelocity.x, mVelocity.y, mVelocity.z);
+ CheckError(alGetError(), "Failed to set Velocity");
+ }
}
void Sound::setVelocity(const Ogre::Vector3& vec)
@@ -318,49 +433,77 @@
if(mParentNode) return;
mSourceRelative = relative;
- alSourcei(mSource, AL_SOURCE_RELATIVE, mSourceRelative);
- CheckError(alGetError(), "Failed to set Source Relative");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcei(mSource, AL_SOURCE_RELATIVE, mSourceRelative);
+ CheckError(alGetError(), "Failed to set Source Relative");
+ }
}
void Sound::setOuterConeGain(Ogre::Real outerConeGain)
{
mOuterConeGain = outerConeGain;
- alSourcef(mSource, AL_CONE_OUTER_GAIN, mOuterConeGain);
- CheckError(alGetError(), "Failed to set Outer Cone Gain");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_CONE_OUTER_GAIN, mOuterConeGain);
+ CheckError(alGetError(), "Failed to set Outer Cone Gain");
+ }
}
void Sound::setInnerConeAngle(Ogre::Real innerConeAngle)
{
mInnerConeAngle = innerConeAngle;
- alSourcef(mSource, AL_CONE_INNER_ANGLE, mInnerConeAngle);
- CheckError(alGetError(), "Failed to set Inner Cone Angle");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_CONE_INNER_ANGLE, mInnerConeAngle);
+ CheckError(alGetError(), "Failed to set Inner Cone Angle");
+ }
}
void Sound::setOuterConeAngle(Ogre::Real outerConeAngle)
{
mOuterConeAngle = outerConeAngle;
- alSourcef(mSource, AL_CONE_OUTER_ANGLE, mOuterConeAngle);
- CheckError(alGetError(), "Failed to set Outer Cone Angle");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_CONE_OUTER_ANGLE, mOuterConeAngle);
+ CheckError(alGetError(), "Failed to set Outer Cone Angle");
+ }
}
void Sound::setLoop(bool loop)
{
mLoop = loop?AL_TRUE:AL_FALSE;
- alSourcei(mSource, AL_LOOPING, mLoop);
- CheckError(alGetError(), "Failed to set Looping");
+
+ if(mSource != AL_NONE)
+ {
+ alSourcei(mSource, AL_LOOPING, mLoop);
+ CheckError(alGetError(), "Failed to set Looping");
+ }
}
void Sound::setSecondOffset(Ogre::Real seconds)
{
- alSourcef(mSource, AL_SEC_OFFSET, seconds);
- CheckError(alGetError(), "Failed to set offset");
+ if(mSource != AL_NONE)
+ {
+ alSourcef(mSource, AL_SEC_OFFSET, seconds);
+ CheckError(alGetError(), "Failed to set offset");
+ }
}
Ogre::Real Sound::getSecondOffset()
{
Ogre::Real offset = 0;
- alGetSourcef(mSource, AL_SEC_OFFSET, &offset);
- CheckError(alGetError(), "Failed to set Looping");
+
+ if(mSource != AL_NONE)
+ {
+ alGetSourcef(mSource, AL_SEC_OFFSET, &offset);
+ CheckError(alGetError(), "Failed to set Looping");
+ }
+
return offset;
}
@@ -416,35 +559,29 @@
mLocalTransformDirty = false;
}
- bool Sound::_updateSound()
+ bool Sound::updateSound()
{
_update();
- alSource3f(mSource, AL_POSITION, mDerivedPosition.x, mDerivedPosition.y, mDerivedPosition.z);
- CheckError(alGetError(), "Failed to set Position");
- alSource3f(mSource, AL_DIRECTION, mDerivedDirection.x, mDerivedDirection.y, mDerivedDirection.z);
- CheckError(alGetError(), "Failed to set Direction");
+ if(mSource != AL_NONE)
+ {
+ alSource3f(mSource, AL_POSITION, mDerivedPosition.x, mDerivedPosition.y, mDerivedPosition.z);
+ CheckError(alGetError(), "Failed to set Position");
+
+ alSource3f(mSource, AL_DIRECTION, mDerivedDirection.x, mDerivedDirection.y, mDerivedDirection.z);
+ CheckError(alGetError(), "Failed to set Direction");
+ }
+
return true;
}
- void Sound::createAndBindSource()
+ void Sound::initSource()
{
- if(SoundManager::getSingleton().xRamSupport())
+ if(mSource == AL_NONE)
{
- SoundManager::getSingleton().eaxSetBufferMode(mNumBuffers, mBuffers, SoundManager::xRamHardware);
+ return;
}
- alGenSources(1, &mSource);
- CheckError(alGetError(), "Failed to generate source");
-
- initSource();
-
- alSourceQueueBuffers(mSource, mNumBuffers, mBuffers);
- CheckError(alGetError(), "Failed to bind Buffer");
- }
-
- void Sound::initSource()
- {
alSourcef (mSource, AL_PITCH, mPitch);
alSourcef (mSource, AL_GAIN, mGain);
alSourcef (mSource, AL_MAX_GAIN, mMaxGain);
@@ -459,10 +596,24 @@
alSource3f(mSource, AL_VELOCITY, mVelocity.x, mVelocity.y, mVelocity.z);
alSource3f(mSource, AL_DIRECTION, mDerivedDirection.x, mDerivedDirection.y, mDerivedDirection.z);
alSourcei (mSource, AL_SOURCE_RELATIVE, mSourceRelative);
- alSourcei (mSource, AL_LOOPING, mLoop);
+ // There is an issue with looping and streaming, so we will
+ // disable looping and deal with it on our own.
+ alSourcei (mSource, AL_LOOPING, mStream ? AL_FALSE : mLoop);
CheckError(alGetError(), "Failed to initialize source");
}
+ void Sound::generateBuffers()
+ {
+ mBuffers = new BufferRef[mNumBuffers];
+ alGenBuffers(mNumBuffers, mBuffers);
+ CheckError(alGetError(), "Could not generate buffer");
+
+ if(SoundManager::getSingleton().xRamSupport())
+ {
+ SoundManager::getSingleton().eaxSetBufferMode(mNumBuffers, mBuffers, SoundManager::xRamHardware);
+ }
+ }
+
void Sound::calculateFormatInfo()
{
switch(mChannels)
@@ -542,22 +693,32 @@
}
}
- void Sound::emptyQueues()
+ void Sound::queueBuffers()
{
+ alSourceQueueBuffers(mSource, mNumBuffers, mBuffers);
+ CheckError(alGetError(), "Failed to bind Buffer");
+ }
+
+ void Sound::unqueueBuffers()
+ {
/*
** If the sound doens't have a state yet it causes an
- ** error when you try to unqueue the buffers! :S
+ ** error when you try to unqueue the buffers! :S In
+ ** order to get around this we stop the source even if
+ ** it wasn't playing.
*/
- if(isInitial()) play();
+ alSourceStop(mSource);
+ CheckError(alGetError(), "Failed to stop sound");
- stop();
-
int queued;
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
CheckError(alGetError(), "Failed to get Source");
alSourceUnqueueBuffers(mSource, queued, mBuffers);
CheckError(alGetError(), "Failed to unqueue Buffers");
+
+
+ mBuffersQueued = false;
}
const Ogre::String& Sound::getMovableType(void) const
@@ -583,8 +744,11 @@
if(mSourceRelative)
{
mSourceRelative = false;
- alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE);
- CheckCondition(alGetError() == AL_NO_ERROR, 13, "Inalid Value");
+ if(mSource != AL_NONE)
+ {
+ alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE);
+ CheckCondition(alGetError() == AL_NO_ERROR, 13, "Inalid Value");
+ }
}
mParentNode = parent;
_update();
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALSound.h
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALSound.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALSound.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -66,8 +66,15 @@
/** Standard Destructor */
virtual ~Sound();
+ enum Priority
+ {
+ LOW,
+ NORMAL,
+ HIGH
+ };
+
/** Plays the sound. */
- virtual bool play();
+ bool play();
/** Returns true if the sound is playing, otherwise false. */
virtual bool isPlaying() const;
/** Pauses the sound. @note Upon calling play again, the sound will resume where it left off */
@@ -75,7 +82,7 @@
/** Returns true if the sound is paused, otherwise false. */
virtual bool isPaused() const;
/** Stops the sound. @note Upon calling play again, the sound will resume from the begining */
- virtual bool stop();
+ bool stop();
/** Returns true if the sound is stopped, otherwise false. */
virtual bool isStopped() const;
/** Returns true if the source does not have a state yet, otherwise false */
@@ -252,6 +259,10 @@
bool isLooping() const {return mLoop==AL_TRUE?true:false;}
/** Returns streaming state */
bool isStreaming() const {return mStream==AL_TRUE?true:false;}
+ /** Sets the priority of the sound */
+ void setPriority(Priority priority) {mPriority = priority;}
+ /** Returns the current Priority for the sound */
+ Priority getPriority() const {return mPriority;}
/** Returns the duration of the audio in seconds */
Ogre::Real getSecondDuration() {return mLengthInSeconds;}
/** Sets the offset within the audio stream in seconds */
@@ -264,6 +275,7 @@
const Ogre::Vector3& getDerivedDirection() const {return mDerivedDirection;}
/** Returns the name of the file used to create this Sound. */
const Ogre::String& getFileName() const {return mFileName;}
+
/** Overridden from MovableObject */
const Ogre::String& getMovableType() const;
/** Overridden from MovableObject */
@@ -281,15 +293,25 @@
protected:
/// Updates the sound if need be
- virtual bool _updateSound();
- /// Creates the source and binds the buffer
- void createAndBindSource();
+ virtual bool updateSound();
+ /// Sets the source for the sound
+ void setSource(SourceRef source) {mSource = source;}
+ /// Returns the SourceRef
+ SourceRef getSource() {return mSource;}
/// Convienance method to reset the sound state
void initSource();
+ /// Convienance method for creating buffers
+ void generateBuffers();
/// Calculates format info for the sounds. @note requires mFreq, mChannels and mBPS;
void calculateFormatInfo();
+ /// Queues buffers to be played
+ void queueBuffers();
/// Empties any queues that may still be active in the sound
- void emptyQueues();
+ void unqueueBuffers();
+ /// Loads the buffers to be played. Returns whether the buffer is loaded.
+ virtual bool loadBuffers() {return true;}
+ /// Unloads the buffers. Returns true if the buffers are still loaded.
+ virtual bool unloadBuffers() {return true;}
/// Returns the BufferRef for this sounds
BufferRef getBufferRef() const {return mBuffers[0];}
@@ -328,12 +350,19 @@
int mNumBuffers;
int mBufferSize;
bool mStream;
+ bool mBuffersLoaded;
+ bool mBuffersQueued;
Size mFreq;
Size mSize;
Size mChannels;
Size mBPS;
BufferFormat mFormat;
+ Priority mPriority;
+
+ // This allows us to start a sound back where is should be after being sacrificed
+ time_t mStartTime;
+
Ogre::Real mLengthInSeconds;
friend class SoundManager;
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -51,6 +51,8 @@
mEAXSupport(false),
mEAXVersion(0),
mXRAMSupport(false),
+ mEFXSupport(false),
+ mSendsPerSource(10),
mContext(0),
mDevice(0),
mDopplerFactor(1.0),
@@ -86,6 +88,22 @@
destroyAllSounds();
delete Listener::getSingletonPtr();
+ // Clean out mActiveSounds and mQueuedSounds
+ mActiveSounds.clear();
+ mQueuedSounds.clear();
+
+ // Clean up the SourcePool
+ while(!mSourcePool.empty())
+ {
+ alDeleteSources(1, &mSourcePool.front());
+ CheckError(alcGetError(mDevice), "Failed to destroy source");
+ mSourcePool.pop();
+ }
+
+ // delete all FormatData pointers in the FormatMap;
+ std::for_each(mSupportedFormats.begin(), mSupportedFormats.end(), DeleteSecond());
+ mSupportedFormats.clear();
+
// Unregister the Sound and Listener Factories
Ogre::Root::getSingleton().removeMovableObjectFactory(mSoundFactory);
Ogre::Root::getSingleton().removeMovableObjectFactory(mListenerFactory);
@@ -93,10 +111,6 @@
delete mListenerFactory;
delete mSoundFactory;
- // delete all FormatData pointers in the FormatMap;
- std::for_each(mSupportedFormats.begin(), mSupportedFormats.end(), DeleteSecond());
- mSupportedFormats.clear();
-
Ogre::LogManager::getSingleton().logMessage("*-*-* Releasing OpenAL");
// Release the OpenAL Context and the Audio device
@@ -220,15 +234,116 @@
{
void operator()(std::pair<std::string, Sound*> pair)const
{
- pair.second->_updateSound();
+ pair.second->updateSound();
}
};
+ struct SoundManager::SortLowToHigh
+ {
+ bool operator()(const Sound *sound1, const Sound *sound2)const
+ {
+ // First we see if either sound has stopped and not given up its source
+ if(sound1->isStopped())
+ return true;
+ else if(sound2->isStopped())
+ return false;
+
+ // If they are both playing we'll test priority
+ if(sound1->getPriority() < sound2->getPriority())
+ return true;
+ else if (sound1->getPriority() > sound2->getPriority())
+ return false;
+
+ // If they are the same priority we'll test against the
+ // distance from the listener
+ Ogre::Real distSound1, distSound2;
+ Ogre::Vector3 listenerPos = Listener::getSingleton().getDerivedPosition();
+ if(sound1->isRelativeToListener())
+ {
+ distSound1 = sound1->getPosition().length();
+ }
+ else
+ {
+ distSound1 = sound1->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(sound2->isRelativeToListener())
+ {
+ distSound2 = sound1->getPosition().length();
+ }
+ else
+ {
+ distSound2 = sound2->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(distSound1 > distSound2)
+ return true;
+ else if(distSound1 < distSound2)
+ return false;
+
+ // If they are at the same priority and distance from the listener then
+ // they are both equally well suited to being sacrificed so we compare
+ // their pointers since it really doesn't matter
+ return sound1 < sound2;
+ }
+ };
+
+ struct SoundManager::SortHighToLow
+ {
+ bool operator()(const Sound *sound1, const Sound *sound2)const
+ {
+ // First we'll test priority
+ if(sound1->getPriority() > sound2->getPriority())
+ return true;
+ else if (sound1->getPriority() < sound2->getPriority())
+ return false;
+
+ // If they are the same priority we'll test against the
+ // distance from the listener
+ Ogre::Real distSound1, distSound2;
+ Ogre::Vector3 listenerPos = Listener::getSingleton().getDerivedPosition();
+ if(sound1->isRelativeToListener())
+ {
+ distSound1 = sound1->getPosition().length();
+ }
+ else
+ {
+ distSound1 = sound1->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(sound2->isRelativeToListener())
+ {
+ distSound2 = sound1->getPosition().length();
+ }
+ else
+ {
+ distSound2 = sound2->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(distSound1 < distSound2)
+ return true;
+ else if(distSound1 > distSound2)
+ return false;
+
+ // If they are at the same priority and distance from the listener then
+ // they are both equally well suited to stealing a source so we compare
+ // their pointers since it really doesn't matter
+ return sound1 < sound2;
+ }
+ };
+
bool SoundManager::frameStarted(const Ogre::FrameEvent& evt)
{
// Update the Sound and Listeners if necessary
std::for_each(mSoundMap.begin(), mSoundMap.end(), UpdateSound());
Listener::getSingleton().updateListener();
+
+ // Sort the active and queued sounds
+ std::sort(mActiveSounds.begin(), mActiveSounds.end(), SortLowToHigh());
+ std::sort(mQueuedSounds.begin(), mQueuedSounds.end(), SortHighToLow());
+
+ // Check to see if we should sacrifice any sounds
+ updateSourceAllocations();
return true;
}
@@ -249,6 +364,7 @@
Ogre::StringVector SoundManager::getDeviceList()
{
const ALCchar* deviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+ CheckError(alGetError(), "Unable to list devices");
Ogre::StringVector deviceVector;
/*
@@ -263,20 +379,33 @@
*/
while(*deviceList != NULL)
{
- ALCdevice *device = alcOpenDevice(deviceList);
- if(device)
+ try
{
- // Device seems to be valid
- ALCcontext *context = alcCreateContext(device, NULL);
- if(context)
+ ALCdevice *device = alcOpenDevice(deviceList);
+ CheckError(alGetError(), "Unable to open device");
+
+ if(device)
{
- // Context seems to be valid
- alcMakeContextCurrent(context);
- deviceVector.push_back(alcGetString(device, ALC_DEVICE_SPECIFIER));
- alcDestroyContext(context);
+ // Device seems to be valid
+ ALCcontext *context = alcCreateContext(device, NULL);
+ CheckError(alGetError(), "Unable to create context");
+ if(context)
+ {
+ // Context seems to be valid
+ alcMakeContextCurrent(context);
+ CheckError(alGetError(), "Unable to make context current");
+ deviceVector.push_back(alcGetString(device, ALC_DEVICE_SPECIFIER));
+ alcDestroyContext(context);
+ CheckError(alGetError(), "Unable to destroy context");
+ }
+ alcCloseDevice(device);
}
- alcCloseDevice(device);
}
+ catch(...)
+ {
+ // Don't die here, we'll just skip this device.
+ }
+
deviceList += strlen(deviceList) + 1;
}
@@ -327,19 +456,118 @@
mSoundFactory->_removeBufferRef(bufferName);
}
- int SoundManager::_getMaxSources()
+ SourceRef SoundManager::_requestSource(Sound *sound)
{
+ if(sound->getSource() != AL_NONE)
+ {
+ // This sound already has a source, so we'll just return the same one
+ return sound->getSource();
+ }
+
+ SoundList::iterator soundItr;
+ for(soundItr = mQueuedSounds.begin(); soundItr != mQueuedSounds.end(); soundItr++)
+ {
+ if((*soundItr) == sound)
+ {
+ // This sound has already requested a source
+ return AL_NONE;
+ break;
+ }
+ }
+
+ if(!mSourcePool.empty())
+ {
+ mActiveSounds.push_back(sound);
+ SourceRef source = mSourcePool.front();
+ mSourcePool.pop();
+ return source;
+ }
+ else
+ {
+ Sound *activeSound = mActiveSounds.front();
+ Ogre::Vector3 listenerPos = Listener::getSingleton().getDerivedPosition();
+ Ogre::Real distSound = sound->getDerivedPosition().distance(listenerPos);
+ Ogre::Real distActiveSound = activeSound->getDerivedPosition().distance(listenerPos);
+
+ if(sound->getPriority() > activeSound->getPriority() ||
+ sound->getPriority() == activeSound->getPriority() && distSound < distActiveSound)
+ {
+ activeSound->pause();
+ SourceRef source = activeSound->getSource();
+ mActiveSounds.erase(mActiveSounds.begin());
+ mQueuedSounds.push_back(activeSound);
+
+ mActiveSounds.push_back(sound);
+ return source;
+ }
+ else
+ {
+ mQueuedSounds.push_back(sound);
+ return AL_NONE;
+ }
+ }
+ }
+
+ SourceRef SoundManager::_releaseSource(Sound *sound)
+ {
+ bool soundFound = false;
+ SoundList::iterator soundItr;
+ for(soundItr = mActiveSounds.begin(); soundItr != mActiveSounds.end(); soundItr++)
+ {
+ if((*soundItr) == sound)
+ {
+ mActiveSounds.erase(soundItr);
+ soundFound = true;
+ break;
+ }
+ }
+
+ // If it's not in the active list, check the queued list
+ if(!soundFound)
+ {
+ for(soundItr = mQueuedSounds.begin(); soundItr != mQueuedSounds.end(); soundItr++)
+ {
+ if((*soundItr) == sound)
+ {
+ mQueuedSounds.erase(soundItr);
+ break;
+ }
+ }
+ }
+
+ SourceRef source = sound->getSource();
+ if(source != AL_NONE)
+ {
+ if(!mQueuedSounds.empty())
+ {
+ Sound *queuedSound = mQueuedSounds.front();
+ mQueuedSounds.erase(mQueuedSounds.begin());
+
+ queuedSound->setSource(source);
+ queuedSound->play();
+ mActiveSounds.push_back(queuedSound);
+ }
+ else
+ {
+ mSourcePool.push(source);
+ }
+ }
+
+ return AL_NONE;
+ }
+
+ int SoundManager::createSourcePool()
+ {
SourceRef source;
- std::vector<SourceRef> sources;
int numSources = 0;
- while (alGetError() == AL_NO_ERROR && numSources < 32)
+ while(alGetError() == AL_NO_ERROR && numSources < 100)
{
source = 0;
alGenSources(1, &source);
- if (source != 0)
+ if(source != 0)
{
- sources.push_back(source);
+ mSourcePool.push(source);
numSources++;
}
else
@@ -350,20 +578,11 @@
}
}
- for(std::vector<SourceRef>::iterator it = sources.begin(); it != sources.end(); it++)
- {
- source = static_cast<SourceRef>(*it);
- alDeleteSources(1, &source);
- CheckError(alGetError(), "Failed to delete Source");
- }
-
return numSources;
}
void SoundManager::initializeDevice(const Ogre::String& deviceName)
{
- bool deviceInList = false;
-
Ogre::LogManager::getSingleton().logMessage("OpenAL Devices");
Ogre::LogManager::getSingleton().logMessage("--------------");
@@ -371,8 +590,9 @@
// List devices in log and see if the sugested device is in the list
Ogre::StringVector deviceList = getDeviceList();
+ bool deviceInList = false;
Ogre::StringVector::iterator deviceItr;
- for(deviceItr = deviceList.begin(); deviceItr != deviceList.end(); deviceItr++)
+ for(deviceItr = deviceList.begin(); deviceItr != deviceList.end() && (*deviceItr).compare("") != 0; deviceItr++)
{
deviceInList = (*deviceItr).compare(deviceName) == 0;
ss << " * " << (*deviceItr);
@@ -445,6 +665,12 @@
}
}
+ // Check for EFX Support
+ if(alcIsExtensionPresent(mDevice, "ALC_EXT_EFX") == AL_TRUE)
+ {
+ Ogre::LogManager::getSingleton().logMessage("EFX Extension Found");
+ }
+
// Check for X-RAM extension
if(alIsExtensionPresent("EAX-RAM") == AL_TRUE)
{
@@ -460,7 +686,63 @@
" (" + Ogre::StringConverter::toString(mXRamFree) + " free)");
}
- // See how many sources the harware allows
- mMaxNumSources = _getMaxSources();
+ // Create our pool of sources
+ mMaxNumSources = createSourcePool();
}
+
+ void SoundManager::updateSourceAllocations()
+ {
+ while(!mQueuedSounds.empty())
+ {
+ Sound *queuedSound = mQueuedSounds.front();
+ Sound *activeSound = mActiveSounds.front();
+
+ Ogre::Real distQueuedSound, distActiveSound;
+ Ogre::Vector3 listenerPos = Listener::getSingleton().getDerivedPosition();
+ if(queuedSound->isRelativeToListener())
+ {
+ distQueuedSound = queuedSound->getPosition().length();
+ }
+ else
+ {
+ distQueuedSound = queuedSound->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(activeSound->isRelativeToListener())
+ {
+ distActiveSound = activeSound->getPosition().length();
+ }
+ else
+ {
+ distActiveSound = activeSound->getDerivedPosition().distance(listenerPos);
+ }
+
+ if(queuedSound->getPriority() > activeSound->getPriority() ||
+ queuedSound->getPriority() == activeSound->getPriority() && distQueuedSound < distActiveSound)
+ {
+ // Remove the sounds from their respective lists
+ mActiveSounds.erase(mActiveSounds.begin());
+ mQueuedSounds.erase(mQueuedSounds.begin());
+
+ // Steal the source from the currently active sound
+ activeSound->pause();
+ activeSound->unqueueBuffers();
+ SourceRef source = activeSound->getSource();
+ activeSound->setSource(AL_NONE);
+
+ // Kickstart the currently queued sound
+ queuedSound->setSource(source);
+ queuedSound->play();
+
+ // Add the sound back to the correct lists
+ mActiveSounds.push_back(queuedSound);
+ mQueuedSounds.push_back(activeSound);
+ }
+ else
+ {
+ // We have no more sounds that we can sacrifice
+ break;
+ }
+ }
+ }
} // Namespace
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.h
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALSoundManager.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -174,6 +174,9 @@
/** Removes a BufferRef from the BufferMap */
void _removeBufferRef(const Ogre::String& bufferName);
+ SourceRef _requestSource(Sound *sound);
+ SourceRef _releaseSource(Sound *sound);
+
static const Ogre::String FILE_TYPE;
static const Ogre::String OGG;
static const Ogre::String WAV;
@@ -198,15 +201,20 @@
bool mEAXSupport;
int mEAXVersion;
bool mXRAMSupport;
+ bool mEFXSupport;
+ int mSendsPerSource;
Ogre::Real mDopplerFactor;
Ogre::Real mSpeedOfSound;
private:
- int _getMaxSources();
+ int createSourcePool();
void createListener();
void initializeDevice(const Ogre::String& deviceName);
void checkFeatureSupport();
+ void updateSourceAllocations();
struct UpdateSound;
+ struct SortLowToHigh;
+ struct SortHighToLow;
int mMaxNumSources;
FormatMap mSupportedFormats;
@@ -214,6 +222,10 @@
SoundMap mSoundMap;
SoundList mPauseResumeAll;
+ SourcePool mSourcePool;
+ SoundList mActiveSounds;
+ SoundList mQueuedSounds;
+
ALCcontext *mContext;
ALCdevice *mDevice;
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.cpp
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.cpp 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.cpp 2007-12-16 14:20:20 UTC (rev 499)
@@ -114,29 +114,9 @@
calculateFormatInfo();
// mBufferSize is equal to 1/4 of a second of audio
- mLengthInSeconds = mDataSize / (mBufferSize * 4);
+ mLengthInSeconds = (float)mDataSize / ((float)mBufferSize * 4);
- mBuffers = new BufferRef[mNumBuffers];
- alGenBuffers(mNumBuffers, mBuffers);
- CheckError(alGetError(), "Could not generate buffer");
-
- for(int i = 0; i < mNumBuffers; i++)
- {
- CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
- Buffer buffer = bufferData(mSoundStream, mStream?mBufferSize:mDataSize);
- alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
- CheckError(alGetError(), "Could not load buffer data");
- }
-
- createAndBindSource();
-
- if(mStream)
- {
- // There is an issue with looping and streaming, so we will
- // disable looping and deal with it on our own.
- alSourcei (mSource, AL_LOOPING, AL_FALSE);
- CheckError(alGetError(), "Failed to set looping");
- }
+ generateBuffers();
}
catch(Ogre::Exception e)
{
@@ -156,39 +136,28 @@
WavSound::~WavSound()
{}
- bool WavSound::play()
+ bool WavSound::loadBuffers()
{
- if(isStopped() && mStream)
+ for(int i = 0; i < mNumBuffers; i++)
{
- for(int i = 0; i < mNumBuffers; i++)
- {
- CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
- Buffer buffer = bufferData(mSoundStream, mStream?mBufferSize:mDataSize);
- alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
- CheckError(alGetError(), "Could not load buffer data");
- }
-
- alSourceQueueBuffers(mSource, mNumBuffers, mBuffers);
- CheckError(alGetError(), "Failed to queue Buffers");
+ CheckCondition(AL_NONE != mBuffers[i], 13, "Could not generate buffer");
+ Buffer buffer = bufferData(mSoundStream, mStream?mBufferSize:mDataSize);
+ alBufferData(mBuffers[i], mFormat, &buffer[0], static_cast<Size>(buffer.size()), mFreq);
+ CheckError(alGetError(), "Could not load buffer data");
}
- return Sound::play();
+ return true;
}
- bool WavSound::stop()
+ bool WavSound::unloadBuffers()
{
- if(Sound::stop())
+ if(mStream)
{
- return true;
+ mSoundStream->seek(mDataStart);
+ return false;
}
else
{
- if(mStream)
- {
- emptyQueues();
- mSoundStream->seek(mDataStart);
- }
-
return true;
}
}
@@ -203,7 +172,7 @@
{
bool wasPlaying = isPlaying();
- stop();
+ pause();
// mBufferSize is 1/4 of a second
size_t dataOffset = static_cast<size_t>(seconds * mBufferSize * 4);
@@ -230,7 +199,7 @@
*/
// mBufferSize is 1/4 of a second
- Ogre::Real wavStreamOffset = (mSoundStream->tell() - mDataStart) / (mBufferSize * 4);
+ Ogre::Real wavStreamOffset = (float)(mSoundStream->tell() - mDataStart) / (float)(mBufferSize * 4);
Ogre::Real bufferOffset = Sound::getSecondOffset();
Ogre::Real totalOffset = wavStreamOffset + (0.25 - bufferOffset);
@@ -238,14 +207,14 @@
}
}
- bool WavSound::_updateSound()
+ bool WavSound::updateSound()
{
// Call the parent method to update the position
- Sound::_updateSound();
+ Sound::updateSound();
bool eof = false;
- if(mStream)
+ if(mStream && mSource != AL_NONE)
{
// Update the stream
int processed;
Modified: trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.h
===================================================================
--- trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.h 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/ThirdParty/ogreal/OgreALWavSound.h 2007-12-16 14:20:20 UTC (rev 499)
@@ -68,23 +68,23 @@
*/
WavSound(const Ogre::String& name, const Ogre::DataStreamPtr& soundStream, bool loop, bool stream);
- /// This is called each frame to update the position, direction, etc
- virtual bool _updateSound();
-
public:
/** Standard Destructor. */
virtual ~WavSound();
- /** Plays the sound. */
- virtual bool play();
- /** Stops the sound. @note Upon calling play again, the sound will resume from the begining */
- virtual bool stop();
-
/** Sets the offset within the audio stream in seconds */
virtual void setSecondOffset(Ogre::Real seconds);
/** Returns the current offset within the audio stream in seconds */
virtual Ogre::Real getSecondOffset();
+ protected:
+ /// This is called each frame to update the position, direction, etc
+ virtual bool updateSound();
+ /// Loads the buffers to be played. Returns whether the buffer is loaded.
+ virtual bool loadBuffers();
+ /// Unloads the buffers. Returns true if the buffers are still loaded.
+ virtual bool unloadBuffers();
+
private:
Buffer bufferData(Ogre::DataStreamPtr dataStream, int size);
size_t mDataStart;
Modified: trunk/python-ogre/code_generators/caelum/generate_code.py
===================================================================
--- trunk/python-ogre/code_generators/caelum/generate_code.py 2007-12-09 09:24:43 UTC (rev 498)
+++ trunk/python-ogre/code_generators/caelum/generate_code.py 2007-12-16 14:20:20 UTC (rev 499)
@@ -83,6 +83,7 @@
main_ns = global_ns
# Py++ doesn't know that this should be noncopyable so we set it here
main_ns.class_('CaelumSystem').noncopyable = True
+ main_ns.class_('LayeredClouds').noncopyable = True
############################################################
##
Added: trunk/python-ogre/makeall.py
===================================================================
--- trunk/python-ogre/makeall.py (rev 0)
+++ trunk/python-ogre/makeall.py 2007-12-16 14:20:20 UTC (rev 499)
@@ -0,0 +1,15 @@
+import subprocess
+import environment
+
+default_projects = []
+for name,cls in environment.projects.items():
+ if cls.active:
+ process = subprocess.Popen (["scons", "PROJECTS="+name], shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ print "Processing:", name,
+ out,err = process.communicate()
+ returncode = process.returncode
+ if returncode != 0:
+ print "ERROR:",returncode, " ", out, err
+ else:
+ print "OK"
+
Added: trunk/python-ogre/scripts_V2/BuildModule.py
===================================================================
--- trunk/python-ogre/scripts_V2/BuildModule.py (rev 0)
+++ trunk/python-ogre/scripts_V2/BuildModule.py 2007-12-16 14:20:20 UTC (rev 499)
@@ -0,0 +1,139 @@
+#
+# BuildModule will build a Python-Ogre module.
+#
+
+## Curent
+
+from optparse import OptionParser
+import subprocess
+import environment
+import logging
+import sys
+import types
+import os
+
+logger = None
+
+def setupLogging ():
+ # set up logging to file
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
+ datefmt='%m-%d %H:%M',
+ filename='log.out',
+ filemode='w')
+ # define a Handler which writes INFO messages or higher to the sys.stderr
+ console = logging.StreamHandler()
+ console.setLevel(logging.INFO)
+ # set a format which is simpler for console use
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ # tell the handler to use this format
+ console.setFormatter(formatter)
+ # add the handler to the root logger
+ logging.getLogger('').addHandler(console)
+
+
+def getClassList ():
+ """ create a dictionary of classes from the enfironment modules
+ """
+ dict = {}
+ for c in dir(environment):
+ var = environment.__dict__[c]
+ if isinstance ( var, types.ClassType ) : ## OK so we know it's a class
+# logger.debug ( "getClassList: Checking %s" % c )
+ if hasattr(var, 'active') and hasattr(var, 'pythonModule'): # and it looks like one we can about
+# logger.debug ( "getClassList: it's one of ours")
+ dict[c] = var
+ return dict
+
+def exit( ExitMessage ):
+ logger.error( ExitMessage )
+ sys.exit( -1 )
+
+
+## This stuff has to be in my spawing sub process
+# # export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PREFIX/lib/pkgconfig
+# # export LD_LIBRARY_PATH=$PREFIX/lib
+# # export CFLAGS="-I$PREFIX/include -L$PREFIX/lib"
+# # export CXXFLAGS=$CFLAGS
+# # export LDFLAGS="-Wl,-rpath='\$\$ORIGIN/../../lib' -Wl,-rpath='\$\$ORIGIN' -Wl,-z,origin"
+# # export PATH=$PREFIX/bin:$PATH
+# # export PYTHONPATH=$PREFIX/lib/python$PYTHONVERSION/site-packages
+
+
+def spawnTask ( task, cwdin = '' ):
+ """Execute a command line task and manage the return code etc
+ """
+ PREFIX = environment.PREFIX
+ PATH = os.environ["PATH"]
+ env = os.environ
+ env["PKG_CONFIG_PATH"]=PREFIX+"/lib/pkgconfig"
+ env["LD_LIBRARY_PATH"]=PREFIX+"/lib"
+ env["CFLAGS"]="\"-I"+PREFIX+"/include -L"+PREFIX+"/lib\""
+ env["CXXFLAGS"]="\"-I"+PREFIX+"/include -L"+PREFIX+"/lib\""
+ env["LDFLAGS"]="\"-Wl,-rpath='\$\$ORIGIN/../../lib' -Wl,-rpath='\$\$ORIGIN' -Wl,-z,origin\""
+ env["PATH"]=PREFIX+"/bin:" + PATH
+ env["PYTHONPATH"]=PREFIX+"/lib/python25/site-packages"
+
+
+ logger.debug ( "Spawning '%s' in '%s' " % (task,cwdin) )
+ process = subprocess.Popen (task, shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd = cwdin, env=env)
+ out,err = process.communicate()
+ returncode = process.returncode
+ if returncode != 0:
+ logger.warning ( "Task Failed" )
+ logger.debug ( out )
+ logger.debug ( err )
+ return returncode
+
+def retrieveSource ( module ):
+ """ Here's we we retrieve the necessary source files
+ """
+ for cmd,args,cwd in module.source:
+ l...
[truncated message content] |