mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-09 18:40:14 +00:00
Merge branch 'master' into sdl_input
This commit is contained in:
commit
6449f68d61
@ -37,8 +37,8 @@ option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
|||||||
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF)
|
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF)
|
||||||
|
|
||||||
# Sound source selection
|
# Sound source selection
|
||||||
option(USE_FFMPEG "use ffmpeg for sound" OFF)
|
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
||||||
option(USE_AUDIERE "use audiere for sound" OFF)
|
option(USE_AUDIERE "use audiere for sound" ON)
|
||||||
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
||||||
|
|
||||||
# OS X deployment
|
# OS X deployment
|
||||||
@ -137,30 +137,54 @@ set(OPENMW_LIBS ${OENGINE_ALL})
|
|||||||
set(OPENMW_LIBS_HEADER)
|
set(OPENMW_LIBS_HEADER)
|
||||||
|
|
||||||
# Sound setup
|
# Sound setup
|
||||||
|
set(GOT_SOUND_INPUT 0)
|
||||||
set(SOUND_INPUT_INCLUDES "")
|
set(SOUND_INPUT_INCLUDES "")
|
||||||
set(SOUND_INPUT_LIBRARY "")
|
set(SOUND_INPUT_LIBRARY "")
|
||||||
set(SOUND_DEFINE "")
|
set(SOUND_DEFINE "")
|
||||||
if (USE_FFMPEG)
|
if (USE_FFMPEG)
|
||||||
find_package(FFMPEG REQUIRED)
|
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIR})
|
find_package(FFmpeg)
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES})
|
if (FFMPEG_FOUND)
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
|
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIRS})
|
||||||
|
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
||||||
|
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
|
||||||
|
set(GOT_SOUND_INPUT 1)
|
||||||
|
endif (FFMPEG_FOUND)
|
||||||
endif (USE_FFMPEG)
|
endif (USE_FFMPEG)
|
||||||
|
|
||||||
if (USE_AUDIERE)
|
if (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
||||||
find_package(Audiere REQUIRED)
|
find_package(Audiere)
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
|
if (AUDIERE_FOUND)
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
|
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
|
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
|
||||||
endif (USE_AUDIERE)
|
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
|
||||||
|
set(GOT_SOUND_INPUT 1)
|
||||||
|
endif (AUDIERE_FOUND)
|
||||||
|
endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
||||||
|
|
||||||
if (USE_MPG123)
|
if (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
||||||
find_package(MPG123 REQUIRED)
|
find_package(MPG123 REQUIRED)
|
||||||
find_package(SNDFILE REQUIRED)
|
find_package(SNDFILE REQUIRED)
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
if (MPG123_FOUND AND SNDFILE_FOUND)
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
|
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
||||||
endif (USE_MPG123)
|
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
|
||||||
|
set(GOT_SOUND_INPUT 1)
|
||||||
|
endif (MPG123_FOUND AND SNDFILE_FOUND)
|
||||||
|
endif (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
||||||
|
|
||||||
|
if (NOT GOT_SOUND_INPUT)
|
||||||
|
message(WARNING "--------------------")
|
||||||
|
message(WARNING "Failed to find any sound input packages")
|
||||||
|
message(WARNING "--------------------")
|
||||||
|
endif (NOT GOT_SOUND_INPUT)
|
||||||
|
|
||||||
|
if (NOT FFMPEG_FOUND)
|
||||||
|
message(WARNING "--------------------")
|
||||||
|
message(WARNING "FFmpeg not found, video playback will be disabled")
|
||||||
|
message(WARNING "--------------------")
|
||||||
|
endif (NOT FFMPEG_FOUND)
|
||||||
|
|
||||||
|
|
||||||
# Platform specific
|
# Platform specific
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
|||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
||||||
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
|
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
|
||||||
compositors characterpreview externalrendering globalmap
|
compositors characterpreview externalrendering globalmap videoplayer
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -128,12 +128,6 @@ float MWBase::Environment::getFrameDuration() const
|
|||||||
|
|
||||||
void MWBase::Environment::cleanup()
|
void MWBase::Environment::cleanup()
|
||||||
{
|
{
|
||||||
delete mInputManager;
|
|
||||||
mInputManager = 0;
|
|
||||||
|
|
||||||
delete mSoundManager;
|
|
||||||
mSoundManager = 0;
|
|
||||||
|
|
||||||
delete mMechanicsManager;
|
delete mMechanicsManager;
|
||||||
mMechanicsManager = 0;
|
mMechanicsManager = 0;
|
||||||
|
|
||||||
@ -146,11 +140,17 @@ void MWBase::Environment::cleanup()
|
|||||||
delete mScriptManager;
|
delete mScriptManager;
|
||||||
mScriptManager = 0;
|
mScriptManager = 0;
|
||||||
|
|
||||||
|
delete mWorld;
|
||||||
|
mWorld = 0;
|
||||||
|
|
||||||
|
delete mSoundManager;
|
||||||
|
mSoundManager = 0;
|
||||||
|
|
||||||
delete mWindowManager;
|
delete mWindowManager;
|
||||||
mWindowManager = 0;
|
mWindowManager = 0;
|
||||||
|
|
||||||
delete mWorld;
|
delete mInputManager;
|
||||||
mWorld = 0;
|
mInputManager = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWBase::Environment& MWBase::Environment::get()
|
const MWBase::Environment& MWBase::Environment::get()
|
||||||
|
@ -22,6 +22,8 @@ namespace MWWorld
|
|||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound;
|
class Sound;
|
||||||
|
class Sound_Decoder;
|
||||||
|
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
@ -32,7 +34,7 @@ namespace MWBase
|
|||||||
class SoundManager
|
class SoundManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/* These must all fit together */
|
||||||
enum PlayMode {
|
enum PlayMode {
|
||||||
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
|
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
|
||||||
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
|
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
|
||||||
@ -41,6 +43,13 @@ namespace MWBase
|
|||||||
* but do not keep it updated (the sound will not move with
|
* but do not keep it updated (the sound will not move with
|
||||||
* the object and will not stop when the object is deleted. */
|
* the object and will not stop when the object is deleted. */
|
||||||
};
|
};
|
||||||
|
enum PlayType {
|
||||||
|
Play_TypeSfx = 1<<3, /* Normal SFX sound */
|
||||||
|
Play_TypeVoice = 1<<4, /* Voice sound */
|
||||||
|
Play_TypeMusic = 1<<5, /* Music track */
|
||||||
|
Play_TypeMovie = 1<<6, /* Movie audio track */
|
||||||
|
Play_TypeMask = Play_TypeSfx|Play_TypeVoice|Play_TypeMusic|Play_TypeMovie
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -89,12 +98,15 @@ namespace MWBase
|
|||||||
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()) = 0;
|
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()) = 0;
|
||||||
///< Stop an actor speaking
|
///< Stop an actor speaking
|
||||||
|
|
||||||
|
virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0;
|
||||||
|
///< Play a 2D audio track, using a custom decoder
|
||||||
|
|
||||||
virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch,
|
virtual SoundPtr playSound(const std::string& soundId, float volume, float pitch,
|
||||||
int mode=Play_Normal) = 0;
|
PlayMode mode=Play_Normal) = 0;
|
||||||
///< Play a sound, independently of 3D-position
|
///< Play a sound, independently of 3D-position
|
||||||
|
|
||||||
virtual SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
virtual SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
||||||
float volume, float pitch, int mode=Play_Normal) = 0;
|
float volume, float pitch, PlayMode mode=Play_Normal) = 0;
|
||||||
///< Play a sound from an object
|
///< Play a sound from an object
|
||||||
|
|
||||||
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId) = 0;
|
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId) = 0;
|
||||||
@ -112,15 +124,16 @@ namespace MWBase
|
|||||||
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0;
|
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0;
|
||||||
///< Is the given sound currently playing on the given object?
|
///< Is the given sound currently playing on the given object?
|
||||||
|
|
||||||
|
virtual void pauseSounds(int types=Play_TypeMask) = 0;
|
||||||
|
///< Pauses all currently playing sounds, including music.
|
||||||
|
|
||||||
|
virtual void resumeSounds(int types=Play_TypeMask) = 0;
|
||||||
|
///< Resumes all previously paused sounds.
|
||||||
|
|
||||||
virtual void update(float duration) = 0;
|
virtual void update(float duration) = 0;
|
||||||
|
|
||||||
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0;
|
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int operator|(SoundManager::PlayMode a, SoundManager::PlayMode b)
|
|
||||||
{ return static_cast<int> (a) | static_cast<int> (b); }
|
|
||||||
inline int operator&(SoundManager::PlayMode a, SoundManager::PlayMode b)
|
|
||||||
{ return static_cast<int> (a) & static_cast<int> (b); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -306,6 +306,11 @@ namespace MWBase
|
|||||||
/// 1 - only waiting \n
|
/// 1 - only waiting \n
|
||||||
/// 2 - player is underwater \n
|
/// 2 - player is underwater \n
|
||||||
/// 3 - enemies are nearby (not implemented)
|
/// 3 - enemies are nearby (not implemented)
|
||||||
|
|
||||||
|
|
||||||
|
/// \todo this does not belong here
|
||||||
|
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
||||||
|
virtual void stopVideo() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,9 @@ namespace MWGui
|
|||||||
GM_Loading,
|
GM_Loading,
|
||||||
GM_LoadingWallpaper,
|
GM_LoadingWallpaper,
|
||||||
|
|
||||||
GM_QuickKeysMenu
|
GM_QuickKeysMenu,
|
||||||
|
|
||||||
|
GM_Video
|
||||||
};
|
};
|
||||||
|
|
||||||
// Windows shown in inventory mode
|
// Windows shown in inventory mode
|
||||||
|
@ -230,6 +230,8 @@ WindowManager::~WindowManager()
|
|||||||
delete mSpellCreationDialog;
|
delete mSpellCreationDialog;
|
||||||
delete mEnchantingDialog;
|
delete mEnchantingDialog;
|
||||||
delete mTrainingWindow;
|
delete mTrainingWindow;
|
||||||
|
delete mCountDialog;
|
||||||
|
delete mQuickKeysMenu;
|
||||||
|
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
|
||||||
@ -407,6 +409,10 @@ void WindowManager::updateVisible()
|
|||||||
case GM_Loading:
|
case GM_Loading:
|
||||||
MyGUI::PointerManager::getInstance().setVisible(false);
|
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||||
break;
|
break;
|
||||||
|
case GM_Video:
|
||||||
|
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||||
|
mHud->setVisible(false);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// Unsupported mode, switch back to game
|
// Unsupported mode, switch back to game
|
||||||
break;
|
break;
|
||||||
|
@ -514,6 +514,8 @@ namespace MWInput
|
|||||||
{
|
{
|
||||||
if (mWindows.isGuiMode () && (mWindows.getMode () == MWGui::GM_MainMenu || mWindows.getMode () == MWGui::GM_Settings))
|
if (mWindows.isGuiMode () && (mWindows.getMode () == MWGui::GM_MainMenu || mWindows.getMode () == MWGui::GM_Settings))
|
||||||
mWindows.popGuiMode();
|
mWindows.popGuiMode();
|
||||||
|
else if (mWindows.isGuiMode () && mWindows.getMode () == MWGui::GM_Video)
|
||||||
|
MWBase::Environment::get().getWorld ()->stopVideo ();
|
||||||
else
|
else
|
||||||
mWindows.pushGuiMode (MWGui::GM_MainMenu);
|
mWindows.pushGuiMode (MWGui::GM_MainMenu);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
|
|
||||||
// These are the Morrowind.ini defaults
|
/// \todo Replace these, once fallback values from the ini file are available.
|
||||||
float Objects::lightLinearValue = 3;
|
float Objects::lightLinearValue = 3;
|
||||||
float Objects::lightLinearRadiusMult = 1;
|
float Objects::lightLinearRadiusMult = 1;
|
||||||
|
|
||||||
@ -31,7 +31,6 @@ int Objects::uniqueID = 0;
|
|||||||
|
|
||||||
void Objects::clearSceneNode (Ogre::SceneNode *node)
|
void Objects::clearSceneNode (Ogre::SceneNode *node)
|
||||||
{
|
{
|
||||||
/// \todo This should probably be moved into OpenEngine at some point.
|
|
||||||
for (int i=node->numAttachedObjects()-1; i>=0; --i)
|
for (int i=node->numAttachedObjects()-1; i>=0; --i)
|
||||||
{
|
{
|
||||||
Ogre::MovableObject *object = node->getAttachedObject (i);
|
Ogre::MovableObject *object = node->getAttachedObject (i);
|
||||||
@ -235,8 +234,9 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
|
|||||||
else
|
else
|
||||||
info.type = LT_Normal;
|
info.type = LT_Normal;
|
||||||
|
|
||||||
// random starting phase for the animation
|
// randomize lights animations
|
||||||
info.time = Ogre::Math::RangeRandom(0, 2 * Ogre::Math::PI);
|
info.time = Ogre::Math::RangeRandom(-500, +500);
|
||||||
|
info.phase = Ogre::Math::RangeRandom(-500, +500);
|
||||||
|
|
||||||
// adjust the lights depending if we're in an interior or exterior cell
|
// adjust the lights depending if we're in an interior or exterior cell
|
||||||
// quadratic means the light intensity falls off quite fast, resulting in a
|
// quadratic means the light intensity falls off quite fast, resulting in a
|
||||||
@ -373,6 +373,46 @@ void Objects::disableLights()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
namespace Pulse
|
||||||
|
{
|
||||||
|
static float amplitude (float phase)
|
||||||
|
{
|
||||||
|
return sin (phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Flicker
|
||||||
|
{
|
||||||
|
static const float fa = 0.785398f;
|
||||||
|
static const float fb = 1.17024f;
|
||||||
|
|
||||||
|
static const float tdo = 0.94f;
|
||||||
|
static const float tdm = 2.48f;
|
||||||
|
|
||||||
|
static const float f [3] = { 1.5708f, 4.18774f, 5.19934f };
|
||||||
|
static const float o [3] = { 0.804248f, 2.11115f, 3.46832f };
|
||||||
|
static const float m [3] = { 1.0f, 0.785f, 0.876f };
|
||||||
|
static const float s = 0.394f;
|
||||||
|
|
||||||
|
static const float phase_wavelength = 120.0f * 3.14159265359f / fa;
|
||||||
|
|
||||||
|
static float frequency (float x)
|
||||||
|
{
|
||||||
|
return tdo + tdm * sin (fa * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float amplitude (float x)
|
||||||
|
{
|
||||||
|
float v = 0.0f;
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
v += sin (fb*x*f[i] + o[1])*m[i];
|
||||||
|
return v * s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Objects::update(const float dt)
|
void Objects::update(const float dt)
|
||||||
{
|
{
|
||||||
std::vector<LightInfo>::iterator it = mLights.begin();
|
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||||
@ -382,77 +422,63 @@ void Objects::update(const float dt)
|
|||||||
{
|
{
|
||||||
Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name);
|
Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name);
|
||||||
|
|
||||||
// Light animation (pulse & flicker)
|
float brightness;
|
||||||
it->time += dt;
|
float cycle_time;
|
||||||
const float phase = std::fmod(static_cast<double> (it->time), static_cast<double>(32 * 2 * Ogre::Math::PI)) * 20;
|
float time_distortion;
|
||||||
float pulseConstant;
|
|
||||||
|
if ((it->type == LT_Pulse) && (it->type == LT_PulseSlow))
|
||||||
|
{
|
||||||
|
cycle_time = 2 * Ogre::Math::PI;
|
||||||
|
time_distortion = 20.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cycle_time = 500.0f;
|
||||||
|
it->phase = fmod (it->phase + dt, Flicker::phase_wavelength);
|
||||||
|
time_distortion = Flicker::frequency (it->phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
it->time += it->dir*dt*time_distortion;
|
||||||
|
if (it->dir > 0 && it->time > +cycle_time)
|
||||||
|
{
|
||||||
|
it->dir = -1.0f;
|
||||||
|
it->time = +2*cycle_time - it->time;
|
||||||
|
}
|
||||||
|
if (it->dir < 0 && it->time < -cycle_time)
|
||||||
|
{
|
||||||
|
it->dir = +1.0f;
|
||||||
|
it->time = -2*cycle_time - it->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const float fast = 4.0f/1.0f;
|
||||||
|
static const float slow = 1.0f/1.0f;
|
||||||
|
|
||||||
// These formulas are just guesswork, but they work pretty well
|
// These formulas are just guesswork, but they work pretty well
|
||||||
if (it->type == LT_Normal)
|
if (it->type == LT_Normal)
|
||||||
{
|
{
|
||||||
// Less than 1/255 light modifier for a constant light:
|
// Less than 1/255 light modifier for a constant light:
|
||||||
pulseConstant = (const float)(1.0 + sin(phase) / 255.0 );
|
brightness = (const float)(1.0 + Flicker::amplitude(it->time*slow) / 255.0 );
|
||||||
}
|
}
|
||||||
else if (it->type == LT_Flicker)
|
else if (it->type == LT_Flicker)
|
||||||
{
|
{
|
||||||
// Let's do a 50% -> 100% sine wave pulse over 1 second:
|
brightness = (const float)(0.75 + Flicker::amplitude(it->time*fast) * 0.25);
|
||||||
// This is 75% +/- 25%
|
|
||||||
pulseConstant = (const float)(0.75 + sin(phase) * 0.25);
|
|
||||||
|
|
||||||
// Then add a 25% flicker variation:
|
|
||||||
it->resetTime -= dt;
|
|
||||||
if (it->resetTime < 0)
|
|
||||||
{
|
|
||||||
it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
|
|
||||||
it->resetTime = 0.5;
|
|
||||||
}
|
|
||||||
if (it->resetTime > 0.25)
|
|
||||||
{
|
|
||||||
pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime * 2.0f) + pulseConstant * it->resetTime * 2.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime * 2.0f) + pulseConstant * (1-it->resetTime * 2.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (it->type == LT_FlickerSlow)
|
else if (it->type == LT_FlickerSlow)
|
||||||
{
|
{
|
||||||
// Let's do a 50% -> 100% sine wave pulse over 1 second:
|
brightness = (const float)(0.75 + Flicker::amplitude(it->time*slow) * 0.25);
|
||||||
// This is 75% +/- 25%
|
|
||||||
pulseConstant = (const float)(0.75 + sin(phase / 4.0) * 0.25);
|
|
||||||
|
|
||||||
// Then add a 25% flicker variation:
|
|
||||||
it->resetTime -= dt;
|
|
||||||
if (it->resetTime < 0)
|
|
||||||
{
|
|
||||||
it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
|
|
||||||
it->resetTime = 0.5;
|
|
||||||
}
|
|
||||||
if (it->resetTime > 0.5)
|
|
||||||
{
|
|
||||||
pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime) + pulseConstant * it->resetTime;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime) + pulseConstant * (1-it->resetTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (it->type == LT_Pulse)
|
else if (it->type == LT_Pulse)
|
||||||
{
|
{
|
||||||
// Let's do a 75% -> 125% sine wave pulse over 1 second:
|
brightness = (const float)(1.0 + Pulse::amplitude (it->time*fast) * 0.25);
|
||||||
// This is 100% +/- 25%
|
|
||||||
pulseConstant = (const float)(1.0 + sin(phase) * 0.25);
|
|
||||||
}
|
}
|
||||||
else if (it->type == LT_PulseSlow)
|
else if (it->type == LT_PulseSlow)
|
||||||
{
|
{
|
||||||
// Let's do a 75% -> 125% sine wave pulse over 1 second:
|
brightness = (const float)(1.0 + Pulse::amplitude (it->time*slow) * 0.25);
|
||||||
// This is 100% +/- 25%
|
|
||||||
pulseConstant = (const float)(1.0 + sin(phase / 4.0) * 0.25);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assert(0 && "Invalid light type");
|
assert(0 && "Invalid light type");
|
||||||
|
|
||||||
light->setDiffuseColour( it->colour * pulseConstant );
|
light->setDiffuseColour(it->colour * brightness);
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@ -476,8 +502,7 @@ void Objects::rebuildStaticGeometry()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void Objects::updateObjectCell(const MWWorld::Ptr &ptr)
|
||||||
Objects::updateObjectCell(const MWWorld::Ptr &ptr)
|
|
||||||
{
|
{
|
||||||
Ogre::SceneNode *node;
|
Ogre::SceneNode *node;
|
||||||
MWWorld::CellStore *newCell = ptr.getCell();
|
MWWorld::CellStore *newCell = ptr.getCell();
|
||||||
|
@ -34,16 +34,13 @@ struct LightInfo
|
|||||||
LightType type;
|
LightType type;
|
||||||
|
|
||||||
// Runtime variables
|
// Runtime variables
|
||||||
float flickerVariation; // 25% flicker variation, reset once every 0.5 seconds
|
float dir; // direction time is running...
|
||||||
float flickerSlowVariation; // 25% flicker variation, reset once every 1.0 seconds
|
float time; // current time
|
||||||
float resetTime;
|
float phase; // current phase
|
||||||
long double time;
|
|
||||||
|
|
||||||
|
|
||||||
LightInfo() :
|
LightInfo() :
|
||||||
flickerVariation(0), resetTime(0.5),
|
dir(1.0f), time(0.0f), phase (0.0f),
|
||||||
flickerSlowVariation(0), time(0), interior(true),
|
interior(true), type(LT_Normal), radius(1.0)
|
||||||
type(LT_Normal), radius(1.0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "npcanimation.hpp"
|
#include "npcanimation.hpp"
|
||||||
#include "externalrendering.hpp"
|
#include "externalrendering.hpp"
|
||||||
#include "globalmap.hpp"
|
#include "globalmap.hpp"
|
||||||
|
#include "videoplayer.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
@ -160,6 +161,9 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||||||
|
|
||||||
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
|
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
|
||||||
|
|
||||||
|
mVideoPlayer = new VideoPlayer(mRendering.getScene ());
|
||||||
|
mVideoPlayer->setResolution (Settings::Manager::getInt ("resolution x", "Video"), Settings::Manager::getInt ("resolution y", "Video"));
|
||||||
|
|
||||||
mSun = 0;
|
mSun = 0;
|
||||||
|
|
||||||
mDebugging = new Debugging(mMwRoot, engine);
|
mDebugging = new Debugging(mMwRoot, engine);
|
||||||
@ -181,7 +185,7 @@ RenderingManager::~RenderingManager ()
|
|||||||
delete mOcclusionQuery;
|
delete mOcclusionQuery;
|
||||||
delete mCompositors;
|
delete mCompositors;
|
||||||
delete mWater;
|
delete mWater;
|
||||||
|
delete mVideoPlayer;
|
||||||
delete mFactory;
|
delete mFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +336,8 @@ void RenderingManager::update (float duration, bool paused)
|
|||||||
}
|
}
|
||||||
mOcclusionQuery->update(duration);
|
mOcclusionQuery->update(duration);
|
||||||
|
|
||||||
|
mVideoPlayer->update ();
|
||||||
|
|
||||||
mRendering.update(duration);
|
mRendering.update(duration);
|
||||||
|
|
||||||
if(paused)
|
if(paused)
|
||||||
@ -838,6 +844,8 @@ void RenderingManager::windowResized(Ogre::RenderWindow* rw)
|
|||||||
mCompositors->recreate();
|
mCompositors->recreate();
|
||||||
mWater->assignTextures();
|
mWater->assignTextures();
|
||||||
|
|
||||||
|
mVideoPlayer->setResolution (rw->getWidth(), rw->getHeight());
|
||||||
|
|
||||||
const Settings::CategorySettingVector& changed = Settings::Manager::apply();
|
const Settings::CategorySettingVector& changed = Settings::Manager::apply();
|
||||||
MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME
|
MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME
|
||||||
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME
|
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME
|
||||||
@ -921,4 +929,14 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
|
|||||||
rendering.setup (mRendering.getScene());
|
rendering.setup (mRendering.getScene());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::playVideo(const std::string& name, bool allowSkipping)
|
||||||
|
{
|
||||||
|
mVideoPlayer->playVideo ("video/" + name, allowSkipping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::stopVideo()
|
||||||
|
{
|
||||||
|
mVideoPlayer->stopVideo ();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -45,6 +45,7 @@ namespace MWRender
|
|||||||
class Compositors;
|
class Compositors;
|
||||||
class ExternalRendering;
|
class ExternalRendering;
|
||||||
class GlobalMap;
|
class GlobalMap;
|
||||||
|
class VideoPlayer;
|
||||||
|
|
||||||
class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
|
class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
|
||||||
|
|
||||||
@ -195,6 +196,9 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
|
|||||||
|
|
||||||
void setupExternalRendering (MWRender::ExternalRendering& rendering);
|
void setupExternalRendering (MWRender::ExternalRendering& rendering);
|
||||||
|
|
||||||
|
void playVideo(const std::string& name, bool allowSkipping);
|
||||||
|
void stopVideo();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void windowResized(Ogre::RenderWindow* rw);
|
virtual void windowResized(Ogre::RenderWindow* rw);
|
||||||
virtual void windowClosed(Ogre::RenderWindow* rw);
|
virtual void windowClosed(Ogre::RenderWindow* rw);
|
||||||
@ -248,6 +252,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
|
|||||||
MWRender::Shadows* mShadows;
|
MWRender::Shadows* mShadows;
|
||||||
|
|
||||||
MWRender::Compositors* mCompositors;
|
MWRender::Compositors* mCompositors;
|
||||||
|
|
||||||
|
VideoPlayer* mVideoPlayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
1151
apps/openmw/mwrender/videoplayer.cpp
Normal file
1151
apps/openmw/mwrender/videoplayer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
52
apps/openmw/mwrender/videoplayer.hpp
Normal file
52
apps/openmw/mwrender/videoplayer.hpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef VIDEOPLAYER_H
|
||||||
|
#define VIDEOPLAYER_H
|
||||||
|
|
||||||
|
#include <OgreMaterial.h>
|
||||||
|
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class SceneManager;
|
||||||
|
class SceneNode;
|
||||||
|
class Rectangle2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
struct VideoState;
|
||||||
|
|
||||||
|
class VideoPlayer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VideoPlayer(Ogre::SceneManager* sceneMgr);
|
||||||
|
~VideoPlayer();
|
||||||
|
|
||||||
|
void playVideo (const std::string& resourceName, bool allowSkipping);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
void close();
|
||||||
|
void stopVideo();
|
||||||
|
|
||||||
|
bool isPlaying();
|
||||||
|
|
||||||
|
void setResolution (int w, int h) { mWidth = w; mHeight = h; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
VideoState* mState;
|
||||||
|
|
||||||
|
bool mAllowSkipping;
|
||||||
|
|
||||||
|
Ogre::SceneManager* mSceneMgr;
|
||||||
|
Ogre::MaterialPtr mVideoMaterial;
|
||||||
|
Ogre::Rectangle2D* mRectangle;
|
||||||
|
Ogre::Rectangle2D* mBackgroundRectangle;
|
||||||
|
Ogre::SceneNode* mNode;
|
||||||
|
Ogre::SceneNode* mBackgroundNode;
|
||||||
|
|
||||||
|
int mWidth;
|
||||||
|
int mHeight;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -301,10 +301,14 @@ op 0x20001ea: LowerRank
|
|||||||
op 0x20001eb: LowerRank, explicit
|
op 0x20001eb: LowerRank, explicit
|
||||||
op 0x20001ec: GetPCCrimeLevel
|
op 0x20001ec: GetPCCrimeLevel
|
||||||
op 0x20001ed: SetPCCrimeLevel
|
op 0x20001ed: SetPCCrimeLevel
|
||||||
op 0x20001ee: SetPCCrimeLevel
|
op 0x20001ee: ModPCCrimeLevel
|
||||||
op 0x20001ef: GetCurrentAIPackage
|
op 0x20001ef: GetCurrentAIPackage
|
||||||
op 0x20001f0: GetCurrentAIPackage, explicit reference
|
op 0x20001f0: GetCurrentAIPackage, explicit reference
|
||||||
op 0x20001f1: GetDetected
|
op 0x20001f1: GetDetected
|
||||||
op 0x20001f2: GetDetected, explicit reference
|
op 0x20001f2: GetDetected, explicit reference
|
||||||
|
op 0x20001f3: AddSoulGem
|
||||||
opcodes 0x20001f3-0x3ffffff unused
|
op 0x20001f4: AddSoulGem, explicit reference
|
||||||
|
op 0x20001f5: RemoveSoulGem
|
||||||
|
op 0x20001f6: RemoveSoulGem, explicit reference
|
||||||
|
op 0x20001f7: PlayBink
|
||||||
|
opcodes 0x20001f8-0x3ffffff unused
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/manualref.hpp"
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
@ -25,6 +27,22 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
class OpPlayBink : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
bool allowSkipping = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld ()->playVideo (name, allowSkipping);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class OpGetPcSleep : public Interpreter::Opcode0
|
class OpGetPcSleep : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -255,7 +273,7 @@ namespace MWScript
|
|||||||
static bool sActivate;
|
static bool sActivate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void execute(Interpreter::Runtime &runtime)
|
virtual void execute(Interpreter::Runtime &runtime)
|
||||||
{
|
{
|
||||||
InterpreterContext& context =
|
InterpreterContext& context =
|
||||||
@ -306,6 +324,65 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpAddSoulGem : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string creature = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
std::string gem = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
store.get<ESM::Creature>().find(creature); // This line throws an exception if it can't find the creature
|
||||||
|
|
||||||
|
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), gem);
|
||||||
|
|
||||||
|
ref.getPtr().getRefData().setCount (1);
|
||||||
|
|
||||||
|
ref.getPtr().getCellRef().mSoul = creature;
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr());
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpRemoveSoulGem : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||||
|
|
||||||
|
|
||||||
|
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
|
||||||
|
{
|
||||||
|
if (iter->getRefData().getCount() <= 1)
|
||||||
|
iter->getRefData().setCount (0);
|
||||||
|
else
|
||||||
|
iter->getRefData().setCount (iter->getRefData().getCount() - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class R>
|
template <class R>
|
||||||
class OpGetAttacked : public Interpreter::Opcode0
|
class OpGetAttacked : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
@ -414,6 +491,10 @@ namespace MWScript
|
|||||||
const int opcodeGetLockedExplicit = 0x20001c8;
|
const int opcodeGetLockedExplicit = 0x20001c8;
|
||||||
const int opcodeGetEffect = 0x20001cf;
|
const int opcodeGetEffect = 0x20001cf;
|
||||||
const int opcodeGetEffectExplicit = 0x20001d0;
|
const int opcodeGetEffectExplicit = 0x20001d0;
|
||||||
|
const int opcodeAddSoulGem = 0x20001f3;
|
||||||
|
const int opcodeAddSoulGemExplicit = 0x20001f4;
|
||||||
|
const int opcodeRemoveSoulGem = 0x20001f5;
|
||||||
|
const int opcodeRemoveSoulGemExplicit = 0x20001f6;
|
||||||
const int opcodeGetAttacked = 0x20001d3;
|
const int opcodeGetAttacked = 0x20001d3;
|
||||||
const int opcodeGetAttackedExplicit = 0x20001d4;
|
const int opcodeGetAttackedExplicit = 0x20001d4;
|
||||||
const int opcodeGetWeaponDrawn = 0x20001d7;
|
const int opcodeGetWeaponDrawn = 0x20001d7;
|
||||||
@ -425,6 +506,8 @@ namespace MWScript
|
|||||||
const int opcodeSetDeleteExplicit = 0x20001e6;
|
const int opcodeSetDeleteExplicit = 0x20001e6;
|
||||||
const int opcodeGetSquareRoot = 0x20001e7;
|
const int opcodeGetSquareRoot = 0x20001e7;
|
||||||
|
|
||||||
|
const int opcodePlayBink = 0x20001f7;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
extensions.registerFunction ("xbox", 'l', "", opcodeXBox);
|
extensions.registerFunction ("xbox", 'l', "", opcodeXBox);
|
||||||
@ -450,8 +533,11 @@ namespace MWScript
|
|||||||
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
|
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
|
||||||
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
|
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
|
||||||
extensions.registerInstruction ("wakeuppc", "", opcodeWakeUpPc);
|
extensions.registerInstruction ("wakeuppc", "", opcodeWakeUpPc);
|
||||||
|
extensions.registerInstruction ("playbink", "Sl", opcodePlayBink);
|
||||||
extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
|
extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
|
||||||
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
|
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
|
||||||
|
extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
|
||||||
|
extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
|
||||||
extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
|
extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
|
||||||
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
|
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
|
||||||
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
|
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
|
||||||
@ -481,10 +567,15 @@ namespace MWScript
|
|||||||
interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
|
interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
|
||||||
interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
|
interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
|
||||||
interpreter.installSegment5 (opcodeWakeUpPc, new OpWakeUpPc);
|
interpreter.installSegment5 (opcodeWakeUpPc, new OpWakeUpPc);
|
||||||
|
interpreter.installSegment5 (opcodePlayBink, new OpPlayBink);
|
||||||
interpreter.installSegment5 (opcodeGetLocked, new OpGetLocked<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetLocked, new OpGetLocked<ImplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetLockedExplicit, new OpGetLocked<ExplicitRef>);
|
interpreter.installSegment5 (opcodeGetLockedExplicit, new OpGetLocked<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetEffect, new OpGetEffect<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetEffect, new OpGetEffect<ImplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
|
interpreter.installSegment5 (opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeAddSoulGem, new OpAddSoulGem<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
||||||
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
||||||
|
@ -118,7 +118,8 @@ namespace MWScript
|
|||||||
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWBase::SoundManager::Play_Loop : 0);
|
MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWBase::SoundManager::Play_Loop :
|
||||||
|
MWBase::SoundManager::Play_Normal);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,7 +145,8 @@ namespace MWScript
|
|||||||
Interpreter::Type_Float pitch = runtime[0].mFloat;
|
Interpreter::Type_Float pitch = runtime[0].mFloat;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, volume, pitch, mLoop ? MWBase::SoundManager::Play_Loop : 0);
|
MWBase::Environment::get().getSoundManager()->playSound3D (ptr, sound, volume, pitch, mLoop ? MWBase::SoundManager::Play_Loop :
|
||||||
|
MWBase::SoundManager::Play_Normal);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,9 @@ public:
|
|||||||
: mStream(stream), refs(1)
|
: mStream(stream), refs(1)
|
||||||
{ }
|
{ }
|
||||||
virtual ~OgreFile() { }
|
virtual ~OgreFile() { }
|
||||||
|
|
||||||
|
Ogre::String getName()
|
||||||
|
{ return mStream->getName(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +63,7 @@ void Audiere_Decoder::open(const std::string &fname)
|
|||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
audiere::FilePtr file(new OgreFile(mResourceMgr.openResource(fname)));
|
mSoundFile = audiere::FilePtr(new OgreFile(mResourceMgr.openResource(fname)));
|
||||||
mSoundSource = audiere::OpenSampleSource(file);
|
mSoundSource = audiere::OpenSampleSource(file);
|
||||||
|
|
||||||
int channels, srate;
|
int channels, srate;
|
||||||
@ -86,9 +89,15 @@ void Audiere_Decoder::open(const std::string &fname)
|
|||||||
|
|
||||||
void Audiere_Decoder::close()
|
void Audiere_Decoder::close()
|
||||||
{
|
{
|
||||||
|
mSoundFile = NULL;
|
||||||
mSoundSource = NULL;
|
mSoundSource = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Audiere_Decoder::getName()
|
||||||
|
{
|
||||||
|
return mSoundFile->getName();
|
||||||
|
}
|
||||||
|
|
||||||
void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
{
|
{
|
||||||
*samplerate = mSampleRate;
|
*samplerate = mSampleRate;
|
||||||
@ -108,6 +117,11 @@ void Audiere_Decoder::rewind()
|
|||||||
mSoundSource->reset();
|
mSoundSource->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Audiere_Decoder::getSampleOffset()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Audiere_Decoder::Audiere_Decoder()
|
Audiere_Decoder::Audiere_Decoder()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
class Audiere_Decoder : public Sound_Decoder
|
class Audiere_Decoder : public Sound_Decoder
|
||||||
{
|
{
|
||||||
|
audiere::FilePtr mSoundFile;
|
||||||
audiere::SampleSourcePtr mSoundSource;
|
audiere::SampleSourcePtr mSoundSource;
|
||||||
int mSampleRate;
|
int mSampleRate;
|
||||||
SampleType mSampleType;
|
SampleType mSampleType;
|
||||||
@ -20,10 +21,12 @@ namespace MWSound
|
|||||||
virtual void open(const std::string &fname);
|
virtual void open(const std::string &fname);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
|
virtual std::string getName();
|
||||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||||
|
|
||||||
virtual size_t read(char *buffer, size_t bytes);
|
virtual size_t read(char *buffer, size_t bytes);
|
||||||
virtual void rewind();
|
virtual void rewind();
|
||||||
|
virtual size_t getSampleOffset();
|
||||||
|
|
||||||
Audiere_Decoder& operator=(const Audiere_Decoder &rhs);
|
Audiere_Decoder& operator=(const Audiere_Decoder &rhs);
|
||||||
Audiere_Decoder(const Audiere_Decoder &rhs);
|
Audiere_Decoder(const Audiere_Decoder &rhs);
|
||||||
|
@ -15,28 +15,6 @@ static void fail(const std::string &msg)
|
|||||||
{ throw std::runtime_error("FFmpeg exception: "+msg); }
|
{ throw std::runtime_error("FFmpeg exception: "+msg); }
|
||||||
|
|
||||||
|
|
||||||
struct PacketList {
|
|
||||||
AVPacket pkt;
|
|
||||||
PacketList *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FFmpeg_Decoder::MyStream {
|
|
||||||
AVCodecContext *mCodecCtx;
|
|
||||||
int mStreamIdx;
|
|
||||||
|
|
||||||
PacketList *mPackets;
|
|
||||||
|
|
||||||
char *mDecodedData;
|
|
||||||
size_t mDecodedDataSize;
|
|
||||||
|
|
||||||
FFmpeg_Decoder *mParent;
|
|
||||||
|
|
||||||
void clearPackets();
|
|
||||||
void *getAVAudioData(size_t *length);
|
|
||||||
size_t readAVAudioData(void *data, size_t length);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size)
|
int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size)
|
||||||
{
|
{
|
||||||
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
|
||||||
@ -72,166 +50,84 @@ int64_t FFmpeg_Decoder::seek(void *user_data, int64_t offset, int whence)
|
|||||||
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
||||||
* correct stream. It won't buffer data for streams that the app doesn't have a
|
* correct stream. It won't buffer data for streams that the app doesn't have a
|
||||||
* handle for. */
|
* handle for. */
|
||||||
bool FFmpeg_Decoder::getNextPacket(int streamidx)
|
bool FFmpeg_Decoder::getNextPacket()
|
||||||
{
|
{
|
||||||
PacketList *packet;
|
if(!mStream)
|
||||||
|
return false;
|
||||||
|
|
||||||
packet = (PacketList*)av_malloc(sizeof(*packet));
|
int stream_idx = mStream - mFormatCtx->streams;
|
||||||
packet->next = NULL;
|
while(av_read_frame(mFormatCtx, &mPacket) >= 0)
|
||||||
|
|
||||||
next_packet:
|
|
||||||
while(av_read_frame(mFormatCtx, &packet->pkt) >= 0)
|
|
||||||
{
|
{
|
||||||
std::vector<MyStream*>::iterator iter = mStreams.begin();
|
/* Check if the packet belongs to this stream */
|
||||||
|
if(stream_idx == mPacket.stream_index)
|
||||||
/* Check each stream the user has a handle for, looking for the one
|
|
||||||
* this packet belongs to */
|
|
||||||
while(iter != mStreams.end())
|
|
||||||
{
|
{
|
||||||
if((*iter)->mStreamIdx == packet->pkt.stream_index)
|
if((uint64_t)mPacket.pts != AV_NOPTS_VALUE)
|
||||||
{
|
mNextPts = av_q2d((*mStream)->time_base)*mPacket.pts;
|
||||||
PacketList **last;
|
return true;
|
||||||
|
|
||||||
last = &(*iter)->mPackets;
|
|
||||||
while(*last != NULL)
|
|
||||||
last = &(*last)->next;
|
|
||||||
|
|
||||||
*last = packet;
|
|
||||||
if((*iter)->mStreamIdx == streamidx)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
packet = (PacketList*)av_malloc(sizeof(*packet));
|
|
||||||
packet->next = NULL;
|
|
||||||
goto next_packet;
|
|
||||||
}
|
|
||||||
iter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the packet and look for another */
|
/* Free the packet and look for another */
|
||||||
av_free_packet(&packet->pkt);
|
av_free_packet(&mPacket);
|
||||||
}
|
}
|
||||||
av_free(packet);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::MyStream::clearPackets()
|
bool FFmpeg_Decoder::getAVAudioData()
|
||||||
{
|
{
|
||||||
while(mPackets)
|
int got_frame, len;
|
||||||
{
|
|
||||||
PacketList *self = mPackets;
|
|
||||||
mPackets = self->next;
|
|
||||||
|
|
||||||
av_free_packet(&self->pkt);
|
if((*mStream)->codec->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
av_free(self);
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *FFmpeg_Decoder::MyStream::getAVAudioData(size_t *length)
|
do {
|
||||||
{
|
if(mPacket.size == 0 && !getNextPacket())
|
||||||
int size;
|
return false;
|
||||||
int len;
|
|
||||||
|
|
||||||
if(length) *length = 0;
|
/* Decode some data, and check for errors */
|
||||||
if(mCodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
if((len=avcodec_decode_audio4((*mStream)->codec, mFrame, &got_frame, &mPacket)) < 0)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
mDecodedDataSize = 0;
|
|
||||||
|
|
||||||
next_packet:
|
|
||||||
if(!mPackets && !mParent->getNextPacket(mStreamIdx))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Decode some data, and check for errors */
|
|
||||||
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
|
||||||
while((len=avcodec_decode_audio3(mCodecCtx, (int16_t*)mDecodedData, &size,
|
|
||||||
&mPackets->pkt)) == 0)
|
|
||||||
{
|
|
||||||
PacketList *self;
|
|
||||||
|
|
||||||
if(size > 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Packet went unread and no data was given? Drop it and try the next,
|
|
||||||
* I guess... */
|
|
||||||
self = mPackets;
|
|
||||||
mPackets = self->next;
|
|
||||||
|
|
||||||
av_free_packet(&self->pkt);
|
|
||||||
av_free(self);
|
|
||||||
|
|
||||||
if(!mPackets)
|
|
||||||
goto next_packet;
|
|
||||||
|
|
||||||
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(len < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if(len < mPackets->pkt.size)
|
|
||||||
{
|
|
||||||
/* Move the unread data to the front and clear the end bits */
|
/* Move the unread data to the front and clear the end bits */
|
||||||
int remaining = mPackets->pkt.size - len;
|
int remaining = mPacket.size - len;
|
||||||
memmove(mPackets->pkt.data, &mPackets->pkt.data[len], remaining);
|
if(remaining <= 0)
|
||||||
memset(&mPackets->pkt.data[remaining], 0, mPackets->pkt.size - remaining);
|
av_free_packet(&mPacket);
|
||||||
mPackets->pkt.size -= len;
|
else
|
||||||
}
|
{
|
||||||
else
|
memmove(mPacket.data, &mPacket.data[len], remaining);
|
||||||
{
|
av_shrink_packet(&mPacket, remaining);
|
||||||
PacketList *self;
|
}
|
||||||
|
} while(got_frame == 0 || mFrame->nb_samples == 0);
|
||||||
|
mNextPts += (double)mFrame->nb_samples / (double)(*mStream)->codec->sample_rate;
|
||||||
|
|
||||||
self = mPackets;
|
return true;
|
||||||
mPackets = self->next;
|
|
||||||
|
|
||||||
av_free_packet(&self->pkt);
|
|
||||||
av_free(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(size == 0)
|
|
||||||
goto next_packet;
|
|
||||||
|
|
||||||
/* Set the output buffer size */
|
|
||||||
mDecodedDataSize = size;
|
|
||||||
if(length) *length = mDecodedDataSize;
|
|
||||||
|
|
||||||
return mDecodedData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length)
|
||||||
{
|
{
|
||||||
size_t dec = 0;
|
size_t dec = 0;
|
||||||
|
|
||||||
while(dec < length)
|
while(dec < length)
|
||||||
{
|
{
|
||||||
/* If there's no decoded data, find some */
|
/* If there's no decoded data, find some */
|
||||||
if(mDecodedDataSize == 0)
|
if(mFramePos >= mFrameSize)
|
||||||
{
|
{
|
||||||
if(getAVAudioData(NULL) == NULL)
|
if(!getAVAudioData())
|
||||||
break;
|
break;
|
||||||
|
mFramePos = 0;
|
||||||
|
mFrameSize = mFrame->nb_samples * (*mStream)->codec->channels *
|
||||||
|
av_get_bytes_per_sample((*mStream)->codec->sample_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mDecodedDataSize > 0)
|
/* Get the amount of bytes remaining to be written, and clamp to
|
||||||
{
|
* the amount of decoded data we have */
|
||||||
/* Get the amount of bytes remaining to be written, and clamp to
|
size_t rem = std::min<size_t>(length-dec, mFrameSize-mFramePos);
|
||||||
* the amount of decoded data we have */
|
|
||||||
size_t rem = length-dec;
|
|
||||||
if(rem > mDecodedDataSize)
|
|
||||||
rem = mDecodedDataSize;
|
|
||||||
|
|
||||||
/* Copy the data to the app's buffer and increment */
|
/* Copy the data to the app's buffer and increment */
|
||||||
if(data != NULL)
|
memcpy(data, mFrame->data[0]+mFramePos, rem);
|
||||||
{
|
data = (char*)data + rem;
|
||||||
memcpy(data, mDecodedData, rem);
|
dec += rem;
|
||||||
data = (char*)data + rem;
|
mFramePos += rem;
|
||||||
}
|
|
||||||
dec += rem;
|
|
||||||
|
|
||||||
/* If there's any decoded data left, move it to the front of the
|
|
||||||
* buffer for next time */
|
|
||||||
if(rem < mDecodedDataSize)
|
|
||||||
memmove(mDecodedData, &mDecodedData[rem], mDecodedDataSize - rem);
|
|
||||||
mDecodedDataSize -= rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the number of bytes we were able to get */
|
/* Return the number of bytes we were able to get */
|
||||||
@ -239,7 +135,6 @@ size_t FFmpeg_Decoder::MyStream::readAVAudioData(void *data, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FFmpeg_Decoder::open(const std::string &fname)
|
void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
@ -265,140 +160,155 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
|||||||
{
|
{
|
||||||
if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||||
{
|
{
|
||||||
std::auto_ptr<MyStream> stream(new MyStream);
|
mStream = &mFormatCtx->streams[j];
|
||||||
stream->mCodecCtx = mFormatCtx->streams[j]->codec;
|
|
||||||
stream->mStreamIdx = j;
|
|
||||||
stream->mPackets = NULL;
|
|
||||||
|
|
||||||
AVCodec *codec = avcodec_find_decoder(stream->mCodecCtx->codec_id);
|
|
||||||
if(!codec)
|
|
||||||
{
|
|
||||||
std::stringstream ss("No codec found for id ");
|
|
||||||
ss << stream->mCodecCtx->codec_id;
|
|
||||||
fail(ss.str());
|
|
||||||
}
|
|
||||||
if(avcodec_open(stream->mCodecCtx, codec) < 0)
|
|
||||||
fail("Failed to open audio codec " + std::string(codec->long_name));
|
|
||||||
|
|
||||||
stream->mDecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
|
||||||
stream->mDecodedDataSize = 0;
|
|
||||||
|
|
||||||
stream->mParent = this;
|
|
||||||
mStreams.push_back(stream.release());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mStreams.empty())
|
if(!mStream)
|
||||||
fail("No audio streams in "+fname);
|
fail("No audio streams in "+fname);
|
||||||
|
|
||||||
|
AVCodec *codec = avcodec_find_decoder((*mStream)->codec->codec_id);
|
||||||
|
if(!codec)
|
||||||
|
{
|
||||||
|
std::stringstream ss("No codec found for id ");
|
||||||
|
ss << (*mStream)->codec->codec_id;
|
||||||
|
fail(ss.str());
|
||||||
|
}
|
||||||
|
if(avcodec_open2((*mStream)->codec, codec, NULL) < 0)
|
||||||
|
fail("Failed to open audio codec " + std::string(codec->long_name));
|
||||||
|
|
||||||
|
mFrame = avcodec_alloc_frame();
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
av_close_input_file(mFormatCtx);
|
avformat_close_input(&mFormatCtx);
|
||||||
mFormatCtx = NULL;
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::close()
|
void FFmpeg_Decoder::close()
|
||||||
{
|
{
|
||||||
while(!mStreams.empty())
|
if(mStream)
|
||||||
{
|
avcodec_close((*mStream)->codec);
|
||||||
MyStream *stream = mStreams.front();
|
mStream = NULL;
|
||||||
|
|
||||||
stream->clearPackets();
|
av_free_packet(&mPacket);
|
||||||
avcodec_close(stream->mCodecCtx);
|
av_freep(&mFrame);
|
||||||
av_free(stream->mDecodedData);
|
|
||||||
delete stream;
|
|
||||||
|
|
||||||
mStreams.erase(mStreams.begin());
|
|
||||||
}
|
|
||||||
if(mFormatCtx)
|
if(mFormatCtx)
|
||||||
{
|
{
|
||||||
AVIOContext* context = mFormatCtx->pb;
|
AVIOContext* context = mFormatCtx->pb;
|
||||||
|
avformat_close_input(&mFormatCtx);
|
||||||
av_free(context);
|
av_free(context);
|
||||||
mFormatCtx->pb = NULL;
|
|
||||||
av_close_input_file(mFormatCtx);
|
|
||||||
}
|
}
|
||||||
mFormatCtx = NULL;
|
|
||||||
|
|
||||||
mDataStream.setNull();
|
mDataStream.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FFmpeg_Decoder::getName()
|
||||||
|
{
|
||||||
|
return mFormatCtx->filename;
|
||||||
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
{
|
{
|
||||||
if(mStreams.empty())
|
if(!mStream)
|
||||||
fail("No audio stream info");
|
fail("No audio stream info");
|
||||||
|
|
||||||
MyStream *stream = mStreams[0];
|
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8)
|
||||||
if(stream->mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
|
|
||||||
*type = SampleType_UInt8;
|
*type = SampleType_UInt8;
|
||||||
else if(stream->mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
|
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16)
|
||||||
*type = SampleType_Int16;
|
*type = SampleType_Int16;
|
||||||
else
|
else
|
||||||
fail(std::string("Unsupported sample format: ")+
|
fail(std::string("Unsupported sample format: ")+
|
||||||
av_get_sample_fmt_name(stream->mCodecCtx->sample_fmt));
|
av_get_sample_fmt_name((*mStream)->codec->sample_fmt));
|
||||||
|
|
||||||
if(stream->mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
|
if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_MONO)
|
||||||
*chans = ChannelConfig_Mono;
|
*chans = ChannelConfig_Mono;
|
||||||
else if(stream->mCodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
|
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_STEREO)
|
||||||
*chans = ChannelConfig_Stereo;
|
*chans = ChannelConfig_Stereo;
|
||||||
else if(stream->mCodecCtx->channel_layout == 0)
|
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_QUAD)
|
||||||
|
*chans = ChannelConfig_Quad;
|
||||||
|
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_5POINT1)
|
||||||
|
*chans = ChannelConfig_5point1;
|
||||||
|
else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_7POINT1)
|
||||||
|
*chans = ChannelConfig_7point1;
|
||||||
|
else if((*mStream)->codec->channel_layout == 0)
|
||||||
{
|
{
|
||||||
/* Unknown channel layout. Try to guess. */
|
/* Unknown channel layout. Try to guess. */
|
||||||
if(stream->mCodecCtx->channels == 1)
|
if((*mStream)->codec->channels == 1)
|
||||||
*chans = ChannelConfig_Mono;
|
*chans = ChannelConfig_Mono;
|
||||||
else if(stream->mCodecCtx->channels == 2)
|
else if((*mStream)->codec->channels == 2)
|
||||||
*chans = ChannelConfig_Stereo;
|
*chans = ChannelConfig_Stereo;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream sstr("Unsupported raw channel count: ");
|
std::stringstream sstr("Unsupported raw channel count: ");
|
||||||
sstr << stream->mCodecCtx->channels;
|
sstr << (*mStream)->codec->channels;
|
||||||
fail(sstr.str());
|
fail(sstr.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char str[1024];
|
char str[1024];
|
||||||
av_get_channel_layout_string(str, sizeof(str), stream->mCodecCtx->channels,
|
av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels,
|
||||||
stream->mCodecCtx->channel_layout);
|
(*mStream)->codec->channel_layout);
|
||||||
fail(std::string("Unsupported channel layout: ")+str);
|
fail(std::string("Unsupported channel layout: ")+str);
|
||||||
}
|
}
|
||||||
|
|
||||||
*samplerate = stream->mCodecCtx->sample_rate;
|
*samplerate = (*mStream)->codec->sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
if(mStreams.empty())
|
if(!mStream)
|
||||||
fail("No audio streams");
|
fail("No audio stream");
|
||||||
|
return readAVAudioData(buffer, bytes);
|
||||||
return mStreams.front()->readAVAudioData(buffer, bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
||||||
{
|
{
|
||||||
if(mStreams.empty())
|
if(!mStream)
|
||||||
fail("No audio streams");
|
fail("No audio stream");
|
||||||
MyStream *stream = mStreams.front();
|
|
||||||
char *inbuf;
|
|
||||||
size_t got;
|
|
||||||
|
|
||||||
while((inbuf=(char*)stream->getAVAudioData(&got)) != NULL && got > 0)
|
while(getAVAudioData())
|
||||||
|
{
|
||||||
|
size_t got = mFrame->nb_samples * (*mStream)->codec->channels *
|
||||||
|
av_get_bytes_per_sample((*mStream)->codec->sample_fmt);
|
||||||
|
const char *inbuf = reinterpret_cast<char*>(mFrame->data[0]);
|
||||||
output.insert(output.end(), inbuf, inbuf+got);
|
output.insert(output.end(), inbuf, inbuf+got);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::rewind()
|
void FFmpeg_Decoder::rewind()
|
||||||
{
|
{
|
||||||
av_seek_frame(mFormatCtx, -1, 0, 0);
|
int stream_idx = mStream - mFormatCtx->streams;
|
||||||
std::for_each(mStreams.begin(), mStreams.end(), std::mem_fun(&MyStream::clearPackets));
|
if(av_seek_frame(mFormatCtx, stream_idx, 0, 0) < 0)
|
||||||
|
fail("Failed to seek in audio stream");
|
||||||
|
av_free_packet(&mPacket);
|
||||||
|
mFrameSize = mFramePos = 0;
|
||||||
|
mNextPts = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpeg_Decoder::FFmpeg_Decoder() : mFormatCtx(NULL)
|
size_t FFmpeg_Decoder::getSampleOffset()
|
||||||
{
|
{
|
||||||
static bool done_init = false;
|
int delay = (mFrameSize-mFramePos) / (*mStream)->codec->channels /
|
||||||
|
av_get_bytes_per_sample((*mStream)->codec->sample_fmt);
|
||||||
|
return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
FFmpeg_Decoder::FFmpeg_Decoder()
|
||||||
|
: mFormatCtx(NULL)
|
||||||
|
, mStream(NULL)
|
||||||
|
, mFrame(NULL)
|
||||||
|
, mFrameSize(0)
|
||||||
|
, mFramePos(0)
|
||||||
|
, mNextPts(0.0)
|
||||||
|
{
|
||||||
|
memset(&mPacket, 0, sizeof(mPacket));
|
||||||
|
|
||||||
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
||||||
* output from the lib */
|
* output from the lib */
|
||||||
|
static bool done_init = false;
|
||||||
if(!done_init)
|
if(!done_init)
|
||||||
{
|
{
|
||||||
av_register_all();
|
av_register_all();
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include <avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "sound_decoder.hpp"
|
#include "sound_decoder.hpp"
|
||||||
@ -22,25 +22,36 @@ namespace MWSound
|
|||||||
class FFmpeg_Decoder : public Sound_Decoder
|
class FFmpeg_Decoder : public Sound_Decoder
|
||||||
{
|
{
|
||||||
AVFormatContext *mFormatCtx;
|
AVFormatContext *mFormatCtx;
|
||||||
|
AVStream **mStream;
|
||||||
|
|
||||||
struct MyStream;
|
AVPacket mPacket;
|
||||||
std::vector<MyStream*> mStreams;
|
AVFrame *mFrame;
|
||||||
|
|
||||||
bool getNextPacket(int streamidx);
|
int mFrameSize;
|
||||||
|
int mFramePos;
|
||||||
|
|
||||||
|
double mNextPts;
|
||||||
|
|
||||||
|
bool getNextPacket();
|
||||||
|
|
||||||
Ogre::DataStreamPtr mDataStream;
|
Ogre::DataStreamPtr mDataStream;
|
||||||
static int readPacket(void *user_data, uint8_t *buf, int buf_size);
|
static int readPacket(void *user_data, uint8_t *buf, int buf_size);
|
||||||
static int writePacket(void *user_data, uint8_t *buf, int buf_size);
|
static int writePacket(void *user_data, uint8_t *buf, int buf_size);
|
||||||
static int64_t seek(void *user_data, int64_t offset, int whence);
|
static int64_t seek(void *user_data, int64_t offset, int whence);
|
||||||
|
|
||||||
|
bool getAVAudioData();
|
||||||
|
size_t readAVAudioData(void *data, size_t length);
|
||||||
|
|
||||||
virtual void open(const std::string &fname);
|
virtual void open(const std::string &fname);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
|
virtual std::string getName();
|
||||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||||
|
|
||||||
virtual size_t read(char *buffer, size_t bytes);
|
virtual size_t read(char *buffer, size_t bytes);
|
||||||
virtual void readAll(std::vector<char> &output);
|
virtual void readAll(std::vector<char> &output);
|
||||||
virtual void rewind();
|
virtual void rewind();
|
||||||
|
virtual size_t getSampleOffset();
|
||||||
|
|
||||||
FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs);
|
FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs);
|
||||||
FFmpeg_Decoder(const FFmpeg_Decoder &rhs);
|
FFmpeg_Decoder(const FFmpeg_Decoder &rhs);
|
||||||
|
@ -155,6 +155,11 @@ void MpgSnd_Decoder::close()
|
|||||||
mDataStream.setNull();
|
mDataStream.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string MpgSnd_Decoder::getName()
|
||||||
|
{
|
||||||
|
return mDataStream->getName();
|
||||||
|
}
|
||||||
|
|
||||||
void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||||
{
|
{
|
||||||
if(!mSndFile && !mMpgFile)
|
if(!mSndFile && !mMpgFile)
|
||||||
@ -213,6 +218,11 @@ void MpgSnd_Decoder::rewind()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t MpgSnd_Decoder::getSampleOffset()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MpgSnd_Decoder::MpgSnd_Decoder()
|
MpgSnd_Decoder::MpgSnd_Decoder()
|
||||||
: mSndInfo()
|
: mSndInfo()
|
||||||
, mSndFile(NULL)
|
, mSndFile(NULL)
|
||||||
|
@ -34,11 +34,13 @@ namespace MWSound
|
|||||||
virtual void open(const std::string &fname);
|
virtual void open(const std::string &fname);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
|
virtual std::string getName();
|
||||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||||
|
|
||||||
virtual size_t read(char *buffer, size_t bytes);
|
virtual size_t read(char *buffer, size_t bytes);
|
||||||
virtual void readAll(std::vector<char> &output);
|
virtual void readAll(std::vector<char> &output);
|
||||||
virtual void rewind();
|
virtual void rewind();
|
||||||
|
virtual size_t getSampleOffset();
|
||||||
|
|
||||||
MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs);
|
MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs);
|
||||||
MpgSnd_Decoder(const MpgSnd_Decoder &rhs);
|
MpgSnd_Decoder(const MpgSnd_Decoder &rhs);
|
||||||
|
@ -61,10 +61,50 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
|
|||||||
if(fmtlist[i].chans == chans && fmtlist[i].type == type)
|
if(fmtlist[i].chans == chans && fmtlist[i].type == type)
|
||||||
return fmtlist[i].format;
|
return fmtlist[i].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
char name[32];
|
||||||
|
ChannelConfig chans;
|
||||||
|
SampleType type;
|
||||||
|
} mcfmtlist[] = {
|
||||||
|
{ "AL_FORMAT_QUAD16", ChannelConfig_Quad, SampleType_Int16 },
|
||||||
|
{ "AL_FORMAT_QUAD8", ChannelConfig_Quad, SampleType_UInt8 },
|
||||||
|
{ "AL_FORMAT_51CHN16", ChannelConfig_5point1, SampleType_Int16 },
|
||||||
|
{ "AL_FORMAT_51CHN8", ChannelConfig_5point1, SampleType_UInt8 },
|
||||||
|
{ "AL_FORMAT_71CHN16", ChannelConfig_7point1, SampleType_Int16 },
|
||||||
|
{ "AL_FORMAT_71CHN8", ChannelConfig_7point1, SampleType_UInt8 },
|
||||||
|
};
|
||||||
|
static const size_t mcfmtlistsize = sizeof(mcfmtlist)/sizeof(mcfmtlist[0]);
|
||||||
|
|
||||||
|
for(size_t i = 0;i < mcfmtlistsize;i++)
|
||||||
|
{
|
||||||
|
if(mcfmtlist[i].chans == chans && mcfmtlist[i].type == type)
|
||||||
|
{
|
||||||
|
ALenum format = alGetEnumValue(mcfmtlist[i].name);
|
||||||
|
if(format != 0 && format != -1)
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fail(std::string("Unsupported sound format (")+getChannelConfigName(chans)+", "+getSampleTypeName(type)+")");
|
fail(std::string("Unsupported sound format (")+getChannelConfigName(chans)+", "+getSampleTypeName(type)+")");
|
||||||
return AL_NONE;
|
return AL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALint getBufferSampleCount(ALuint buf)
|
||||||
|
{
|
||||||
|
ALint size, bits, channels;
|
||||||
|
|
||||||
|
alGetBufferi(buf, AL_SIZE, &size);
|
||||||
|
alGetBufferi(buf, AL_BITS, &bits);
|
||||||
|
alGetBufferi(buf, AL_CHANNELS, &channels);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
return size / channels * 8 / bits;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// A streaming OpenAL sound.
|
// A streaming OpenAL sound.
|
||||||
//
|
//
|
||||||
@ -82,19 +122,26 @@ class OpenAL_SoundStream : public Sound
|
|||||||
ALsizei mSampleRate;
|
ALsizei mSampleRate;
|
||||||
ALuint mBufferSize;
|
ALuint mBufferSize;
|
||||||
|
|
||||||
|
ALuint mSamplesQueued;
|
||||||
|
|
||||||
DecoderPtr mDecoder;
|
DecoderPtr mDecoder;
|
||||||
|
|
||||||
volatile bool mIsFinished;
|
volatile bool mIsFinished;
|
||||||
|
|
||||||
|
void updateAll(bool local);
|
||||||
|
|
||||||
OpenAL_SoundStream(const OpenAL_SoundStream &rhs);
|
OpenAL_SoundStream(const OpenAL_SoundStream &rhs);
|
||||||
OpenAL_SoundStream& operator=(const OpenAL_SoundStream &rhs);
|
OpenAL_SoundStream& operator=(const OpenAL_SoundStream &rhs);
|
||||||
|
|
||||||
|
friend class OpenAL_Output;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder);
|
OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, float basevol, float pitch, int flags);
|
||||||
virtual ~OpenAL_SoundStream();
|
virtual ~OpenAL_SoundStream();
|
||||||
|
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool isPlaying();
|
virtual bool isPlaying();
|
||||||
|
virtual double getTimeOffset();
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
void play();
|
void play();
|
||||||
@ -109,7 +156,7 @@ const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f;
|
|||||||
struct OpenAL_Output::StreamThread {
|
struct OpenAL_Output::StreamThread {
|
||||||
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
typedef std::vector<OpenAL_SoundStream*> StreamVec;
|
||||||
StreamVec mStreams;
|
StreamVec mStreams;
|
||||||
boost::mutex mMutex;
|
boost::recursive_mutex mMutex;
|
||||||
boost::thread mThread;
|
boost::thread mThread;
|
||||||
|
|
||||||
StreamThread()
|
StreamThread()
|
||||||
@ -170,8 +217,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder)
|
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, float basevol, float pitch, int flags)
|
||||||
: mOutput(output), mSource(src), mDecoder(decoder), mIsFinished(true)
|
: Sound(Ogre::Vector3(0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)
|
||||||
|
, mOutput(output), mSource(src), mSamplesQueued(0), mDecoder(decoder), mIsFinished(true)
|
||||||
{
|
{
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
@ -189,6 +237,8 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode
|
|||||||
|
|
||||||
mBufferSize = static_cast<ALuint>(sBufferLength*srate);
|
mBufferSize = static_cast<ALuint>(sBufferLength*srate);
|
||||||
mBufferSize = framesToBytes(mBufferSize, chans, type);
|
mBufferSize = framesToBytes(mBufferSize, chans, type);
|
||||||
|
|
||||||
|
mOutput.mActiveSounds.push_back(this);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -209,22 +259,20 @@ OpenAL_SoundStream::~OpenAL_SoundStream()
|
|||||||
alGetError();
|
alGetError();
|
||||||
|
|
||||||
mDecoder->close();
|
mDecoder->close();
|
||||||
|
|
||||||
|
mOutput.mActiveSounds.erase(std::find(mOutput.mActiveSounds.begin(),
|
||||||
|
mOutput.mActiveSounds.end(), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_SoundStream::play()
|
void OpenAL_SoundStream::play()
|
||||||
{
|
{
|
||||||
std::vector<char> data(mBufferSize);
|
|
||||||
|
|
||||||
alSourceStop(mSource);
|
alSourceStop(mSource);
|
||||||
alSourcei(mSource, AL_BUFFER, 0);
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
mSamplesQueued = 0;
|
||||||
|
|
||||||
for(ALuint i = 0;i < sNumBuffers;i++)
|
for(ALuint i = 0;i < sNumBuffers;i++)
|
||||||
{
|
alBufferData(mBuffers[i], mFormat, this, 0, mSampleRate);
|
||||||
size_t got;
|
|
||||||
got = mDecoder->read(&data[0], data.size());
|
|
||||||
alBufferData(mBuffers[i], mFormat, &data[0], got, mSampleRate);
|
|
||||||
}
|
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
alSourceQueueBuffers(mSource, sNumBuffers, mBuffers);
|
alSourceQueueBuffers(mSource, sNumBuffers, mBuffers);
|
||||||
@ -243,6 +291,7 @@ void OpenAL_SoundStream::stop()
|
|||||||
alSourceStop(mSource);
|
alSourceStop(mSource);
|
||||||
alSourcei(mSource, AL_BUFFER, 0);
|
alSourcei(mSource, AL_BUFFER, 0);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
mSamplesQueued = 0;
|
||||||
|
|
||||||
mDecoder->rewind();
|
mDecoder->rewind();
|
||||||
}
|
}
|
||||||
@ -254,11 +303,49 @@ bool OpenAL_SoundStream::isPlaying()
|
|||||||
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
if(state == AL_PLAYING)
|
if(state == AL_PLAYING || state == AL_PAUSED)
|
||||||
return true;
|
return true;
|
||||||
return !mIsFinished;
|
return !mIsFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double OpenAL_SoundStream::getTimeOffset()
|
||||||
|
{
|
||||||
|
ALint state = AL_STOPPED;
|
||||||
|
ALfloat offset = 0.0f;
|
||||||
|
double t;
|
||||||
|
|
||||||
|
mOutput.mStreamThread->mMutex.lock();
|
||||||
|
alGetSourcef(mSource, AL_SEC_OFFSET, &offset);
|
||||||
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
|
if(state == AL_PLAYING || state == AL_PAUSED)
|
||||||
|
t = (double)(mDecoder->getSampleOffset() - mSamplesQueued)/(double)mSampleRate + offset;
|
||||||
|
else
|
||||||
|
t = (double)mDecoder->getSampleOffset() / (double)mSampleRate;
|
||||||
|
mOutput.mStreamThread->mMutex.unlock();
|
||||||
|
|
||||||
|
throwALerror();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_SoundStream::updateAll(bool local)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance);
|
||||||
|
alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
|
||||||
|
if(local)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_ROLLOFF_FACTOR, 0.0f);
|
||||||
|
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
}
|
||||||
|
alSourcei(mSource, AL_LOOPING, AL_FALSE);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void OpenAL_SoundStream::update()
|
void OpenAL_SoundStream::update()
|
||||||
{
|
{
|
||||||
ALfloat gain = mVolume*mBaseVolume;
|
ALfloat gain = mVolume*mBaseVolume;
|
||||||
@ -279,52 +366,58 @@ void OpenAL_SoundStream::update()
|
|||||||
|
|
||||||
bool OpenAL_SoundStream::process()
|
bool OpenAL_SoundStream::process()
|
||||||
{
|
{
|
||||||
bool finished = mIsFinished;
|
try {
|
||||||
ALint processed, state;
|
bool finished = mIsFinished;
|
||||||
|
ALint processed, state;
|
||||||
|
|
||||||
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed);
|
alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed);
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
if(processed > 0)
|
|
||||||
{
|
|
||||||
std::vector<char> data(mBufferSize);
|
|
||||||
do {
|
|
||||||
ALuint bufid;
|
|
||||||
size_t got;
|
|
||||||
|
|
||||||
alSourceUnqueueBuffers(mSource, 1, &bufid);
|
|
||||||
processed--;
|
|
||||||
|
|
||||||
if(finished)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
got = mDecoder->read(&data[0], data.size());
|
|
||||||
finished = (got < data.size());
|
|
||||||
if(got > 0)
|
|
||||||
{
|
|
||||||
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
|
|
||||||
alSourceQueueBuffers(mSource, 1, &bufid);
|
|
||||||
}
|
|
||||||
} while(processed > 0);
|
|
||||||
throwALerror();
|
throwALerror();
|
||||||
}
|
|
||||||
|
|
||||||
if(state != AL_PLAYING && state != AL_PAUSED)
|
if(processed > 0)
|
||||||
{
|
|
||||||
ALint queued;
|
|
||||||
|
|
||||||
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
|
|
||||||
throwALerror();
|
|
||||||
if(queued > 0)
|
|
||||||
{
|
{
|
||||||
alSourcePlay(mSource);
|
std::vector<char> data(mBufferSize);
|
||||||
|
do {
|
||||||
|
ALuint bufid = 0;
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(mSource, 1, &bufid);
|
||||||
|
mSamplesQueued -= getBufferSampleCount(bufid);
|
||||||
|
processed--;
|
||||||
|
|
||||||
|
if(finished)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
got = mDecoder->read(&data[0], data.size());
|
||||||
|
finished = (got < data.size());
|
||||||
|
if(got > 0)
|
||||||
|
{
|
||||||
|
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
|
||||||
|
alSourceQueueBuffers(mSource, 1, &bufid);
|
||||||
|
mSamplesQueued += getBufferSampleCount(bufid);
|
||||||
|
}
|
||||||
|
} while(processed > 0);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mIsFinished = finished;
|
if(state != AL_PLAYING && state != AL_PAUSED)
|
||||||
return !finished;
|
{
|
||||||
|
ALint queued = 0;
|
||||||
|
|
||||||
|
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
if(queued > 0)
|
||||||
|
alSourcePlay(mSource);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsFinished = finished;
|
||||||
|
}
|
||||||
|
catch(std::exception &e) {
|
||||||
|
std::cout<< "Error updating stream \""<<mDecoder->getName()<<"\"" <<std::endl;
|
||||||
|
mSamplesQueued = 0;
|
||||||
|
mIsFinished = true;
|
||||||
|
}
|
||||||
|
return !mIsFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -338,16 +431,21 @@ protected:
|
|||||||
ALuint mSource;
|
ALuint mSource;
|
||||||
ALuint mBuffer;
|
ALuint mBuffer;
|
||||||
|
|
||||||
|
friend class OpenAL_Output;
|
||||||
|
|
||||||
|
void updateAll(bool local);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OpenAL_Sound(const OpenAL_Sound &rhs);
|
OpenAL_Sound(const OpenAL_Sound &rhs);
|
||||||
OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
|
OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf);
|
OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf, const Ogre::Vector3& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags);
|
||||||
virtual ~OpenAL_Sound();
|
virtual ~OpenAL_Sound();
|
||||||
|
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool isPlaying();
|
virtual bool isPlaying();
|
||||||
|
virtual double getTimeOffset();
|
||||||
virtual void update();
|
virtual void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,16 +458,18 @@ class OpenAL_Sound3D : public OpenAL_Sound
|
|||||||
OpenAL_Sound3D& operator=(const OpenAL_Sound &rhs);
|
OpenAL_Sound3D& operator=(const OpenAL_Sound &rhs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenAL_Sound3D(OpenAL_Output &output, ALuint src, ALuint buf)
|
OpenAL_Sound3D(OpenAL_Output &output, ALuint src, ALuint buf, const Ogre::Vector3& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags)
|
||||||
: OpenAL_Sound(output, src, buf)
|
: OpenAL_Sound(output, src, buf, pos, vol, basevol, pitch, mindist, maxdist, flags)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf)
|
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf, const Ogre::Vector3& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags)
|
||||||
: mOutput(output), mSource(src), mBuffer(buf)
|
: Sound(pos, vol, basevol, pitch, mindist, maxdist, flags)
|
||||||
|
, mOutput(output), mSource(src), mBuffer(buf)
|
||||||
{
|
{
|
||||||
|
mOutput.mActiveSounds.push_back(this);
|
||||||
}
|
}
|
||||||
OpenAL_Sound::~OpenAL_Sound()
|
OpenAL_Sound::~OpenAL_Sound()
|
||||||
{
|
{
|
||||||
@ -378,6 +478,9 @@ OpenAL_Sound::~OpenAL_Sound()
|
|||||||
|
|
||||||
mOutput.mFreeSources.push_back(mSource);
|
mOutput.mFreeSources.push_back(mSource);
|
||||||
mOutput.bufferFinished(mBuffer);
|
mOutput.bufferFinished(mBuffer);
|
||||||
|
|
||||||
|
mOutput.mActiveSounds.erase(std::find(mOutput.mActiveSounds.begin(),
|
||||||
|
mOutput.mActiveSounds.end(), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_Sound::stop()
|
void OpenAL_Sound::stop()
|
||||||
@ -393,13 +496,43 @@ bool OpenAL_Sound::isPlaying()
|
|||||||
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
return state==AL_PLAYING;
|
return state==AL_PLAYING || state==AL_PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
double OpenAL_Sound::getTimeOffset()
|
||||||
|
{
|
||||||
|
ALfloat t;
|
||||||
|
|
||||||
|
alGetSourcef(mSource, AL_SEC_OFFSET, &t);
|
||||||
|
throwALerror();
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Sound::updateAll(bool local)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_REFERENCE_DISTANCE, mMinDistance);
|
||||||
|
alSourcef(mSource, AL_MAX_DISTANCE, mMaxDistance);
|
||||||
|
if(local)
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_ROLLOFF_FACTOR, 0.0f);
|
||||||
|
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alSourcef(mSource, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
alSourcei(mSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
}
|
||||||
|
alSourcei(mSource, AL_LOOPING, (mFlags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE);
|
||||||
|
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_Sound::update()
|
void OpenAL_Sound::update()
|
||||||
{
|
{
|
||||||
ALfloat gain = mVolume*mBaseVolume;
|
ALfloat gain = mVolume*mBaseVolume;
|
||||||
ALfloat pitch = mPitch;
|
ALfloat pitch = mPitch;
|
||||||
|
|
||||||
if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater)
|
if(!(mFlags&MWBase::SoundManager::Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater)
|
||||||
{
|
{
|
||||||
gain *= 0.9f;
|
gain *= 0.9f;
|
||||||
@ -521,11 +654,9 @@ void OpenAL_Output::deinit()
|
|||||||
{
|
{
|
||||||
mStreamThread->removeAll();
|
mStreamThread->removeAll();
|
||||||
|
|
||||||
while(!mFreeSources.empty())
|
for(size_t i = 0;i < mFreeSources.size();i++)
|
||||||
{
|
alDeleteSources(1, &mFreeSources[i]);
|
||||||
alDeleteSources(1, &mFreeSources.front());
|
mFreeSources.clear();
|
||||||
mFreeSources.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
mBufferRefs.clear();
|
mBufferRefs.clear();
|
||||||
mUnusedBuffers.clear();
|
mUnusedBuffers.clear();
|
||||||
@ -642,7 +773,7 @@ void OpenAL_Output::bufferFinished(ALuint buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, int flags)
|
MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, float basevol, float pitch, int flags)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<OpenAL_Sound> sound;
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
ALuint src=0, buf=0;
|
ALuint src=0, buf=0;
|
||||||
@ -655,7 +786,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
buf = getBuffer(fname);
|
buf = getBuffer(fname);
|
||||||
sound.reset(new OpenAL_Sound(*this, src, buf));
|
sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags));
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -666,25 +797,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
sound->updateAll(true);
|
||||||
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
|
||||||
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f);
|
|
||||||
alSourcef(src, AL_MAX_DISTANCE, 1000.0f);
|
|
||||||
alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
|
|
||||||
|
|
||||||
if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater)
|
|
||||||
{
|
|
||||||
volume *= 0.9f;
|
|
||||||
pitch *= 0.7f;
|
|
||||||
}
|
|
||||||
alSourcef(src, AL_GAIN, volume);
|
|
||||||
alSourcef(src, AL_PITCH, pitch);
|
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
|
||||||
alSourcei(src, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE);
|
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
alSourcei(src, AL_BUFFER, buf);
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
alSourcePlay(src);
|
alSourcePlay(src);
|
||||||
@ -693,8 +806,8 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume
|
|||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch,
|
MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float vol, float basevol, float pitch,
|
||||||
float min, float max, int flags)
|
float min, float max, int flags)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<OpenAL_Sound> sound;
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
ALuint src=0, buf=0;
|
ALuint src=0, buf=0;
|
||||||
@ -707,7 +820,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
buf = getBuffer(fname);
|
buf = getBuffer(fname);
|
||||||
sound.reset(new OpenAL_Sound3D(*this, src, buf));
|
sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags));
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -718,26 +831,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSource3f(src, AL_POSITION, pos.x, pos.z, -pos.y);
|
sound->updateAll(false);
|
||||||
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
|
||||||
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
alSourcef(src, AL_REFERENCE_DISTANCE, min);
|
|
||||||
alSourcef(src, AL_MAX_DISTANCE, max);
|
|
||||||
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
|
||||||
|
|
||||||
if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater)
|
|
||||||
{
|
|
||||||
volume *= 0.9f;
|
|
||||||
pitch *= 0.7f;
|
|
||||||
}
|
|
||||||
alSourcef(src, AL_GAIN, (pos.squaredDistance(mPos) > max*max) ?
|
|
||||||
0.0f : volume);
|
|
||||||
alSourcef(src, AL_PITCH, pitch);
|
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
|
||||||
alSourcei(src, AL_LOOPING, (flags&MWBase::SoundManager::Play_Loop) ? AL_TRUE : AL_FALSE);
|
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
alSourcei(src, AL_BUFFER, buf);
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
alSourcePlay(src);
|
alSourcePlay(src);
|
||||||
@ -747,7 +841,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MWBase::SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch, int flags)
|
MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, float pitch, int flags)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<OpenAL_SoundStream> sound;
|
boost::shared_ptr<OpenAL_SoundStream> sound;
|
||||||
ALuint src;
|
ALuint src;
|
||||||
@ -757,13 +851,11 @@ MWBase::SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volu
|
|||||||
src = mFreeSources.front();
|
src = mFreeSources.front();
|
||||||
mFreeSources.pop_front();
|
mFreeSources.pop_front();
|
||||||
|
|
||||||
|
if((flags&MWBase::SoundManager::Play_Loop))
|
||||||
|
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if((flags&MWBase::SoundManager::Play_Loop))
|
sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags));
|
||||||
std::cout <<"Warning: cannot loop stream "<<fname<< std::endl;
|
|
||||||
DecoderPtr decoder = mManager.getDecoder();
|
|
||||||
decoder->open(fname);
|
|
||||||
sound.reset(new OpenAL_SoundStream(*this, src, decoder));
|
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -771,25 +863,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volu
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
sound->updateAll(true);
|
||||||
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
|
||||||
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f);
|
|
||||||
alSourcef(src, AL_MAX_DISTANCE, 1000.0f);
|
|
||||||
alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
|
|
||||||
|
|
||||||
if(!(flags&MWBase::SoundManager::Play_NoEnv) && mLastEnvironment == Env_Underwater)
|
|
||||||
{
|
|
||||||
volume *= 0.9f;
|
|
||||||
pitch *= 0.7f;
|
|
||||||
}
|
|
||||||
alSourcef(src, AL_GAIN, volume);
|
|
||||||
alSourcef(src, AL_PITCH, pitch);
|
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
|
||||||
alSourcei(src, AL_LOOPING, AL_FALSE);
|
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
sound->play();
|
sound->play();
|
||||||
return sound;
|
return sound;
|
||||||
@ -814,6 +888,61 @@ void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenAL_Output::pauseSounds(int types)
|
||||||
|
{
|
||||||
|
std::vector<ALuint> sources;
|
||||||
|
SoundVec::const_iterator iter = mActiveSounds.begin();
|
||||||
|
while(iter != mActiveSounds.end())
|
||||||
|
{
|
||||||
|
const OpenAL_SoundStream *stream = dynamic_cast<OpenAL_SoundStream*>(*iter);
|
||||||
|
if(stream)
|
||||||
|
{
|
||||||
|
if(stream->mSource && (stream->getPlayType()&types))
|
||||||
|
sources.push_back(stream->mSource);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const OpenAL_Sound *sound = dynamic_cast<OpenAL_Sound*>(*iter);
|
||||||
|
if(sound && sound->mSource && (sound->getPlayType()&types))
|
||||||
|
sources.push_back(sound->mSource);
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
if(sources.size() > 0)
|
||||||
|
{
|
||||||
|
alSourcePausev(sources.size(), &sources[0]);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAL_Output::resumeSounds(int types)
|
||||||
|
{
|
||||||
|
std::vector<ALuint> sources;
|
||||||
|
SoundVec::const_iterator iter = mActiveSounds.begin();
|
||||||
|
while(iter != mActiveSounds.end())
|
||||||
|
{
|
||||||
|
const OpenAL_SoundStream *stream = dynamic_cast<OpenAL_SoundStream*>(*iter);
|
||||||
|
if(stream)
|
||||||
|
{
|
||||||
|
if(stream->mSource && (stream->getPlayType()&types))
|
||||||
|
sources.push_back(stream->mSource);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const OpenAL_Sound *sound = dynamic_cast<OpenAL_Sound*>(*iter);
|
||||||
|
if(sound && sound->mSource && (sound->getPlayType()&types))
|
||||||
|
sources.push_back(sound->mSource);
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
if(sources.size() > 0)
|
||||||
|
{
|
||||||
|
alSourcePlayv(sources.size(), &sources[0]);
|
||||||
|
throwALerror();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenAL_Output::OpenAL_Output(SoundManager &mgr)
|
OpenAL_Output::OpenAL_Output(SoundManager &mgr)
|
||||||
: Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0),
|
: Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0),
|
||||||
mLastEnvironment(Env_Normal), mStreamThread(new StreamThread)
|
mLastEnvironment(Env_Normal), mStreamThread(new StreamThread)
|
||||||
|
@ -33,6 +33,9 @@ namespace MWSound
|
|||||||
|
|
||||||
uint64_t mBufferCacheMemSize;
|
uint64_t mBufferCacheMemSize;
|
||||||
|
|
||||||
|
typedef std::vector<Sound*> SoundVec;
|
||||||
|
SoundVec mActiveSounds;
|
||||||
|
|
||||||
ALuint getBuffer(const std::string &fname);
|
ALuint getBuffer(const std::string &fname);
|
||||||
void bufferFinished(ALuint buffer);
|
void bufferFinished(ALuint buffer);
|
||||||
|
|
||||||
@ -42,13 +45,16 @@ namespace MWSound
|
|||||||
virtual void init(const std::string &devname="");
|
virtual void init(const std::string &devname="");
|
||||||
virtual void deinit();
|
virtual void deinit();
|
||||||
|
|
||||||
virtual MWBase::SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags);
|
virtual MWBase::SoundPtr playSound(const std::string &fname, float vol, float basevol, float pitch, int flags);
|
||||||
virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
||||||
float volume, float pitch, float min, float max, int flags);
|
float vol, float basevol, float pitch, float min, float max, int flags);
|
||||||
virtual MWBase::SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags);
|
virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float volume, float pitch, int flags);
|
||||||
|
|
||||||
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env);
|
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env);
|
||||||
|
|
||||||
|
virtual void pauseSounds(int types);
|
||||||
|
virtual void resumeSounds(int types);
|
||||||
|
|
||||||
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
||||||
OpenAL_Output(const OpenAL_Output &rhs);
|
OpenAL_Output(const OpenAL_Output &rhs);
|
||||||
|
|
||||||
@ -64,7 +70,7 @@ namespace MWSound
|
|||||||
friend class SoundManager;
|
friend class SoundManager;
|
||||||
};
|
};
|
||||||
#ifndef DEFAULT_OUTPUT
|
#ifndef DEFAULT_OUTPUT
|
||||||
#define DEFAULT_OUTPUT (::MWSound::OpenAL_Output)
|
#define DEFAULT_OUTPUT(x) ::MWSound::OpenAL_Output((x))
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,16 +26,22 @@ namespace MWSound
|
|||||||
public:
|
public:
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
virtual bool isPlaying() = 0;
|
virtual bool isPlaying() = 0;
|
||||||
|
virtual double getTimeOffset() = 0;
|
||||||
void setPosition(const Ogre::Vector3 &pos) { mPos = pos; }
|
void setPosition(const Ogre::Vector3 &pos) { mPos = pos; }
|
||||||
void setVolume(float volume) { mVolume = volume; }
|
void setVolume(float volume) { mVolume = volume; }
|
||||||
|
|
||||||
Sound() : mPos(0.0f, 0.0f, 0.0f)
|
MWBase::SoundManager::PlayType getPlayType() const
|
||||||
, mVolume(1.0f)
|
{ return (MWBase::SoundManager::PlayType)(mFlags&MWBase::SoundManager::Play_TypeMask); }
|
||||||
, mBaseVolume(1.0f)
|
|
||||||
, mPitch(1.0f)
|
|
||||||
, mMinDistance(20.0f) /* 1 * min_range_scale */
|
Sound(const Ogre::Vector3& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags)
|
||||||
, mMaxDistance(12750.0f) /* 255 * max_range_scale */
|
: mPos(pos)
|
||||||
, mFlags(MWBase::SoundManager::Play_Normal)
|
, mVolume(vol)
|
||||||
|
, mBaseVolume(basevol)
|
||||||
|
, mPitch(pitch)
|
||||||
|
, mMinDistance(mindist)
|
||||||
|
, mMaxDistance(maxdist)
|
||||||
|
, mFlags(flags)
|
||||||
{ }
|
{ }
|
||||||
virtual ~Sound() { }
|
virtual ~Sound() { }
|
||||||
|
|
||||||
|
@ -15,7 +15,10 @@ namespace MWSound
|
|||||||
|
|
||||||
enum ChannelConfig {
|
enum ChannelConfig {
|
||||||
ChannelConfig_Mono,
|
ChannelConfig_Mono,
|
||||||
ChannelConfig_Stereo
|
ChannelConfig_Stereo,
|
||||||
|
ChannelConfig_Quad,
|
||||||
|
ChannelConfig_5point1,
|
||||||
|
ChannelConfig_7point1
|
||||||
};
|
};
|
||||||
const char *getChannelConfigName(ChannelConfig config);
|
const char *getChannelConfigName(ChannelConfig config);
|
||||||
|
|
||||||
@ -29,11 +32,13 @@ namespace MWSound
|
|||||||
virtual void open(const std::string &fname) = 0;
|
virtual void open(const std::string &fname) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
virtual std::string getName() = 0;
|
||||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
||||||
|
|
||||||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||||
virtual void readAll(std::vector<char> &output);
|
virtual void readAll(std::vector<char> &output);
|
||||||
virtual void rewind() = 0;
|
virtual void rewind() = 0;
|
||||||
|
virtual size_t getSampleOffset() = 0;
|
||||||
|
|
||||||
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
||||||
{ }
|
{ }
|
||||||
|
@ -24,13 +24,16 @@ namespace MWSound
|
|||||||
virtual void init(const std::string &devname="") = 0;
|
virtual void init(const std::string &devname="") = 0;
|
||||||
virtual void deinit() = 0;
|
virtual void deinit() = 0;
|
||||||
|
|
||||||
virtual MWBase::SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0;
|
virtual MWBase::SoundPtr playSound(const std::string &fname, float vol, float basevol, float pitch, int flags) = 0;
|
||||||
virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
virtual MWBase::SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
||||||
float volume, float pitch, float min, float max, int flags) = 0;
|
float vol, float basevol, float pitch, float min, float max, int flags) = 0;
|
||||||
virtual MWBase::SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags) = 0;
|
virtual MWBase::SoundPtr streamSound(DecoderPtr decoder, float volume, float pitch, int flags) = 0;
|
||||||
|
|
||||||
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0;
|
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0;
|
||||||
|
|
||||||
|
virtual void pauseSounds(int types) = 0;
|
||||||
|
virtual void resumeSounds(int types) = 0;
|
||||||
|
|
||||||
Sound_Output& operator=(const Sound_Output &rhs);
|
Sound_Output& operator=(const Sound_Output &rhs);
|
||||||
Sound_Output(const Sound_Output &rhs);
|
Sound_Output(const Sound_Output &rhs);
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ namespace MWSound
|
|||||||
, mMusicVolume(1.0f)
|
, mMusicVolume(1.0f)
|
||||||
, mFootstepsVolume(1.0f)
|
, mFootstepsVolume(1.0f)
|
||||||
, mVoiceVolume(1.0f)
|
, mVoiceVolume(1.0f)
|
||||||
|
, mPausedSoundTypes(0)
|
||||||
{
|
{
|
||||||
if(!useSound)
|
if(!useSound)
|
||||||
return;
|
return;
|
||||||
@ -86,7 +87,7 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
if(devname.empty())
|
if(devname.empty())
|
||||||
throw;
|
throw;
|
||||||
std::cout <<"Failed to open device \""<<devname<<"\", trying default."<< std::endl << "The error given was: " << e.what() << std::endl;
|
std::cerr <<"Failed to open device \""<<devname<<"\": " << e.what() << std::endl;
|
||||||
mOutput->init();
|
mOutput->init();
|
||||||
Settings::Manager::setString("device", "Sound", "");
|
Settings::Manager::setString("device", "Sound", "");
|
||||||
}
|
}
|
||||||
@ -137,6 +138,27 @@ namespace MWSound
|
|||||||
return "Sound/"+snd->mSound;
|
return "Sound/"+snd->mSound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the combined volume settings for the given sound type
|
||||||
|
float SoundManager::volumeFromType(PlayType type) const
|
||||||
|
{
|
||||||
|
float volume = mMasterVolume;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case Play_TypeSfx:
|
||||||
|
volume *= mSFXVolume;
|
||||||
|
break;
|
||||||
|
case Play_TypeVoice:
|
||||||
|
volume *= mVoiceVolume;
|
||||||
|
break;
|
||||||
|
case Play_TypeMusic:
|
||||||
|
case Play_TypeMovie:
|
||||||
|
volume *= mMusicVolume;
|
||||||
|
break;
|
||||||
|
case Play_TypeMask:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
bool SoundManager::isPlaying(MWWorld::Ptr ptr, const std::string &id) const
|
bool SoundManager::isPlaying(MWWorld::Ptr ptr, const std::string &id) const
|
||||||
{
|
{
|
||||||
@ -165,11 +187,13 @@ namespace MWSound
|
|||||||
std::cout <<"Playing "<<filename<< std::endl;
|
std::cout <<"Playing "<<filename<< std::endl;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
float basevol = mMasterVolume * mMusicVolume;
|
|
||||||
stopMusic();
|
stopMusic();
|
||||||
mMusic = mOutput->streamSound(filename, basevol, 1.0f, Play_NoEnv);
|
|
||||||
mMusic->mBaseVolume = basevol;
|
DecoderPtr decoder = getDecoder();
|
||||||
mMusic->mFlags = Play_NoEnv;
|
decoder->open(filename);
|
||||||
|
|
||||||
|
mMusic = mOutput->streamSound(decoder, volumeFromType(Play_TypeMusic),
|
||||||
|
1.0f, Play_NoEnv|Play_TypeMusic);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -212,16 +236,13 @@ namespace MWSound
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// The range values are not tested
|
// The range values are not tested
|
||||||
float basevol = mMasterVolume * mVoiceVolume;
|
float basevol = volumeFromType(Play_TypeVoice);
|
||||||
std::string filePath = "Sound/"+filename;
|
std::string filePath = "Sound/"+filename;
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
|
|
||||||
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, basevol, 1.0f,
|
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
|
||||||
20.0f, 12750.0f, Play_Normal);
|
20.0f, 12750.0f, Play_Normal|Play_TypeVoice);
|
||||||
sound->mPos = objpos;
|
|
||||||
sound->mBaseVolume = basevol;
|
|
||||||
|
|
||||||
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
|
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
@ -236,12 +257,10 @@ namespace MWSound
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
float basevol = mMasterVolume * mVoiceVolume;
|
float basevol = volumeFromType(Play_TypeVoice);
|
||||||
std::string filePath = "Sound/"+filename;
|
std::string filePath = "Sound/"+filename;
|
||||||
|
|
||||||
MWBase::SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal);
|
MWBase::SoundPtr sound = mOutput->playSound(filePath, 1.0f, basevol, 1.0f, Play_Normal|Play_TypeVoice);
|
||||||
sound->mBaseVolume = basevol;
|
|
||||||
|
|
||||||
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound"));
|
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound"));
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
@ -271,26 +290,35 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MWBase::SoundPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type)
|
||||||
|
{
|
||||||
|
MWBase::SoundPtr track;
|
||||||
|
if(!mOutput->isInitialized())
|
||||||
|
return track;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
track = mOutput->streamSound(decoder, volumeFromType(type), 1.0f, Play_NoEnv|type);
|
||||||
|
}
|
||||||
|
catch(std::exception &e)
|
||||||
|
{
|
||||||
|
std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
||||||
|
}
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode)
|
|
||||||
|
MWBase::SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, PlayMode mode)
|
||||||
{
|
{
|
||||||
MWBase::SoundPtr sound;
|
MWBase::SoundPtr sound;
|
||||||
if(!mOutput->isInitialized())
|
if(!mOutput->isInitialized())
|
||||||
return sound;
|
return sound;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
float basevol = mMasterVolume * mSFXVolume;
|
float basevol = volumeFromType(Play_TypeSfx);
|
||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, basevol, min, max);
|
std::string file = lookup(soundId, volume, min, max);
|
||||||
|
|
||||||
sound = mOutput->playSound(file, volume*basevol, pitch, mode);
|
|
||||||
sound->mVolume = volume;
|
|
||||||
sound->mBaseVolume = basevol;
|
|
||||||
sound->mPitch = pitch;
|
|
||||||
sound->mMinDistance = min;
|
|
||||||
sound->mMaxDistance = max;
|
|
||||||
sound->mFlags = mode;
|
|
||||||
|
|
||||||
|
sound = mOutput->playSound(file, volume, basevol, pitch, mode|Play_TypeSfx);
|
||||||
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
@ -301,7 +329,7 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
|
|
||||||
MWBase::SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId,
|
MWBase::SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId,
|
||||||
float volume, float pitch, int mode)
|
float volume, float pitch, PlayMode mode)
|
||||||
{
|
{
|
||||||
MWBase::SoundPtr sound;
|
MWBase::SoundPtr sound;
|
||||||
if(!mOutput->isInitialized())
|
if(!mOutput->isInitialized())
|
||||||
@ -309,21 +337,13 @@ namespace MWSound
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Look up the sound in the ESM data
|
// Look up the sound in the ESM data
|
||||||
float basevol = mMasterVolume * mSFXVolume;
|
float basevol = volumeFromType(Play_TypeSfx);
|
||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, basevol, min, max);
|
std::string file = lookup(soundId, volume, min, max);
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();;
|
const ESM::Position &pos = ptr.getRefData().getPosition();;
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
|
|
||||||
sound = mOutput->playSound3D(file, objpos, volume*basevol, pitch, min, max, mode);
|
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|Play_TypeSfx);
|
||||||
sound->mPos = objpos;
|
|
||||||
sound->mVolume = volume;
|
|
||||||
sound->mBaseVolume = basevol;
|
|
||||||
sound->mPitch = pitch;
|
|
||||||
sound->mMinDistance = min;
|
|
||||||
sound->mMaxDistance = max;
|
|
||||||
sound->mFlags = mode;
|
|
||||||
|
|
||||||
if((mode&Play_NoTrack))
|
if((mode&Play_NoTrack))
|
||||||
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
||||||
else
|
else
|
||||||
@ -404,6 +424,27 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SoundManager::pauseSounds(int types)
|
||||||
|
{
|
||||||
|
if(mOutput->isInitialized())
|
||||||
|
{
|
||||||
|
types &= Play_TypeMask;
|
||||||
|
mOutput->pauseSounds(types);
|
||||||
|
mPausedSoundTypes |= types;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::resumeSounds(int types)
|
||||||
|
{
|
||||||
|
if(mOutput->isInitialized())
|
||||||
|
{
|
||||||
|
types &= types&Play_TypeMask&mPausedSoundTypes;
|
||||||
|
mOutput->resumeSounds(types);
|
||||||
|
mPausedSoundTypes &= ~types;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SoundManager::updateRegionSound(float duration)
|
void SoundManager::updateRegionSound(float duration)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
|
MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
|
||||||
@ -525,24 +566,13 @@ namespace MWSound
|
|||||||
SoundMap::iterator snditer = mActiveSounds.begin();
|
SoundMap::iterator snditer = mActiveSounds.begin();
|
||||||
while(snditer != mActiveSounds.end())
|
while(snditer != mActiveSounds.end())
|
||||||
{
|
{
|
||||||
if(snditer->second.second != "_say_sound")
|
snditer->first->mBaseVolume = volumeFromType(snditer->first->getPlayType());
|
||||||
{
|
|
||||||
float basevol = mMasterVolume * mSFXVolume;
|
|
||||||
float min, max;
|
|
||||||
lookup(snditer->second.second, basevol, min, max);
|
|
||||||
snditer->first->mBaseVolume = basevol;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float basevol = mMasterVolume * mVoiceVolume;
|
|
||||||
snditer->first->mBaseVolume = basevol;
|
|
||||||
}
|
|
||||||
snditer->first->update();
|
snditer->first->update();
|
||||||
snditer++;
|
snditer++;
|
||||||
}
|
}
|
||||||
if(mMusic)
|
if(mMusic)
|
||||||
{
|
{
|
||||||
mMusic->mBaseVolume = mMasterVolume * mMusicVolume;
|
mMusic->mBaseVolume = volumeFromType(mMusic->getPlayType());
|
||||||
mMusic->update();
|
mMusic->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,8 +615,11 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
switch(config)
|
switch(config)
|
||||||
{
|
{
|
||||||
case ChannelConfig_Mono: return "Mono";
|
case ChannelConfig_Mono: return "Mono";
|
||||||
case ChannelConfig_Stereo: return "Stereo";
|
case ChannelConfig_Stereo: return "Stereo";
|
||||||
|
case ChannelConfig_Quad: return "Quad";
|
||||||
|
case ChannelConfig_5point1: return "5.1 Surround";
|
||||||
|
case ChannelConfig_7point1: return "7.1 Surround";
|
||||||
}
|
}
|
||||||
return "(unknown channel config)";
|
return "(unknown channel config)";
|
||||||
}
|
}
|
||||||
@ -595,8 +628,11 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
switch(config)
|
switch(config)
|
||||||
{
|
{
|
||||||
case ChannelConfig_Mono: frames *= 1; break;
|
case ChannelConfig_Mono: frames *= 1; break;
|
||||||
case ChannelConfig_Stereo: frames *= 2; break;
|
case ChannelConfig_Stereo: frames *= 2; break;
|
||||||
|
case ChannelConfig_Quad: frames *= 4; break;
|
||||||
|
case ChannelConfig_5point1: frames *= 6; break;
|
||||||
|
case ChannelConfig_7point1: frames *= 8; break;
|
||||||
}
|
}
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -22,8 +22,6 @@ namespace MWSound
|
|||||||
struct Sound_Decoder;
|
struct Sound_Decoder;
|
||||||
class Sound;
|
class Sound;
|
||||||
|
|
||||||
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
|
||||||
|
|
||||||
enum Environment {
|
enum Environment {
|
||||||
Env_Normal,
|
Env_Normal,
|
||||||
Env_Underwater
|
Env_Underwater
|
||||||
@ -54,6 +52,8 @@ namespace MWSound
|
|||||||
Ogre::Vector3 mListenerDir;
|
Ogre::Vector3 mListenerDir;
|
||||||
Ogre::Vector3 mListenerUp;
|
Ogre::Vector3 mListenerUp;
|
||||||
|
|
||||||
|
int mPausedSoundTypes;
|
||||||
|
|
||||||
std::string lookup(const std::string &soundId,
|
std::string lookup(const std::string &soundId,
|
||||||
float &volume, float &min, float &max);
|
float &volume, float &min, float &max);
|
||||||
void streamMusicFull(const std::string& filename);
|
void streamMusicFull(const std::string& filename);
|
||||||
@ -61,6 +61,8 @@ namespace MWSound
|
|||||||
void updateSounds(float duration);
|
void updateSounds(float duration);
|
||||||
void updateRegionSound(float duration);
|
void updateRegionSound(float duration);
|
||||||
|
|
||||||
|
float volumeFromType(PlayType type) const;
|
||||||
|
|
||||||
SoundManager(const SoundManager &rhs);
|
SoundManager(const SoundManager &rhs);
|
||||||
SoundManager& operator=(const SoundManager &rhs);
|
SoundManager& operator=(const SoundManager &rhs);
|
||||||
|
|
||||||
@ -105,11 +107,14 @@ namespace MWSound
|
|||||||
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr());
|
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr());
|
||||||
///< Stop an actor speaking
|
///< Stop an actor speaking
|
||||||
|
|
||||||
virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal);
|
virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type);
|
||||||
|
///< Play a 2D audio track, using a custom decoder
|
||||||
|
|
||||||
|
virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayMode mode=Play_Normal);
|
||||||
///< Play a sound, independently of 3D-position
|
///< Play a sound, independently of 3D-position
|
||||||
|
|
||||||
virtual MWBase::SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
virtual MWBase::SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
||||||
float volume, float pitch, int mode=Play_Normal);
|
float volume, float pitch, PlayMode mode=Play_Normal);
|
||||||
///< Play a sound from an object
|
///< Play a sound from an object
|
||||||
|
|
||||||
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId);
|
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId);
|
||||||
@ -127,6 +132,12 @@ namespace MWSound
|
|||||||
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const;
|
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const;
|
||||||
///< Is the given sound currently playing on the given object?
|
///< Is the given sound currently playing on the given object?
|
||||||
|
|
||||||
|
virtual void pauseSounds(int types=Play_TypeMask);
|
||||||
|
///< Pauses all currently playing sounds, including music.
|
||||||
|
|
||||||
|
virtual void resumeSounds(int types=Play_TypeMask);
|
||||||
|
///< Resumes all previously paused sounds.
|
||||||
|
|
||||||
virtual void update(float duration);
|
virtual void update(float duration);
|
||||||
|
|
||||||
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up);
|
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up);
|
||||||
|
@ -738,7 +738,7 @@ void WeatherManager::update(float duration)
|
|||||||
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end())
|
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end())
|
||||||
{
|
{
|
||||||
mSoundsPlaying.push_back(ambientSnd);
|
mSoundsPlaying.push_back(ambientSnd);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound(ambientSnd, 1.0, 1.0, true);
|
MWBase::Environment::get().getSoundManager()->playSound(ambientSnd, 1.0, 1.0, MWBase::SoundManager::Play_Loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ void WeatherManager::update(float duration)
|
|||||||
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end())
|
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end())
|
||||||
{
|
{
|
||||||
mSoundsPlaying.push_back(rainSnd);
|
mSoundsPlaying.push_back(rainSnd);
|
||||||
MWBase::Environment::get().getSoundManager()->playSound(rainSnd, 1.0, 1.0, true);
|
MWBase::Environment::get().getSoundManager()->playSound(rainSnd, 1.0, 1.0, MWBase::SoundManager::Play_Loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,4 +1300,14 @@ namespace MWWorld
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::playVideo (const std::string &name, bool allowSkipping)
|
||||||
|
{
|
||||||
|
mRendering->playVideo(name, allowSkipping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::stopVideo ()
|
||||||
|
{
|
||||||
|
mRendering->stopVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,6 +336,10 @@ namespace MWWorld
|
|||||||
/// 1 - only waiting \n
|
/// 1 - only waiting \n
|
||||||
/// 2 - player is underwater \n
|
/// 2 - player is underwater \n
|
||||||
/// 3 - enemies are nearby (not implemented)
|
/// 3 - enemies are nearby (not implemented)
|
||||||
|
|
||||||
|
/// \todo this does not belong here
|
||||||
|
virtual void playVideo(const std::string& name, bool allowSkipping);
|
||||||
|
virtual void stopVideo();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
# Find the FFmpeg library
|
|
||||||
#
|
|
||||||
# Sets
|
|
||||||
# FFMPEG_FOUND. If false, don't try to use ffmpeg
|
|
||||||
# FFMPEG_INCLUDE_DIR
|
|
||||||
# FFMPEG_LIBRARIES
|
|
||||||
#
|
|
||||||
# Modified by Nicolay Korslund for OpenMW
|
|
||||||
|
|
||||||
SET( FFMPEG_FOUND "NO" )
|
|
||||||
|
|
||||||
FIND_PATH( FFMPEG_general_INCLUDE_DIR libavcodec/avcodec.h libavformat/avformat.h
|
|
||||||
HINTS
|
|
||||||
PATHS
|
|
||||||
/usr/include
|
|
||||||
/usr/local/include
|
|
||||||
/usr/include/ffmpeg
|
|
||||||
/usr/local/include/ffmpeg
|
|
||||||
/usr/include/ffmpeg/libavcodec
|
|
||||||
/usr/local/include/ffmpeg/libavcodec
|
|
||||||
/usr/include/libavcodec
|
|
||||||
/usr/local/include/libavcodec
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_PATH( FFMPEG_avcodec_INCLUDE_DIR avcodec.h
|
|
||||||
HINTS
|
|
||||||
PATHS
|
|
||||||
${FFMPEG_general_INCLUDE_DIR}/libavcodec
|
|
||||||
/usr/include
|
|
||||||
/usr/local/include
|
|
||||||
/usr/include/ffmpeg
|
|
||||||
/usr/local/include/ffmpeg
|
|
||||||
/usr/include/ffmpeg/libavcodec
|
|
||||||
/usr/local/include/ffmpeg/libavcodec
|
|
||||||
/usr/include/libavcodec
|
|
||||||
/usr/local/include/libavcodec
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_PATH( FFMPEG_avformat_INCLUDE_DIR avformat.h
|
|
||||||
HINTS
|
|
||||||
PATHS
|
|
||||||
${FFMPEG_general_INCLUDE_DIR}/libavformat
|
|
||||||
/usr/include
|
|
||||||
/usr/local/include
|
|
||||||
/usr/include/ffmpeg
|
|
||||||
/usr/local/include/ffmpeg
|
|
||||||
/usr/include/ffmpeg/libavformat
|
|
||||||
/usr/local/include/ffmpeg/libavformat
|
|
||||||
/usr/include/libavformat
|
|
||||||
/usr/local/include/libavformat
|
|
||||||
)
|
|
||||||
|
|
||||||
set(FFMPEG_INCLUDE_DIR ${FFMPEG_general_INCLUDE_DIR} ${FFMPEG_avcodec_INCLUDE_DIR} ${FFMPEG_avformat_INCLUDE_DIR})
|
|
||||||
|
|
||||||
IF( FFMPEG_INCLUDE_DIR )
|
|
||||||
|
|
||||||
FIND_PROGRAM( FFMPEG_CONFIG ffmpeg-config
|
|
||||||
/usr/bin
|
|
||||||
/usr/local/bin
|
|
||||||
${HOME}/bin
|
|
||||||
)
|
|
||||||
|
|
||||||
IF( FFMPEG_CONFIG )
|
|
||||||
EXEC_PROGRAM( ${FFMPEG_CONFIG} ARGS "--libs avformat" OUTPUT_VARIABLE FFMPEG_LIBS )
|
|
||||||
SET( FFMPEG_FOUND "YES" )
|
|
||||||
SET( FFMPEG_LIBRARIES "${FFMPEG_LIBS}" )
|
|
||||||
|
|
||||||
ELSE( FFMPEG_CONFIG )
|
|
||||||
|
|
||||||
FIND_LIBRARY( FFMPEG_avcodec_LIBRARY avcodec
|
|
||||||
/usr/lib
|
|
||||||
/usr/local/lib
|
|
||||||
/usr/lib64
|
|
||||||
/usr/local/lib64
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY( FFMPEG_avformat_LIBRARY avformat
|
|
||||||
/usr/lib
|
|
||||||
/usr/local/lib
|
|
||||||
/usr/lib64
|
|
||||||
/usr/local/lib64
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY( FFMPEG_avutil_LIBRARY avutil
|
|
||||||
/usr/lib
|
|
||||||
/usr/local/lib
|
|
||||||
/usr/lib64
|
|
||||||
/usr/local/lib64
|
|
||||||
)
|
|
||||||
|
|
||||||
IF( FFMPEG_avcodec_LIBRARY )
|
|
||||||
IF( FFMPEG_avformat_LIBRARY )
|
|
||||||
|
|
||||||
SET( FFMPEG_FOUND "YES" )
|
|
||||||
SET( FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} ${FFMPEG_avcodec_LIBRARY} )
|
|
||||||
IF( FFMPEG_avutil_LIBRARY )
|
|
||||||
SET( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_avutil_LIBRARY} )
|
|
||||||
ENDIF( FFMPEG_avutil_LIBRARY )
|
|
||||||
|
|
||||||
ENDIF( FFMPEG_avformat_LIBRARY )
|
|
||||||
ENDIF( FFMPEG_avcodec_LIBRARY )
|
|
||||||
|
|
||||||
ENDIF( FFMPEG_CONFIG )
|
|
||||||
|
|
||||||
ENDIF( FFMPEG_INCLUDE_DIR )
|
|
148
cmake/FindFFmpeg.cmake
Normal file
148
cmake/FindFFmpeg.cmake
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# vim: ts=2 sw=2
|
||||||
|
# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
|
||||||
|
#
|
||||||
|
# Once done this will define
|
||||||
|
# FFMPEG_FOUND - System has the all required components.
|
||||||
|
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
|
||||||
|
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
|
||||||
|
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
|
||||||
|
#
|
||||||
|
# For each of the components it will additionaly set.
|
||||||
|
# - AVCODEC
|
||||||
|
# - AVDEVICE
|
||||||
|
# - AVFORMAT
|
||||||
|
# - AVUTIL
|
||||||
|
# - POSTPROCESS
|
||||||
|
# - SWSCALE
|
||||||
|
# the following variables will be defined
|
||||||
|
# <component>_FOUND - System has <component>
|
||||||
|
# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
|
||||||
|
# <component>_LIBRARIES - Link these to use <component>
|
||||||
|
# <component>_DEFINITIONS - Compiler switches required for using <component>
|
||||||
|
# <component>_VERSION - The components version
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>
|
||||||
|
# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>
|
||||||
|
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
# The default components were taken from a survey over other FindFFMPEG.cmake files
|
||||||
|
if (NOT FFmpeg_FIND_COMPONENTS)
|
||||||
|
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#
|
||||||
|
### Macro: set_component_found
|
||||||
|
#
|
||||||
|
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
|
||||||
|
#
|
||||||
|
macro(set_component_found _component )
|
||||||
|
if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
|
||||||
|
# message(STATUS " - ${_component} found.")
|
||||||
|
set(${_component}_FOUND TRUE)
|
||||||
|
else ()
|
||||||
|
# message(STATUS " - ${_component} not found.")
|
||||||
|
endif ()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
#
|
||||||
|
### Macro: find_component
|
||||||
|
#
|
||||||
|
# Checks for the given component by invoking pkgconfig and then looking up the libraries and
|
||||||
|
# include directories.
|
||||||
|
#
|
||||||
|
macro(find_component _component _pkgconfig _library _header)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
# use pkg-config to get the directories and then use these values
|
||||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if (PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(PC_${_component} ${_pkgconfig})
|
||||||
|
endif ()
|
||||||
|
endif (NOT WIN32)
|
||||||
|
|
||||||
|
find_path(${_component}_INCLUDE_DIRS ${_header}
|
||||||
|
HINTS
|
||||||
|
${PC_LIB${_component}_INCLUDEDIR}
|
||||||
|
${PC_LIB${_component}_INCLUDE_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
ffmpeg
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(${_component}_LIBRARIES NAMES ${_library}
|
||||||
|
HINTS
|
||||||
|
${PC_LIB${_component}_LIBDIR}
|
||||||
|
${PC_LIB${_component}_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
|
||||||
|
set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.")
|
||||||
|
|
||||||
|
set_component_found(${_component})
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
${_component}_INCLUDE_DIRS
|
||||||
|
${_component}_LIBRARIES
|
||||||
|
${_component}_DEFINITIONS
|
||||||
|
${_component}_VERSION)
|
||||||
|
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
# Check for cached results. If there are skip the costly part.
|
||||||
|
if (NOT FFMPEG_LIBRARIES)
|
||||||
|
|
||||||
|
# Check for all possible component.
|
||||||
|
find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
|
||||||
|
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
|
||||||
|
find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
|
||||||
|
find_component(AVUTIL libavutil avutil libavutil/avutil.h)
|
||||||
|
find_component(SWSCALE libswscale swscale libswscale/swscale.h)
|
||||||
|
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
|
||||||
|
|
||||||
|
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
|
||||||
|
foreach (_component ${FFmpeg_FIND_COMPONENTS})
|
||||||
|
if (${_component}_FOUND)
|
||||||
|
# message(STATUS "Required component ${_component} present.")
|
||||||
|
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES})
|
||||||
|
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
|
||||||
|
list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
|
||||||
|
else ()
|
||||||
|
# message(STATUS "Required component ${_component} missing.")
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# Build the include path with duplicates removed.
|
||||||
|
if (FFMPEG_INCLUDE_DIRS)
|
||||||
|
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# cache the vars.
|
||||||
|
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
|
||||||
|
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
|
||||||
|
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
|
||||||
|
|
||||||
|
mark_as_advanced(FFMPEG_INCLUDE_DIRS
|
||||||
|
FFMPEG_LIBRARIES
|
||||||
|
FFMPEG_DEFINITIONS)
|
||||||
|
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Now set the noncached _FOUND vars for the components.
|
||||||
|
foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE)
|
||||||
|
set_component_found(${_component})
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# Compile the list of required vars
|
||||||
|
set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
|
||||||
|
foreach (_component ${FFmpeg_FIND_COMPONENTS})
|
||||||
|
list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# Give a nice error message if some of the required vars are missing.
|
||||||
|
find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})
|
177
cmake/FindSDL.cmake
Normal file
177
cmake/FindSDL.cmake
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
# Locate SDL library
|
||||||
|
# This module defines
|
||||||
|
# SDL_LIBRARY, the name of the library to link against
|
||||||
|
# SDL_FOUND, if false, do not try to link to SDL
|
||||||
|
# SDL_INCLUDE_DIR, where to find SDL.h
|
||||||
|
#
|
||||||
|
# This module responds to the the flag:
|
||||||
|
# SDL_BUILDING_LIBRARY
|
||||||
|
# If this is defined, then no SDL_main will be linked in because
|
||||||
|
# only applications need main().
|
||||||
|
# Otherwise, it is assumed you are building an application and this
|
||||||
|
# module will attempt to locate and set the the proper link flags
|
||||||
|
# as part of the returned SDL_LIBRARY variable.
|
||||||
|
#
|
||||||
|
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||||
|
# OS X framework based version. (Other versions link to -lSDLmain which
|
||||||
|
# this module will try to find on your behalf.) Also for OS X, this
|
||||||
|
# module will automatically add the -framework Cocoa on your behalf.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Additional Note: If you see an empty SDL_LIBRARY_TEMP in your configuration
|
||||||
|
# and no SDL_LIBRARY, it means CMake did not find your SDL library
|
||||||
|
# (SDL.dll, libsdl.so, SDL.framework, etc).
|
||||||
|
# Set SDL_LIBRARY_TEMP to point to your SDL library, and configure again.
|
||||||
|
# Similarly, if you see an empty SDLMAIN_LIBRARY, you should set this value
|
||||||
|
# as appropriate. These values are used to generate the final SDL_LIBRARY
|
||||||
|
# variable, but when these values are unset, SDL_LIBRARY does not get created.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# $SDLDIR is an environment variable that would
|
||||||
|
# correspond to the ./configure --prefix=$SDLDIR
|
||||||
|
# used in building SDL.
|
||||||
|
# l.e.galup 9-20-02
|
||||||
|
#
|
||||||
|
# Modified by Eric Wing.
|
||||||
|
# Added code to assist with automated building by using environmental variables
|
||||||
|
# and providing a more controlled/consistent search behavior.
|
||||||
|
# Added new modifications to recognize OS X frameworks and
|
||||||
|
# additional Unix paths (FreeBSD, etc).
|
||||||
|
# Also corrected the header search path to follow "proper" SDL guidelines.
|
||||||
|
# Added a search for SDLmain which is needed by some platforms.
|
||||||
|
# Added a search for threads which is needed by some platforms.
|
||||||
|
# Added needed compile switches for MinGW.
|
||||||
|
#
|
||||||
|
# On OSX, this will prefer the Framework version (if found) over others.
|
||||||
|
# People will have to manually change the cache values of
|
||||||
|
# SDL_LIBRARY to override this selection or set the CMake environment
|
||||||
|
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||||
|
#
|
||||||
|
# Note that the header path has changed from SDL/SDL.h to just SDL.h
|
||||||
|
# This needed to change because "proper" SDL convention
|
||||||
|
# is #include "SDL.h", not <SDL/SDL.h>. This is done for portability
|
||||||
|
# reasons because not all systems place things in SDL/ (see FreeBSD).
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2003-2009 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
FIND_PATH(SDL_INCLUDE_DIR SDL.h
|
||||||
|
HINTS
|
||||||
|
$ENV{SDLDIR}
|
||||||
|
PATH_SUFFIXES include/SDL include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local/include/SDL12
|
||||||
|
/usr/local/include/SDL11 # FreeBSD ports
|
||||||
|
/usr/include/SDL12
|
||||||
|
/usr/include/SDL11
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt/csw # Blastwave
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
#MESSAGE("SDL_INCLUDE_DIR is ${SDL_INCLUDE_DIR}")
|
||||||
|
|
||||||
|
# SDL-1.1 is the name used by FreeBSD ports...
|
||||||
|
# don't confuse it for the version number.
|
||||||
|
FIND_LIBRARY(SDL_LIBRARY_TEMP
|
||||||
|
NAMES SDL SDL-1.1
|
||||||
|
HINTS
|
||||||
|
$ENV{SDLDIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
/sw
|
||||||
|
/opt/local
|
||||||
|
/opt/csw
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
#MESSAGE("SDL_LIBRARY_TEMP is ${SDL_LIBRARY_TEMP}")
|
||||||
|
|
||||||
|
IF(NOT SDL_BUILDING_LIBRARY)
|
||||||
|
IF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
|
||||||
|
# Non-OS X framework versions expect you to also dynamically link to
|
||||||
|
# SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||||
|
# seem to provide SDLmain for compatibility even though they don't
|
||||||
|
# necessarily need it.
|
||||||
|
FIND_LIBRARY(SDLMAIN_LIBRARY
|
||||||
|
NAMES SDLmain SDLmain-1.1
|
||||||
|
HINTS
|
||||||
|
$ENV{SDLDIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
/sw
|
||||||
|
/opt/local
|
||||||
|
/opt/csw
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
ENDIF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
|
||||||
|
ENDIF(NOT SDL_BUILDING_LIBRARY)
|
||||||
|
|
||||||
|
# SDL may require threads on your system.
|
||||||
|
# The Apple build may not need an explicit flag because one of the
|
||||||
|
# frameworks may already provide it.
|
||||||
|
# But for non-OSX systems, I will use the CMake Threads package.
|
||||||
|
IF(NOT APPLE)
|
||||||
|
FIND_PACKAGE(Threads)
|
||||||
|
ENDIF(NOT APPLE)
|
||||||
|
|
||||||
|
# MinGW needs an additional library, mwindows
|
||||||
|
# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -lmwindows
|
||||||
|
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||||
|
IF(MINGW)
|
||||||
|
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||||
|
ENDIF(MINGW)
|
||||||
|
|
||||||
|
SET(SDL_FOUND "NO")
|
||||||
|
IF(SDL_LIBRARY_TEMP)
|
||||||
|
# For SDLmain
|
||||||
|
IF(NOT SDL_BUILDING_LIBRARY)
|
||||||
|
IF(SDLMAIN_LIBRARY)
|
||||||
|
SET(SDL_LIBRARY_TEMP ${SDLMAIN_LIBRARY} ${SDL_LIBRARY_TEMP})
|
||||||
|
ENDIF(SDLMAIN_LIBRARY)
|
||||||
|
ENDIF(NOT SDL_BUILDING_LIBRARY)
|
||||||
|
|
||||||
|
# For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
|
||||||
|
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||||
|
# though it actually is there if I modify a pre-used variable.
|
||||||
|
# I think it has something to do with the CACHE STRING.
|
||||||
|
# So I use a temporary variable until the end so I can set the
|
||||||
|
# "real" variable in one-shot.
|
||||||
|
IF(APPLE)
|
||||||
|
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} "-framework Cocoa")
|
||||||
|
ENDIF(APPLE)
|
||||||
|
|
||||||
|
# For threads, as mentioned Apple doesn't need this.
|
||||||
|
# In fact, there seems to be a problem if I used the Threads package
|
||||||
|
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||||
|
IF(NOT APPLE)
|
||||||
|
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
ENDIF(NOT APPLE)
|
||||||
|
|
||||||
|
# For MinGW library
|
||||||
|
IF(MINGW)
|
||||||
|
SET(SDL_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL_LIBRARY_TEMP})
|
||||||
|
ENDIF(MINGW)
|
||||||
|
|
||||||
|
# Set the final string here so the GUI reflects the final state.
|
||||||
|
SET(SDL_LIBRARY ${SDL_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found")
|
||||||
|
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||||
|
SET(SDL_LIBRARY_TEMP "${SDL_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||||
|
|
||||||
|
SET(SDL_FOUND "YES")
|
||||||
|
ENDIF(SDL_LIBRARY_TEMP)
|
||||||
|
|
||||||
|
#MESSAGE("SDL_LIBRARY is ${SDL_LIBRARY}")
|
||||||
|
|
@ -72,7 +72,7 @@ compositor gbufferFinalizer
|
|||||||
pass render_scene
|
pass render_scene
|
||||||
{
|
{
|
||||||
first_render_queue 51
|
first_render_queue 51
|
||||||
last_render_queue 100
|
last_render_queue 105
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target_output
|
target_output
|
||||||
|
Loading…
x
Reference in New Issue
Block a user