From aecf74e7bbeca9dae1d19444535b511f3df7f473 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 07:00:04 -0800 Subject: [PATCH 1/7] Don't throw exceptions from the audio decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 204 ++++++++++++---------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 18 +- apps/openmw/mwsound/movieaudiofactory.cpp | 32 ++-- apps/openmw/mwsound/openal_output.cpp | 14 +- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 153 insertions(+), 119 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 1f18347614..12ea84a42d 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -11,11 +11,6 @@ namespace MWSound { -void FFmpeg_Decoder::fail(const std::string &msg) -{ - throw std::runtime_error("FFmpeg exception: "+msg); -} - int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) { try @@ -33,7 +28,8 @@ int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) int FFmpeg_Decoder::writePacket(void *, uint8_t *, int) { - throw std::runtime_error("can't write to read-only stream"); + std::cerr<< "can't write to read-only stream" <get(fname); - - if((mFormatCtx=avformat_alloc_context()) == NULL) - fail("Failed to allocate context"); - - mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); - if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) - { - // "Note that a user-supplied AVFormatContext will be freed on failure". - if (mFormatCtx) - { - if (mFormatCtx->pb != NULL) - { - if (mFormatCtx->pb->buffer != NULL) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; - } - avformat_free_context(mFormatCtx); - } - mFormatCtx = NULL; - fail("Failed to allocate input stream"); - } - try { + mDataStream = mResourceMgr->get(fname); + + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); + + mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); + if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) + { + // "Note that a user-supplied AVFormatContext will be freed on failure". + if (mFormatCtx) + { + if (mFormatCtx->pb != NULL) + { + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; + } + avformat_free_context(mFormatCtx); + } + mFormatCtx = NULL; + throw std::runtime_error("Failed to allocate input stream"); + } + if(avformat_find_stream_info(mFormatCtx, NULL) < 0) - fail("Failed to find stream info in "+fname); + throw std::runtime_error("Failed to find stream info in "+fname); for(size_t j = 0;j < mFormatCtx->nb_streams;j++) { @@ -224,23 +220,45 @@ void FFmpeg_Decoder::open(const std::string &fname) } } if(!mStream) - fail("No audio streams in "+fname); + throw std::runtime_error("No audio streams in "+fname); (*mStream)->codec->request_sample_fmt = (*mStream)->codec->sample_fmt; 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()); + std::string ss = "No codec found for id " + + std::to_string((*mStream)->codec->codec_id); + throw std::runtime_error(ss); } if(avcodec_open2((*mStream)->codec, codec, NULL) < 0) - fail("Failed to open audio codec " + std::string(codec->long_name)); + throw std::runtime_error(std::string("Failed to open audio codec ") + + codec->long_name); mFrame = av_frame_alloc(); + + if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || + (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) + mOutputSampleFormat = AV_SAMPLE_FMT_U8; + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + else + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + + mOutputChannelLayout = (*mStream)->codec->channel_layout; + if(mOutputChannelLayout == 0) + mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); + + return true; } - catch(std::exception&) + catch(std::exception &e) + { + std::cerr<< "Could not open audio file: "<codec); @@ -248,15 +266,15 @@ void FFmpeg_Decoder::open(const std::string &fname) if (mFormatCtx->pb->buffer != NULL) { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; } av_free(mFormatCtx->pb); mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); - throw; } + return false; } void FFmpeg_Decoder::close() @@ -274,18 +292,18 @@ void FFmpeg_Decoder::close() { if (mFormatCtx->pb != NULL) { - // mFormatCtx->pb->buffer must be freed by hand, - // if not, valgrind will show memleak, see: - // - // https://trac.ffmpeg.org/ticket/1357 - // - if (mFormatCtx->pb->buffer != NULL) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; + // mFormatCtx->pb->buffer must be freed by hand, + // if not, valgrind will show memleak, see: + // + // https://trac.ffmpeg.org/ticket/1357 + // + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; } avformat_close_input(&mFormatCtx); } @@ -298,19 +316,13 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - fail("No audio stream info"); - - if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) - mOutputSampleFormat = AV_SAMPLE_FMT_U8; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; - else - mOutputSampleFormat = AV_SAMPLE_FMT_S16; + { + std::cerr<< "No audio stream info" <codec->channel_layout; - - if(ch_layout == 0) - ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - - mOutputChannelLayout = ch_layout; - if (ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 - || ch_layout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - else if (ch_layout != AV_CH_LAYOUT_MONO - && ch_layout != AV_CH_LAYOUT_STEREO) - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - if(mOutputChannelLayout == AV_CH_LAYOUT_MONO) *chans = ChannelConfig_Mono; else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO) @@ -347,13 +346,27 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * char str[1024]; av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels, (*mStream)->codec->channel_layout); - fail(std::string("Unsupported channel layout: ")+str); + std::cerr<< "Unsupported channel layout: "<codec->channels == 1) + { + mOutputChannelLayout = AV_CH_LAYOUT_MONO; + *chans = ChannelConfig_Mono; + } + else + { + mOutputChannelLayout = AV_CH_LAYOUT_STEREO; + *chans = ChannelConfig_Stereo; + } } *samplerate = (*mStream)->codec->sample_rate; + int64_t ch_layout = (*mStream)->codec->channel_layout; + if(ch_layout == 0) + ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - if(mOutputSampleFormat != (*mStream)->codec->sample_fmt - || mOutputChannelLayout != ch_layout) + if(mOutputSampleFormat != (*mStream)->codec->sample_fmt || + mOutputChannelLayout != ch_layout) { mSwr = swr_alloc_set_opts(mSwr, // SwrContext mOutputChannelLayout, // output ch layout @@ -365,24 +378,37 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * 0, // logging level offset NULL); // log context if(!mSwr) - fail(std::string("Couldn't allocate SwrContext")); + { + std::cerr<< "Couldn't allocate SwrContext" < &output) { if(!mStream) - fail("No audio stream"); + { + std::cerr<< "No audio stream" < &output); - virtual size_t getSampleOffset(); - - void fail(const std::string &msg); + size_t read(char *buffer, size_t bytes) override; + void readAll(std::vector &output) override; + size_t getSampleOffset() override; FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs); FFmpeg_Decoder(const FFmpeg_Decoder &rhs); diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index f54ab5c068..188514f85b 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -1,5 +1,7 @@ #include "movieaudiofactory.hpp" +#include + #include #include @@ -13,7 +15,7 @@ namespace MWSound { class MovieAudioDecoder; - class MWSoundDecoderBridge : public Sound_Decoder + class MWSoundDecoderBridge final : public Sound_Decoder { public: MWSoundDecoderBridge(MWSound::MovieAudioDecoder* decoder) @@ -25,12 +27,12 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - virtual void open(const std::string &fname); - virtual void close(); - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - virtual size_t read(char *buffer, size_t bytes); - virtual size_t getSampleOffset(); + bool open(const std::string &fname) override; + void close() override; + std::string getName() override; + bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + size_t read(char *buffer, size_t bytes) override; + size_t getSampleOffset() override; }; class MovieAudioDecoder : public Video::MovieAudioDecoder @@ -96,9 +98,9 @@ namespace MWSound }; - void MWSoundDecoderBridge::open(const std::string &fname) + bool MWSoundDecoderBridge::open(const std::string &fname) { - throw std::runtime_error("unimplemented"); + return false; } void MWSoundDecoderBridge::close() {} @@ -107,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -124,9 +126,8 @@ namespace MWSound *chans = ChannelConfig_Quad; else { - std::stringstream error; - error << "Unsupported channel layout: " << outputChannelLayout; - throw std::runtime_error(error.str()); + std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); @@ -140,8 +141,11 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - throw std::runtime_error(std::string("Unsupported sample format: ") + str); + std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type); + if(!mDecoder->getInfo(&mSampleRate, &chans, &type)) + return false; mFormat = getALFormat(chans, type); if(!mFormat) return false; @@ -948,14 +949,18 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. if(decoder->mResourceMgr->exists(fname)) - decoder->open(fname); + { + if(!decoder->open(fname)) + return std::make_pair(nullptr, 0); + } else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - decoder->open(file); + if(!decoder->open(file)) + return std::make_pair(nullptr, 0); } std::vector data; @@ -964,7 +969,8 @@ std::pair OpenAL_Output::loadSound(const std::string &fname ALenum format; int srate; - decoder->getInfo(&srate, &chans, &type); + if(!decoder->getInfo(&srate, &chans, &type)) + return std::make_pair(nullptr, 0); format = getALFormat(chans, type); if(!format) return std::make_pair(nullptr, 0); diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 34bae87d74..57edb13936 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual void open(const std::string &fname) = 0; + virtual bool open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; virtual size_t read(char *buffer, size_t bytes) = 0; virtual void readAll(std::vector &output); From 06ae61479a95fbad45ff38c4ef3f62e7988c5cbb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 22:10:09 -0800 Subject: [PATCH 2/7] If a sound effect fails to load, substitute silence. --- apps/openmw/mwsound/openal_output.cpp | 35 ++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 009c019e7b..89475ea481 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -948,35 +948,42 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + bool succeeded; if(decoder->mResourceMgr->exists(fname)) - { - if(!decoder->open(fname)) - return std::make_pair(nullptr, 0); - } + succeeded = decoder->open(fname); else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - if(!decoder->open(file)) - return std::make_pair(nullptr, 0); + succeeded = decoder->open(file); } std::vector data; - ChannelConfig chans; - SampleType type; ALenum format; int srate; - if(!decoder->getInfo(&srate, &chans, &type)) - return std::make_pair(nullptr, 0); - format = getALFormat(chans, type); - if(!format) return std::make_pair(nullptr, 0); - - decoder->readAll(data); + if(succeeded) + { + ChannelConfig chans; + SampleType type; + if(decoder->getInfo(&srate, &chans, &type)) + { + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + } decoder->close(); + if(data.empty()) + { + // If we failed to get any usable audio, substitute with silence. + format = AL_FORMAT_MONO8; + srate = 8000; + data.assign(8000, -128); + } + ALint size; ALuint buf = 0; alGenBuffers(1, &buf); From 08e947319a99021eaa3d16813c97905644a71cbf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 9 Dec 2017 11:00:56 -0800 Subject: [PATCH 3/7] Restore exception throwing to the decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 48 ++++++++------------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 4 +- apps/openmw/mwsound/movieaudiofactory.cpp | 21 ++++----- apps/openmw/mwsound/openal_output.cpp | 52 ++++++++++++----------- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 56 insertions(+), 73 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 12ea84a42d..e2d54876f7 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -176,16 +176,16 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length) return dec; } -bool FFmpeg_Decoder::open(const std::string &fname) +void FFmpeg_Decoder::open(const std::string &fname) { close(); + mDataStream = mResourceMgr->get(fname); + + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); + try { - mDataStream = mResourceMgr->get(fname); - - if((mFormatCtx=avformat_alloc_context()) == NULL) - throw std::runtime_error("Failed to allocate context"); - mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) { @@ -250,16 +250,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mOutputChannelLayout = (*mStream)->codec->channel_layout; if(mOutputChannelLayout == 0) mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); - - return true; } - catch(std::exception &e) - { - std::cerr<< "Could not open audio file: "<codec); mStream = NULL; @@ -273,8 +265,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); + throw; } - return false; } void FFmpeg_Decoder::close() @@ -316,13 +308,10 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - { - std::cerr<< "No audio stream info" < &output) override; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 188514f85b..4975625169 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -27,10 +27,10 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - bool open(const std::string &fname) override; + void open(const std::string &fname) override; void close() override; std::string getName() override; - bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; size_t read(char *buffer, size_t bytes) override; size_t getSampleOffset() override; }; @@ -98,9 +98,9 @@ namespace MWSound }; - bool MWSoundDecoderBridge::open(const std::string &fname) + void MWSoundDecoderBridge::open(const std::string &fname) { - return false; + throw std::runtime_error("Method not implemented"); } void MWSoundDecoderBridge::close() {} @@ -109,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -125,10 +125,8 @@ namespace MWSound else if (outputChannelLayout == AV_CH_LAYOUT_QUAD) *chans = ChannelConfig_Quad; else - { - std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); if (outputSampleFormat == AV_SAMPLE_FMT_U8) @@ -141,11 +139,8 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type)) + try { + mDecoder->getInfo(&mSampleRate, &chans, &type); + mFormat = getALFormat(chans, type); + } + catch(std::exception &e) { + std::cerr<< "Failed to get stream info: "< OpenAL_Output::loadSound(const std::string &fname { getALError(); - DecoderPtr decoder = mManager.getDecoder(); - // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. - bool succeeded; - if(decoder->mResourceMgr->exists(fname)) - succeeded = decoder->open(fname); - else - { - std::string file = fname; - std::string::size_type pos = file.rfind('.'); - if(pos != std::string::npos) - file = file.substr(0, pos)+".mp3"; - succeeded = decoder->open(file); - } - std::vector data; ALenum format; int srate; - if(succeeded) - { + try { + DecoderPtr decoder = mManager.getDecoder(); + // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + if(decoder->mResourceMgr->exists(fname)) + decoder->open(fname); + else + { + std::string file = fname; + std::string::size_type pos = file.rfind('.'); + if(pos != std::string::npos) + file = file.substr(0, pos)+".mp3"; + decoder->open(file); + } + ChannelConfig chans; SampleType type; - if(decoder->getInfo(&srate, &chans, &type)) - { - format = getALFormat(chans, type); - if(format) decoder->readAll(data); - } + decoder->getInfo(&srate, &chans, &type); + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + catch(std::exception &e) { + std::cerr<< "Failed to load audio from "<close(); if(data.empty()) { diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 57edb13936..34bae87d74 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual bool open(const std::string &fname) = 0; + virtual void open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual bool 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 void readAll(std::vector &output); From c908ad2fba38a7260f41d480ad26343622f13ae1 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 10 Dec 2017 14:38:02 +0400 Subject: [PATCH 4/7] Do not allow to place actors underground via SetPos (bug #3783) --- apps/openmw/mwscript/transformationextensions.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index c876d4cf7d..208a1f46f2 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -227,6 +227,17 @@ namespace MWScript } else if(axis == "z") { + // We should not place actors under ground + if (ptr.getClass().isActor()) + { + float terrainHeight = -std::numeric_limits::max(); + if (ptr.getCell()->isExterior()) + terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(osg::Vec3f(ax, ay, az)); + + if (pos < terrainHeight) + pos = terrainHeight; + } + updated = MWBase::Environment::get().getWorld()->moveObject(ptr,ax,ay,pos); } else From 0e04a26ef6d3a5453f69073d9f3351a0cd2b5c34 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 10 Dec 2017 16:10:44 +0400 Subject: [PATCH 5/7] Set duration of magic effects from ingredients (bug #4261) --- apps/openmw/mwmechanics/spellcasting.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 8fbf67535d..d864dc6198 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -968,9 +968,9 @@ namespace MWMechanics float y = roll / std::min(x, 100.f); y *= 0.25f * x; if (magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) - effect.mDuration = static_cast(y); - else effect.mDuration = 1; + else + effect.mDuration = static_cast(y); if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) From ba46473038f68e6e0c1a0235b518e293668d9bfa Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 13 Dec 2017 10:53:23 +0400 Subject: [PATCH 6/7] Do not skip weather transitions from SetPos script command (bug #3603) --- apps/openmw/mwscript/transformationextensions.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 208a1f46f2..68b1063e43 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -202,11 +202,6 @@ namespace MWScript if (!ptr.isInCell()) return; - if (ptr == MWMechanics::getPlayer()) - { - MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); - } - std::string axis = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Float pos = runtime[0].mFloat; @@ -216,6 +211,8 @@ namespace MWScript float ay = ptr.getRefData().getPosition().pos[1]; float az = ptr.getRefData().getPosition().pos[2]; + // Note: SetPos does not skip weather transitions in vanilla engine, so we do not call setTeleported(true) here. + MWWorld::Ptr updated = ptr; if(axis == "x") { From 269c3227eaca6cf4a2a647e3f3f281950b09d853 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Wed, 13 Dec 2017 10:44:06 +0000 Subject: [PATCH 7/7] Make sure we have cmake for the before_install step --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d173ef6f29..02cc7cf20a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ addons: - llvm-toolchain-precise-3.6 packages: [ # Dev - clang-3.6, libunshield-dev, libtinyxml-dev, + cmake, clang-3.6, libunshield-dev, libtinyxml-dev, # Tests libgtest-dev, google-mock, # Boost