[Python-ogre-commit] SF.net SVN: python-ogre: [499] trunk/python-ogre
Brought to you by:
andy_miller,
roman_yakovenko
From: <and...@us...> - 2007-12-16 14:20:21
|
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] |