From 82931059fd82c3e396f757081466fcbb03c78051 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 19 Apr 2024 22:34:40 +0200 Subject: [PATCH 1/5] Make NormalizedView constructor from const char* explicit --- apps/openmw/mwgui/mainmenu.cpp | 5 ++++- apps/openmw/mwgui/windowmanagerimp.cpp | 3 ++- apps/openmw_test_suite/misc/test_resourcehelpers.cpp | 9 ++++++--- apps/openmw_test_suite/vfs/testpathutil.cpp | 2 +- components/resource/scenemanager.cpp | 3 ++- components/vfs/pathutil.hpp | 2 +- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index be3700342a..53f791fdac 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "../mwbase/environment.hpp" @@ -37,7 +38,9 @@ namespace MWGui getWidget(mVersionText, "VersionText"); mVersionText->setCaption(versionDescription); - mHasAnimatedMenu = mVFS->exists("video/menu_background.bik"); + constexpr VFS::Path::NormalizedView menuBackgroundVideo("video/menu_background.bik"); + + mHasAnimatedMenu = mVFS->exists(menuBackgroundVideo); updateMenu(); } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 61a8b3361c..3212e8f02b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -356,7 +356,8 @@ namespace MWGui mWindows.push_back(std::move(console)); trackWindow(mConsole, makeConsoleWindowSettingValues()); - bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds"); + constexpr VFS::Path::NormalizedView menubookOptionsOverTexture("textures/tx_menubook_options_over.dds"); + const bool questList = mResourceSystem->getVFS()->exists(menubookOptionsOverTexture); auto journal = JournalWindow::create(JournalViewModel::create(), questList, mEncoding); mGuiModeStates[GM_Journal] = GuiModeState(journal.get()); mWindows.push_back(std::move(journal)); diff --git a/apps/openmw_test_suite/misc/test_resourcehelpers.cpp b/apps/openmw_test_suite/misc/test_resourcehelpers.cpp index 5290630394..48edb72578 100644 --- a/apps/openmw_test_suite/misc/test_resourcehelpers.cpp +++ b/apps/openmw_test_suite/misc/test_resourcehelpers.cpp @@ -8,19 +8,22 @@ namespace TEST(CorrectSoundPath, wav_files_not_overridden_with_mp3_in_vfs_are_not_corrected) { std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { "sound/bar.wav", nullptr } }); - EXPECT_EQ(correctSoundPath("sound/bar.wav", *mVFS), "sound/bar.wav"); + constexpr VFS::Path::NormalizedView path("sound/bar.wav"); + EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/bar.wav"); } TEST(CorrectSoundPath, wav_files_overridden_with_mp3_in_vfs_are_corrected) { std::unique_ptr mVFS = TestingOpenMW::createTestVFS({ { "sound/foo.mp3", nullptr } }); - EXPECT_EQ(correctSoundPath("sound/foo.wav", *mVFS), "sound/foo.mp3"); + constexpr VFS::Path::NormalizedView path("sound/foo.wav"); + EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/foo.mp3"); } TEST(CorrectSoundPath, corrected_path_does_not_check_existence_in_vfs) { std::unique_ptr mVFS = TestingOpenMW::createTestVFS({}); - EXPECT_EQ(correctSoundPath("sound/foo.wav", *mVFS), "sound/foo.mp3"); + constexpr VFS::Path::NormalizedView path("sound/foo.wav"); + EXPECT_EQ(correctSoundPath(path, *mVFS), "sound/foo.mp3"); } namespace diff --git a/apps/openmw_test_suite/vfs/testpathutil.cpp b/apps/openmw_test_suite/vfs/testpathutil.cpp index 6eb84f97d5..3819f9905a 100644 --- a/apps/openmw_test_suite/vfs/testpathutil.cpp +++ b/apps/openmw_test_suite/vfs/testpathutil.cpp @@ -39,7 +39,7 @@ namespace VFS::Path TEST(NormalizedTest, shouldSupportConstructorFromNormalizedView) { - const NormalizedView view = "foo/bar/baz"; + const NormalizedView view("foo/bar/baz"); const Normalized value(view); EXPECT_EQ(value.view(), "foo/bar/baz"); } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index e4d0b4363d..6aeae80af6 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -865,7 +865,8 @@ namespace Resource << ", using embedded marker_error instead"; } Files::IMemStream file(ErrorMarker::sValue.data(), ErrorMarker::sValue.size()); - return loadNonNif("error_marker.osgt", file, mImageManager); + constexpr VFS::Path::NormalizedView errorMarker("error_marker.osgt"); + return loadNonNif(errorMarker, file, mImageManager); } osg::ref_ptr SceneManager::cloneErrorMarker() diff --git a/components/vfs/pathutil.hpp b/components/vfs/pathutil.hpp index 07e73acfa9..1696e656ad 100644 --- a/components/vfs/pathutil.hpp +++ b/components/vfs/pathutil.hpp @@ -79,7 +79,7 @@ namespace VFS::Path public: constexpr NormalizedView() noexcept = default; - constexpr NormalizedView(const char* value) + constexpr explicit NormalizedView(const char* value) : mValue(value) { if (!isNormalized(mValue)) From 38b005cda6a5d7de526a676777707348dc603aff Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 12 Mar 2024 00:25:48 +0100 Subject: [PATCH 2/5] Use normalized path to store playlist music files --- apps/openmw/mwsound/soundmanagerimp.cpp | 17 +++++++++++------ apps/openmw/mwsound/soundmanagerimp.hpp | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 56224b4dcb..6ad1359c0d 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -300,13 +300,16 @@ namespace MWSound void SoundManager::startRandomTitle() { - const std::vector& filelist = mMusicFiles[mCurrentPlaylist]; - if (filelist.empty()) + const auto playlist = mMusicFiles.find(mCurrentPlaylist); + + if (playlist == mMusicFiles.end() || playlist->second.empty()) { advanceMusic(std::string()); return; } + const std::vector& filelist = playlist->second; + auto& tracklist = mMusicToPlay[mCurrentPlaylist]; // Do a Fisher-Yates shuffle @@ -359,18 +362,20 @@ namespace MWSound if (mCurrentPlaylist == playlist) return; - if (mMusicFiles.find(playlist) == mMusicFiles.end()) + auto it = mMusicFiles.find(playlist); + + if (it == mMusicFiles.end()) { - std::vector filelist; + std::vector filelist; auto playlistPath = Misc::ResourceHelpers::correctMusicPath(playlist) + '/'; for (const auto& name : mVFS->getRecursiveDirectoryIterator(playlistPath)) filelist.push_back(name); - mMusicFiles[playlist] = std::move(filelist); + it = mMusicFiles.emplace_hint(it, playlist, std::move(filelist)); } // No Battle music? Use Explore playlist - if (playlist == "Battle" && mMusicFiles[playlist].empty()) + if (playlist == "Battle" && it->second.empty()) { playPlaylist("Explore"); return; diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 75b1193118..bd9743c528 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -52,7 +52,7 @@ namespace MWSound std::unique_ptr mOutput; // Caches available music tracks by - std::unordered_map> mMusicFiles; + std::unordered_map> mMusicFiles; std::unordered_map> mMusicToPlay; // A list with music files not yet played std::string mLastPlayedMusic; // The music file that was last played From e11a5a43526778468376e9a813c2ba86ca9a2363 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 12 Mar 2024 00:40:03 +0100 Subject: [PATCH 3/5] Use normalized path for SoundManager::playPlaylist --- apps/niftest/niftest.cpp | 2 +- apps/opencs/model/world/resources.cpp | 2 +- apps/openmw/mwbase/soundmanager.hpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 3 ++- apps/openmw/mwgui/settingswindow.cpp | 3 ++- .../mwmechanics/mechanicsmanagerimp.cpp | 6 +++-- apps/openmw/mwsound/constants.hpp | 12 ++++++++++ apps/openmw/mwsound/soundmanagerimp.cpp | 23 ++++++++++--------- apps/openmw/mwsound/soundmanagerimp.hpp | 8 ++++--- apps/openmw/mwworld/worldimp.cpp | 4 +++- components/misc/resourcehelpers.cpp | 6 +++-- components/misc/resourcehelpers.hpp | 2 +- components/vfs/manager.cpp | 17 ++++++++++++++ components/vfs/manager.hpp | 4 ++++ components/vfs/pathutil.hpp | 22 ++++++++++++++++++ 15 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 apps/openmw/mwsound/constants.hpp diff --git a/apps/niftest/niftest.cpp b/apps/niftest/niftest.cpp index b37d85d739..5dbe99c356 100644 --- a/apps/niftest/niftest.cpp +++ b/apps/niftest/niftest.cpp @@ -95,7 +95,7 @@ void readVFS(std::unique_ptr&& archive, const std::filesystem::pat vfs.addArchive(std::move(archive)); vfs.buildIndex(); - for (const auto& name : vfs.getRecursiveDirectoryIterator("")) + for (const auto& name : vfs.getRecursiveDirectoryIterator()) { if (isNIF(name.value())) { diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index 9957af3d66..7082575c64 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -28,7 +28,7 @@ void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char* const* e size_t baseSize = mBaseDirectory.size(); - for (const auto& filepath : vfs->getRecursiveDirectoryIterator("")) + for (const auto& filepath : vfs->getRecursiveDirectoryIterator()) { const std::string_view view = filepath.view(); if (view.size() < baseSize + 1 || !view.starts_with(mBaseDirectory) || view[baseSize] != '/') diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 05b925f87d..a55d696224 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -126,7 +126,7 @@ namespace MWBase virtual bool isMusicPlaying() = 0; ///< Returns true if music is playing - virtual void playPlaylist(const std::string& playlist) = 0; + virtual void playPlaylist(VFS::Path::NormalizedView playlist) = 0; ///< Start playing music from the selected folder /// \param name of the folder that contains the playlist /// Title music playlist is predefined diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 8ba2bb8312..3a9aba7828 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -67,7 +67,8 @@ namespace MWGui != supported_extensions.end(); }; - for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator("Splash/")) + constexpr VFS::Path::NormalizedView splash("splash/"); + for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(splash)) { if (isSupportedExtension(Misc::getFileExtension(name))) mSplashScreens.push_back(name); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 396d0b18a3..075a338592 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -402,7 +402,8 @@ namespace MWGui std::vector availableLanguages; const VFS::Manager* vfs = MWBase::Environment::get().getResourceSystem()->getVFS(); - for (const auto& path : vfs->getRecursiveDirectoryIterator("l10n/")) + constexpr VFS::Path::NormalizedView l10n("l10n/"); + for (const auto& path : vfs->getRecursiveDirectoryIterator(l10n)) { if (Misc::getFileExtension(path) == "yaml") { diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 47fba46c75..048476c6ef 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -29,6 +29,8 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwsound/constants.hpp" + #include "actor.hpp" #include "actors.hpp" #include "actorutil.hpp" @@ -1678,12 +1680,12 @@ namespace MWMechanics if (mMusicType != MWSound::MusicType::Explore && !hasHostiles && !(player.getClass().getCreatureStats(player).isDead() && musicPlaying)) { - MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); + MWBase::Environment::get().getSoundManager()->playPlaylist(MWSound::explorePlaylist); mMusicType = MWSound::MusicType::Explore; } else if (mMusicType != MWSound::MusicType::Battle && hasHostiles) { - MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Battle")); + MWBase::Environment::get().getSoundManager()->playPlaylist(MWSound::battlePlaylist); mMusicType = MWSound::MusicType::Battle; } } diff --git a/apps/openmw/mwsound/constants.hpp b/apps/openmw/mwsound/constants.hpp new file mode 100644 index 0000000000..5022b142f9 --- /dev/null +++ b/apps/openmw/mwsound/constants.hpp @@ -0,0 +1,12 @@ +#ifndef OPENMW_APPS_OPENMW_MWSOUND_CONSTANTS_H +#define OPENMW_APPS_OPENMW_MWSOUND_CONSTANTS_H + +#include + +namespace MWSound +{ + constexpr VFS::Path::NormalizedView battlePlaylist("battle"); + constexpr VFS::Path::NormalizedView explorePlaylist("explore"); +} + +#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 6ad1359c0d..4c3f227ecd 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -26,14 +26,14 @@ #include "../mwmechanics/actorutil.hpp" +#include "constants.hpp" +#include "ffmpeg_decoder.hpp" +#include "openal_output.hpp" #include "sound.hpp" #include "sound_buffer.hpp" #include "sound_decoder.hpp" #include "sound_output.hpp" -#include "ffmpeg_decoder.hpp" -#include "openal_output.hpp" - namespace MWSound { namespace @@ -352,12 +352,12 @@ namespace MWSound mechanicsManager->setMusicType(type); advanceMusic(normalizedName, fade); if (type == MWSound::MusicType::Battle) - mCurrentPlaylist = "Battle"; + mCurrentPlaylist = battlePlaylist; else if (type == MWSound::MusicType::Explore) - mCurrentPlaylist = "Explore"; + mCurrentPlaylist = explorePlaylist; } - void SoundManager::playPlaylist(const std::string& playlist) + void SoundManager::playPlaylist(VFS::Path::NormalizedView playlist) { if (mCurrentPlaylist == playlist) return; @@ -367,17 +367,18 @@ namespace MWSound if (it == mMusicFiles.end()) { std::vector filelist; - auto playlistPath = Misc::ResourceHelpers::correctMusicPath(playlist) + '/'; - for (const auto& name : mVFS->getRecursiveDirectoryIterator(playlistPath)) + constexpr VFS::Path::NormalizedView music("music"); + const VFS::Path::Normalized playlistPath = music / playlist / VFS::Path::NormalizedView(); + for (const auto& name : mVFS->getRecursiveDirectoryIterator(VFS::Path::NormalizedView(playlistPath))) filelist.push_back(name); it = mMusicFiles.emplace_hint(it, playlist, std::move(filelist)); } // No Battle music? Use Explore playlist - if (playlist == "Battle" && it->second.empty()) + if (playlist == battlePlaylist && it->second.empty()) { - playPlaylist("Explore"); + playPlaylist(explorePlaylist); return; } @@ -1024,7 +1025,7 @@ namespace MWSound mTimePassed = 0.0f; // Make sure music is still playing - if (!isMusicPlaying() && !mCurrentPlaylist.empty()) + if (!isMusicPlaying() && !mCurrentPlaylist.value().empty()) startRandomTitle(); Environment env = Env_Normal; diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index bd9743c528..7fc7c143d5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "../mwbase/soundmanager.hpp" @@ -52,7 +53,8 @@ namespace MWSound std::unique_ptr mOutput; // Caches available music tracks by - std::unordered_map> mMusicFiles; + std::unordered_map, VFS::Path::Hash, std::equal_to<>> + mMusicFiles; std::unordered_map> mMusicToPlay; // A list with music files not yet played std::string mLastPlayedMusic; // The music file that was last played @@ -90,7 +92,7 @@ namespace MWSound TrackList mActiveTracks; StreamPtr mMusic; - std::string mCurrentPlaylist; + VFS::Path::Normalized mCurrentPlaylist; bool mListenerUnderwater; osg::Vec3f mListenerPos; @@ -183,7 +185,7 @@ namespace MWSound bool isMusicPlaying() override; ///< Returns true if music is playing - void playPlaylist(const std::string& playlist) override; + void playPlaylist(VFS::Path::NormalizedView playlist) override; ///< Start playing music from the selected folder /// \param name of the folder that contains the playlist /// Title music playlist is predefined diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 74335a1534..c72a9993d6 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -90,6 +90,8 @@ #include "../mwphysics/object.hpp" #include "../mwphysics/physicssystem.hpp" +#include "../mwsound/constants.hpp" + #include "actionteleport.hpp" #include "cellstore.hpp" #include "containerstore.hpp" @@ -394,7 +396,7 @@ namespace MWWorld { // Make sure that we do not continue to play a Title music after a new game video. MWBase::Environment::get().getSoundManager()->stopMusic(); - MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); + MWBase::Environment::get().getSoundManager()->playPlaylist(MWSound::explorePlaylist); MWBase::Environment::get().getWindowManager()->playVideo(video, true); } } diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index 1d5b57bfd9..1eb3800012 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -186,9 +186,11 @@ VFS::Path::Normalized Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normali return prefix / resPath; } -std::string Misc::ResourceHelpers::correctMusicPath(const std::string& resPath) +std::string Misc::ResourceHelpers::correctMusicPath(std::string_view resPath) { - return "music\\" + resPath; + std::string result("music/"); + result += resPath; + return result; } std::string_view Misc::ResourceHelpers::meshPathForESM3(std::string_view resPath) diff --git a/components/misc/resourcehelpers.hpp b/components/misc/resourcehelpers.hpp index cda99d928d..4e747c54ee 100644 --- a/components/misc/resourcehelpers.hpp +++ b/components/misc/resourcehelpers.hpp @@ -42,7 +42,7 @@ namespace Misc VFS::Path::Normalized correctSoundPath(VFS::Path::NormalizedView resPath); // Adds "music\\". - std::string correctMusicPath(const std::string& resPath); + std::string correctMusicPath(std::string_view resPath); // Removes "meshes\\". std::string_view meshPathForESM3(std::string_view resPath); diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 936dd64679..2d22a7a034 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -99,4 +99,21 @@ namespace VFS ++normalized.back(); return { it, mIndex.lower_bound(normalized) }; } + + RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(VFS::Path::NormalizedView path) const + { + if (path.value().empty()) + return { mIndex.begin(), mIndex.end() }; + const auto it = mIndex.lower_bound(path); + if (it == mIndex.end() || !it->first.view().starts_with(path.value())) + return { it, it }; + std::string copy(path.value()); + ++copy.back(); + return { it, mIndex.lower_bound(copy) }; + } + + RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator() const + { + return { mIndex.begin(), mIndex.end() }; + } } diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index 59211602de..d64be1d1d1 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -65,6 +65,10 @@ namespace VFS /// @note May be called from any thread once the index has been built. RecursiveDirectoryRange getRecursiveDirectoryIterator(std::string_view path) const; + RecursiveDirectoryRange getRecursiveDirectoryIterator(VFS::Path::NormalizedView path) const; + + RecursiveDirectoryRange getRecursiveDirectoryIterator() const; + /// Retrieve the absolute path to the file /// @note Throws an exception if the file can not be found. /// @note May be called from any thread once the index has been built. diff --git a/components/vfs/pathutil.hpp b/components/vfs/pathutil.hpp index 1696e656ad..50f16d1804 100644 --- a/components/vfs/pathutil.hpp +++ b/components/vfs/pathutil.hpp @@ -179,6 +179,12 @@ namespace VFS::Path return true; } + Normalized& operator=(NormalizedView value) + { + mValue = value.value(); + return *this; + } + Normalized& operator/=(NormalizedView value) { mValue.reserve(mValue.size() + value.value().size() + 1); @@ -258,6 +264,22 @@ namespace VFS::Path result /= rhs; return result; } + + struct Hash + { + using is_transparent = void; + + [[nodiscard]] std::size_t operator()(std::string_view sv) const { return std::hash{}(sv); } + + [[nodiscard]] std::size_t operator()(const std::string& s) const { return std::hash{}(s); } + + [[nodiscard]] std::size_t operator()(const Normalized& s) const { return std::hash{}(s.value()); } + + [[nodiscard]] std::size_t operator()(NormalizedView s) const + { + return std::hash{}(s.value()); + } + }; } #endif From 40cc16046b782df327a605a54e1857ee8fa52d1b Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 14 Apr 2024 19:51:10 +0200 Subject: [PATCH 4/5] Use normalized path for sound decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 4 ++-- apps/openmw/mwsound/ffmpeg_decoder.hpp | 2 +- apps/openmw/mwsound/movieaudiofactory.cpp | 12 ++++-------- apps/openmw/mwsound/sound_decoder.hpp | 4 +++- apps/openmw/mwsound/soundmanagerimp.cpp | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 9e7a2be3a8..e9a5a1eb94 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -208,7 +208,7 @@ namespace MWSound return dec; } - void FFmpeg_Decoder::open(const std::string& fname) + void FFmpeg_Decoder::open(VFS::Path::NormalizedView fname) { close(); mDataStream = mResourceMgr->get(fname); @@ -224,7 +224,7 @@ namespace MWSound formatCtx->pb = ioCtx.get(); // avformat_open_input frees user supplied AVFormatContext on failure - if (avformat_open_input(&formatCtx, fname.c_str(), nullptr, nullptr) != 0) + if (avformat_open_input(&formatCtx, fname.value().data(), nullptr, nullptr) != 0) throw std::runtime_error("Failed to open input"); AVFormatContextPtr formatCtxPtr(std::exchange(formatCtx, nullptr)); diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index ed3297403e..264ff8fab7 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -93,7 +93,7 @@ namespace MWSound bool getAVAudioData(); size_t readAVAudioData(void* data, size_t length); - void open(const std::string& fname) override; + void open(VFS::Path::NormalizedView fname) override; void close() override; std::string getName() override; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 1bb5275c45..68ea221321 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -24,8 +24,10 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - void open(const std::string& fname) override; - void close() override; + void open(VFS::Path::NormalizedView fname) override { throw std::runtime_error("Method not implemented"); } + + void close() override {} + std::string getName() override; void getInfo(int* samplerate, ChannelConfig* chans, SampleType* type) override; size_t read(char* buffer, size_t bytes) override; @@ -92,12 +94,6 @@ namespace MWSound std::shared_ptr mDecoderBridge; }; - void MWSoundDecoderBridge::open(const std::string& fname) - { - throw std::runtime_error("Method not implemented"); - } - void MWSoundDecoderBridge::close() {} - std::string MWSoundDecoderBridge::getName() { return mDecoder->getStreamName(); diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index f6dcdb7032..17f9d28909 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -1,6 +1,8 @@ #ifndef GAME_SOUND_SOUND_DECODER_H #define GAME_SOUND_SOUND_DECODER_H +#include + #include #include @@ -36,7 +38,7 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual void open(const std::string& fname) = 0; + virtual void open(VFS::Path::NormalizedView fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 4c3f227ecd..039c283d7a 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -267,7 +267,7 @@ namespace MWSound DecoderPtr decoder = getDecoder(); try { - decoder->open(filename); + decoder->open(VFS::Path::Normalized(filename)); } catch (std::exception& e) { From a863899eb1a158fce32cc3193e8899f17c4d4c24 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 14 Apr 2024 19:51:48 +0200 Subject: [PATCH 5/5] Use normalized path for SoundManager::streamMusic --- apps/openmw/engine.cpp | 6 ++--- apps/openmw/mwbase/soundmanager.hpp | 2 +- apps/openmw/mwgui/levelupdialog.cpp | 5 ++-- apps/openmw/mwlua/soundbindings.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 4 ++- apps/openmw/mwscript/soundextensions.cpp | 2 +- apps/openmw/mwsound/constants.hpp | 3 +++ apps/openmw/mwsound/soundmanagerimp.cpp | 31 +++++++++++------------- apps/openmw/mwsound/soundmanagerimp.hpp | 10 ++++---- components/misc/resourcehelpers.cpp | 7 +++--- components/misc/resourcehelpers.hpp | 6 ++--- 11 files changed, 40 insertions(+), 38 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 63473fe67d..179dbcdc32 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -64,6 +64,7 @@ #include "mwscript/interpretercontext.hpp" #include "mwscript/scriptmanagerimp.hpp" +#include "mwsound/constants.hpp" #include "mwsound/soundmanagerimp.hpp" #include "mwworld/class.hpp" @@ -987,9 +988,8 @@ void OMW::Engine::go() // start in main menu mWindowManager->pushGuiMode(MWGui::GM_MainMenu); - std::string titlefile = "music/special/morrowind title.mp3"; - if (mVFS->exists(titlefile)) - mSoundManager->streamMusic(titlefile, MWSound::MusicType::Special); + if (mVFS->exists(MWSound::titleMusic)) + mSoundManager->streamMusic(MWSound::titleMusic, MWSound::MusicType::Special); else Log(Debug::Warning) << "Title music not found"; diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index a55d696224..ab3f9c5605 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -117,7 +117,7 @@ namespace MWBase virtual void stopMusic() = 0; ///< Stops music if it's playing - virtual void streamMusic(const std::string& filename, MWSound::MusicType type, float fade = 1.f) = 0; + virtual void streamMusic(VFS::Path::NormalizedView filename, MWSound::MusicType type, float fade = 1.f) = 0; ///< Play a soundifle /// \param filename name of a sound file in the data directory. /// \param type music type. diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index 4950e3edf4..f1a40a3f16 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -22,6 +22,8 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwsound/constants.hpp" + #include "class.hpp" namespace @@ -216,8 +218,7 @@ namespace MWGui center(); // Play LevelUp Music - MWBase::Environment::get().getSoundManager()->streamMusic( - "Music/Special/MW_Triumph.mp3", MWSound::MusicType::Special); + MWBase::Environment::get().getSoundManager()->streamMusic(MWSound::triumphMusic, MWSound::MusicType::Special); } void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender) diff --git a/apps/openmw/mwlua/soundbindings.cpp b/apps/openmw/mwlua/soundbindings.cpp index 57d1e606c1..a5ec69b4fc 100644 --- a/apps/openmw/mwlua/soundbindings.cpp +++ b/apps/openmw/mwlua/soundbindings.cpp @@ -141,7 +141,7 @@ namespace MWLua api["streamMusic"] = [](std::string_view fileName, const sol::optional& options) { auto args = getStreamMusicArgs(options); MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager(); - sndMgr->streamMusic(std::string(fileName), MWSound::MusicType::Scripted, args.mFade); + sndMgr->streamMusic(VFS::Path::Normalized(fileName), MWSound::MusicType::Scripted, args.mFade); }; api["say"] diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index addf62df34..32f81c398e 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -39,6 +39,8 @@ #include "../mwrender/vismask.hpp" +#include "../mwsound/constants.hpp" + #include "actor.hpp" #include "actorutil.hpp" #include "aicombataction.hpp" @@ -1798,7 +1800,7 @@ namespace MWMechanics MWBase::Environment::get().getStateManager()->askLoadRecent(); // Play Death Music if it was the player dying MWBase::Environment::get().getSoundManager()->streamMusic( - "Music/Special/MW_Death.mp3", MWSound::MusicType::Special); + MWSound::deathMusic, MWSound::MusicType::Special); } else { diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index ee39860584..79bdf20160 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -63,7 +63,7 @@ namespace MWScript public: void execute(Interpreter::Runtime& runtime) override { - std::string music{ runtime.getStringLiteral(runtime[0].mInteger) }; + const VFS::Path::Normalized music(runtime.getStringLiteral(runtime[0].mInteger)); runtime.pop(); MWBase::Environment::get().getSoundManager()->streamMusic( diff --git a/apps/openmw/mwsound/constants.hpp b/apps/openmw/mwsound/constants.hpp index 5022b142f9..217dd1935e 100644 --- a/apps/openmw/mwsound/constants.hpp +++ b/apps/openmw/mwsound/constants.hpp @@ -7,6 +7,9 @@ namespace MWSound { constexpr VFS::Path::NormalizedView battlePlaylist("battle"); constexpr VFS::Path::NormalizedView explorePlaylist("explore"); + constexpr VFS::Path::NormalizedView titleMusic("music/special/morrowind title.mp3"); + constexpr VFS::Path::NormalizedView triumphMusic("music/special/mw_triumph.mp3"); + constexpr VFS::Path::NormalizedView deathMusic("music/special/mw_death.mp3"); } #endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 039c283d7a..bcaec8ddfd 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -252,13 +252,13 @@ namespace MWSound } } - void SoundManager::streamMusicFull(const std::string& filename) + void SoundManager::streamMusicFull(VFS::Path::NormalizedView filename) { if (!mOutput->isInitialized()) return; stopMusic(); - if (filename.empty()) + if (filename.value().empty()) return; Log(Debug::Info) << "Playing \"" << filename << "\""; @@ -267,9 +267,9 @@ namespace MWSound DecoderPtr decoder = getDecoder(); try { - decoder->open(VFS::Path::Normalized(filename)); + decoder->open(filename); } - catch (std::exception& e) + catch (const std::exception& e) { Log(Debug::Error) << "Failed to load audio from \"" << filename << "\": " << e.what(); return; @@ -285,7 +285,7 @@ namespace MWSound mOutput->streamSound(std::move(decoder), mMusic.get()); } - void SoundManager::advanceMusic(const std::string& filename, float fadeOut) + void SoundManager::advanceMusic(VFS::Path::NormalizedView filename, float fadeOut) { if (!isMusicPlaying()) { @@ -304,7 +304,7 @@ namespace MWSound if (playlist == mMusicFiles.end() || playlist->second.empty()) { - advanceMusic(std::string()); + advanceMusic(VFS::Path::NormalizedView()); return; } @@ -338,7 +338,7 @@ namespace MWSound return mMusic && mOutput->isStreamPlaying(mMusic.get()); } - void SoundManager::streamMusic(const std::string& filename, MusicType type, float fade) + void SoundManager::streamMusic(VFS::Path::NormalizedView filename, MusicType type, float fade) { const auto mechanicsManager = MWBase::Environment::get().getMechanicsManager(); @@ -347,10 +347,8 @@ namespace MWSound && type != MusicType::Special) return; - std::string normalizedName = VFS::Path::normalizeFilename(filename); - mechanicsManager->setMusicType(type); - advanceMusic(normalizedName, fade); + advanceMusic(filename, fade); if (type == MWSound::MusicType::Battle) mCurrentPlaylist = battlePlaylist; else if (type == MWSound::MusicType::Explore) @@ -367,8 +365,8 @@ namespace MWSound if (it == mMusicFiles.end()) { std::vector filelist; - constexpr VFS::Path::NormalizedView music("music"); - const VFS::Path::Normalized playlistPath = music / playlist / VFS::Path::NormalizedView(); + const VFS::Path::Normalized playlistPath + = Misc::ResourceHelpers::correctMusicPath(playlist) / VFS::Path::NormalizedView(); for (const auto& name : mVFS->getRecursiveDirectoryIterator(VFS::Path::NormalizedView(playlistPath))) filelist.push_back(name); @@ -1143,10 +1141,10 @@ namespace MWSound if (!mMusic || !mMusic->updateFade(duration) || !mOutput->isStreamPlaying(mMusic.get())) { stopMusic(); - if (!mNextMusic.empty()) + if (!mNextMusic.value().empty()) { streamMusicFull(mNextMusic); - mNextMusic.clear(); + mNextMusic = VFS::Path::Normalized(); } } else @@ -1166,9 +1164,8 @@ namespace MWSound if (isMainMenu && !isMusicPlaying()) { - std::string titlefile = "music/special/morrowind title.mp3"; - if (mVFS->exists(titlefile)) - streamMusic(titlefile, MWSound::MusicType::Special); + if (mVFS->exists(MWSound::titleMusic)) + streamMusic(MWSound::titleMusic, MWSound::MusicType::Special); } updateSounds(duration); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 7fc7c143d5..1ba80f1d73 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -56,7 +56,7 @@ namespace MWSound std::unordered_map, VFS::Path::Hash, std::equal_to<>> mMusicFiles; std::unordered_map> mMusicToPlay; // A list with music files not yet played - std::string mLastPlayedMusic; // The music file that was last played + VFS::Path::Normalized mLastPlayedMusic; // The music file that was last played WaterSoundUpdater mWaterSoundUpdater; @@ -104,7 +104,7 @@ namespace MWSound Sound* mUnderwaterSound; Sound* mNearWaterSound; - std::string mNextMusic; + VFS::Path::Normalized mNextMusic; bool mPlaybackPaused; RegionSoundSelector mRegionSoundSelector; @@ -125,8 +125,8 @@ namespace MWSound StreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f& pos, bool playlocal); - void streamMusicFull(const std::string& filename); - void advanceMusic(const std::string& filename, float fadeOut = 1.f); + void streamMusicFull(VFS::Path::NormalizedView filename); + void advanceMusic(VFS::Path::NormalizedView filename, float fadeOut = 1.f); void startRandomTitle(); void cull3DSound(SoundBase* sound); @@ -176,7 +176,7 @@ namespace MWSound void stopMusic() override; ///< Stops music if it's playing - void streamMusic(const std::string& filename, MWSound::MusicType type, float fade = 1.f) override; + void streamMusic(VFS::Path::NormalizedView filename, MWSound::MusicType type, float fade = 1.f) override; ///< Play a soundifle /// \param filename name of a sound file in the data directory. /// \param type music type. diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index 1eb3800012..d3d75a8176 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -186,11 +186,10 @@ VFS::Path::Normalized Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normali return prefix / resPath; } -std::string Misc::ResourceHelpers::correctMusicPath(std::string_view resPath) +VFS::Path::Normalized Misc::ResourceHelpers::correctMusicPath(VFS::Path::NormalizedView resPath) { - std::string result("music/"); - result += resPath; - return result; + static constexpr VFS::Path::NormalizedView prefix("music"); + return prefix / resPath; } std::string_view Misc::ResourceHelpers::meshPathForESM3(std::string_view resPath) diff --git a/components/misc/resourcehelpers.hpp b/components/misc/resourcehelpers.hpp index 4e747c54ee..c0728dc442 100644 --- a/components/misc/resourcehelpers.hpp +++ b/components/misc/resourcehelpers.hpp @@ -38,11 +38,11 @@ namespace Misc // Adds "meshes\\". std::string correctMeshPath(std::string_view resPath); - // Adds "sound\\". + // Prepends "sound/". VFS::Path::Normalized correctSoundPath(VFS::Path::NormalizedView resPath); - // Adds "music\\". - std::string correctMusicPath(std::string_view resPath); + // Prepends "music/". + VFS::Path::Normalized correctMusicPath(VFS::Path::NormalizedView resPath); // Removes "meshes\\". std::string_view meshPathForESM3(std::string_view resPath);