diff --git a/include/Nazara/Core/ResourceLoader.hpp b/include/Nazara/Core/ResourceLoader.hpp index a1a5e8ecf..0fa307769 100644 --- a/include/Nazara/Core/ResourceLoader.hpp +++ b/include/Nazara/Core/ResourceLoader.hpp @@ -9,7 +9,6 @@ #include #include -#include #include class NzInputStream; @@ -18,17 +17,21 @@ template class NzResourceLoader { public: - using CheckFunction = bool (*)(NzInputStream& stream, const Parameters& parameters); - using LoadFunction = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); + using ExtensionGetter = bool (*)(const NzString& extension); + using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); + using StreamChecker = bool (*)(NzInputStream& stream, const Parameters& parameters); + using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); + + static bool IsExtensionSupported(const NzString& extension); static bool LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters = Parameters()); static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters = Parameters()); static bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters()); - static void RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadfunc); - static void UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadfunc); + static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); + static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); - using Loader = std::tuple, CheckFunction, LoadFunction>; + using Loader = std::tuple; using LoaderList = std::list; }; diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index 659d3dd24..6444c928c 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -9,6 +9,20 @@ #include #include +template +bool NzResourceLoader::IsExtensionSupported(const NzString& extension) +{ + for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) + { + ExtensionGetter isExtensionSupported = std::get<0>(*loader); + + if (isExtensionSupported && isExtensionSupported(extension)) + return true; + } + + return false; +} + template bool NzResourceLoader::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters) { @@ -28,38 +42,54 @@ bool NzResourceLoader::LoadFromFile(Type* resource, const NzSt return false; } - NzFile file(path, NzFile::ReadOnly); - if (!file.IsOpen()) - { - NazaraError("Failed to open \"" + path + '"'); - return false; - } + NzFile file(path); // Ouvert seulement en cas de besoin for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) { - for (const NzString& loaderExt : std::get<0>(*loader)) + ExtensionGetter isExtensionSupported = std::get<0>(*loader); + if (!isExtensionSupported || !isExtensionSupported(ext)) + continue; + + StreamChecker checkFunc = std::get<1>(*loader); + StreamLoader streamLoader = std::get<2>(*loader); + FileLoader fileLoader = std::get<3>(*loader); + + if (checkFunc && !file.IsOpen()) { - int cmp = NzString::Compare(loaderExt, ext); - if (cmp == 0) + if (!file.Open(NzFile::ReadOnly)) + { + NazaraError("Failed to load file: unable to open file"); + return false; + } + } + + if (fileLoader) + { + if (checkFunc) { file.SetCursorPos(0); - if (!std::get<1>(*loader)(file, parameters)) + if (!checkFunc(file, parameters)) continue; - - file.SetCursorPos(0); - - // Chargement de la ressource - if (std::get<2>(*loader)(resource, file, parameters)) - return true; - - NazaraWarning("Loader failed"); } - else if (cmp < 0) // S'il est encore possible que l'extension se situe après + + if (fileLoader(resource, filePath, parameters)) + return true; + } + else + { + file.SetCursorPos(0); + + if (!checkFunc(file, parameters)) continue; - break; + file.SetCursorPos(0); + + if (streamLoader(resource, file, parameters)) + return true; } + + NazaraWarning("Loader failed"); } NazaraError("Failed to load file: no loader"); @@ -95,17 +125,20 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS nzUInt64 streamPos = stream.GetCursorPos(); for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) { + StreamChecker checkFunc = std::get<1>(*loader); + StreamLoader streamLoader = std::get<2>(*loader); + stream.SetCursorPos(streamPos); // Le loader supporte-t-il les données ? - if (!std::get<1>(*loader)(stream, parameters)) + if (!checkFunc(stream, parameters)) continue; // On repositionne le stream à son ancienne position stream.SetCursorPos(streamPos); // Chargement de la ressource - if (std::get<2>(*loader)(resource, stream, parameters)) + if (streamLoader(resource, stream, parameters)) return true; NazaraWarning("Loader failed"); @@ -116,28 +149,31 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS } template -void NzResourceLoader::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) +void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) { - ///FIXME: Trouver une alternative à ce code monstrueux - std::vector exts; - fileExtensions.SplitAny(exts, " /\\.,;|-_"); + #if NAZARA_CORE_SAFE + if (streamLoader) + { + if (!checkFunc) + { + NazaraError("StreamLoader present without StreamChecker"); + return; + } + } + else if (!fileLoader) + { + NazaraError("Neither FileLoader nor StreamLoader were found"); + return; + } + #endif - std::set extensions; - std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); - - Type::s_loaders.push_front(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); + Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); } template -void NzResourceLoader::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) +void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) { - std::vector exts; - fileExtensions.SplitAny(exts, " /\\.,;|-_"); - - std::set extensions; - std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); - - Type::s_loaders.remove(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); + Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); } #include diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index dccf2d6cc..a9761aa74 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -12,13 +13,13 @@ #include #include #include +#include +#include #include #include namespace { - const char* supportedFormats = "aiff,au,avr,caf,flac,htk,ircam,mat4,mat5,mpc2k,nist,ogg,paf,pvf,raw,rf64,sd2,sds,svx,voc,w64,wav,wve"; - sf_count_t GetSize(void* user_data) { NzInputStream* stream = static_cast(user_data); @@ -66,12 +67,19 @@ namespace class sndfileStream : public NzSoundStream { public: - sndfileStream() = default; + sndfileStream() : + m_file(nullptr), + m_handle(nullptr) + { + } ~sndfileStream() { + if (m_handle) + sf_close(m_handle); + if (m_file) - sf_close(m_file); + delete m_file; } nzUInt32 GetDuration() const @@ -94,13 +102,25 @@ namespace return m_sampleRate; } + bool Open(const NzString& filePath) + { + m_file = new NzFile(filePath); + if (!m_file->Open(NzFile::ReadOnly)) + { + NazaraError("Failed to open file " + filePath); + return false; + } + + return Open(*m_file); + } + bool Open(NzInputStream& stream) { SF_INFO infos; - m_file = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); - if (!m_file) + m_handle = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); + if (!m_handle) { - NazaraError("Failed to open sound: " + NzString(sf_strerror(m_file))); + NazaraError("Failed to open sound: " + NzString(sf_strerror(m_handle))); return false; } @@ -108,8 +128,8 @@ namespace if (m_format == nzAudioFormat_Unknown) { NazaraError("Channel count not handled"); - sf_close(m_file); - m_file = nullptr; + sf_close(m_handle); + m_handle = nullptr; return false; } @@ -123,30 +143,40 @@ namespace // http://www.mega-nerd.com/libsndfile/command.html#SFC_SET_SCALE_FLOAT_INT_READ ///FIXME: Seulement le Vorbis ? /*if (infos.format & SF_FORMAT_VORBIS) - sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);*/ + sf_command(m_handle, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);*/ return true; } unsigned int Read(void* buffer, unsigned int sampleCount) { - return sf_read_short(m_file, reinterpret_cast(buffer), sampleCount); + return sf_read_short(m_handle, reinterpret_cast(buffer), sampleCount); } void Seek(nzUInt32 offset) { - sf_seek(m_file, offset*m_sampleRate / 1000, SEEK_SET); + sf_seek(m_handle, offset*m_sampleRate / 1000, SEEK_SET); } private: nzAudioFormat m_format; - SNDFILE* m_file = nullptr; + NzFile* m_file; + SNDFILE* m_handle; unsigned int m_duration; unsigned int m_sampleCount; unsigned int m_sampleRate; }; - bool NzLoader_sndfile_Check_Music(NzInputStream& stream, const NzMusicParams& parameters) + bool IsSupported(const NzString& extension) + { + static std::set supportedExtensions = { + "aiff", "au", "avr", "caf", "flac", "htk", "ircam", "mat4", "mat5", "mpc2k", + "nist","ogg", "pvf", "raw", "rf64", "sd2", "sds", "svx", "voc", "w64", "wav", "wve"}; + + return supportedExtensions.find(extension) != supportedExtensions.end(); + } + + bool CheckMusic(NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); @@ -161,31 +191,51 @@ namespace return false; } - bool NzLoader_sndfile_Load_Music(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) + bool LoadMusicFile(NzMusic* music, const NzString& filePath, const NzMusicParams& parameters) { NazaraUnused(parameters); - sndfileStream* musicStream = new sndfileStream; - if (!musicStream->Open(stream)) + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(filePath)) { - // L'erreur a déjà été signalée par la méthode - delete musicStream; - + NazaraError("Failed to open music stream"); return false; } - if (!music->Create(musicStream)) + if (!music->Create(musicStream.get())) { NazaraError("Failed to create music"); - delete musicStream; - return false; } + musicStream.release(); + return true; } - bool NzLoader_sndfile_Check_SoundBuffer(NzInputStream& stream, const NzSoundBufferParams& parameters) + bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(stream)) + { + NazaraError("Failed to open music stream"); + return false; + } + + if (!music->Create(musicStream.get())) + { + NazaraError("Failed to create music"); + return false; + } + + musicStream.release(); + + return true; + } + + bool CheckSoundBuffer(NzInputStream& stream, const NzSoundBufferParams& parameters) { NazaraUnused(parameters); @@ -200,7 +250,7 @@ namespace return false; } - bool NzLoader_sndfile_Load_SoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) + bool LoadSoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) { NazaraUnused(parameters); @@ -209,35 +259,32 @@ namespace return false; // L'erreur a déjà été envoyée par la méthode unsigned int sampleCount = musicStream.GetSampleCount(); - nzInt16* samples = new nzInt16[sampleCount]; - if (musicStream.Read(samples, sampleCount) != sampleCount) + std::unique_ptr samples(new nzInt16[sampleCount]); + + if (musicStream.Read(samples.get(), sampleCount) != sampleCount) { NazaraError("Failed to read samples"); return false; } - if (!soundBuffer->Create(musicStream.GetFormat(), sampleCount, musicStream.GetSampleRate(), samples)) + if (!soundBuffer->Create(musicStream.GetFormat(), sampleCount, musicStream.GetSampleRate(), samples.get())) { NazaraError("Failed to create sound buffer"); - delete[] samples; - return false; } - delete[] samples; - return true; } } void NzLoaders_sndfile_Register() { - NzMusicLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); - NzSoundBufferLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); + NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } void NzLoaders_sndfile_Unregister() { - NzMusicLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); - NzSoundBufferLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); + NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index 1c4a5b4df..ebb6837ad 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -20,7 +20,7 @@ struct NzMusicImpl ALenum audioFormat; std::vector chunkSamples; NzSoundStream* stream; - NzThread* thread = nullptr; + NzThread thread; bool loop = false; bool playing = false; bool paused = false; @@ -178,8 +178,7 @@ bool NzMusic::Play() }*/ m_impl->playing = true; - m_impl->thread = new NzThread(&NzMusic::MusicThread, this); - m_impl->thread->Launch(); + m_impl->thread = NzThread(&NzMusic::MusicThread, this); return true; } @@ -197,9 +196,7 @@ void NzMusic::Stop() if (m_impl->playing) { m_impl->playing = false; - m_impl->thread->Join(); - delete m_impl->thread; - m_impl->thread = nullptr; + m_impl->thread.Join(); } } diff --git a/src/Nazara/Renderer/Loaders/Texture/Loader.cpp b/src/Nazara/Renderer/Loaders/Texture/Loader.cpp index 902609f87..a3688083c 100644 --- a/src/Nazara/Renderer/Loaders/Texture/Loader.cpp +++ b/src/Nazara/Renderer/Loaders/Texture/Loader.cpp @@ -38,11 +38,10 @@ namespace void NzLoaders_Texture_Register() { - ///FIXME: Pas bon - NzMaterialLoader::RegisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzMaterialLoader::RegisterLoader(NzImageLoader::IsExtensionSupported, Check, Load); } void NzLoaders_Texture_Unregister() { - NzMaterialLoader::UnregisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzMaterialLoader::UnregisterLoader(NzImageLoader::IsExtensionSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index c4cc78ce8..c1532550c 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -19,7 +19,11 @@ namespace { - /// Loader de mesh + bool IsSupported(const NzString& extension) + { + return (extension == "md2"); + } + bool CheckMesh(NzInputStream& stream, const NzMeshParams& parameters) { NazaraUnused(parameters); @@ -330,12 +334,12 @@ namespace void NzLoaders_MD2_Register() { - NzAnimationLoader::RegisterLoader("md2", CheckAnim, LoadAnim); - NzMeshLoader::RegisterLoader("md2", CheckMesh, LoadMesh); + NzAnimationLoader::RegisterLoader(IsSupported, CheckAnim, LoadAnim); + NzMeshLoader::RegisterLoader(IsSupported, CheckMesh, LoadMesh); } void NzLoaders_MD2_Unregister() { - NzAnimationLoader::UnregisterLoader("md2", CheckAnim, LoadAnim); - NzMeshLoader::UnregisterLoader("md2", CheckMesh, LoadMesh); + NzAnimationLoader::UnregisterLoader(IsSupported, CheckAnim, LoadAnim); + NzMeshLoader::UnregisterLoader(IsSupported, CheckMesh, LoadMesh); } diff --git a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp index 58d9dba49..f48192e95 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp @@ -8,6 +8,11 @@ namespace { + bool IsSupported(const NzString& extension) + { + return (extension == "md5anim"); + } + bool Check(NzInputStream& stream, const NzAnimationParams& parameters) { NzMD5AnimParser parser(stream, parameters); @@ -23,10 +28,10 @@ namespace void NzLoaders_MD5Anim_Register() { - NzAnimationLoader::RegisterLoader("md5anim", Check, Load); + NzAnimationLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_MD5Anim_Unregister() { - NzAnimationLoader::UnregisterLoader("md5anim", Check, Load); + NzAnimationLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp index c4f84c578..a9848c65f 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp @@ -8,6 +8,11 @@ namespace { + bool IsSupported(const NzString& extension) + { + return (extension == "md5mesh"); + } + bool Check(NzInputStream& stream, const NzMeshParams& parameters) { NzMD5MeshParser parser(stream, parameters); @@ -23,10 +28,10 @@ namespace void NzLoaders_MD5Mesh_Register() { - NzMeshLoader::RegisterLoader("md5mesh", Check, Load); + NzMeshLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_MD5Mesh_Unregister() { - NzMeshLoader::UnregisterLoader("md5mesh", Check, Load); + NzMeshLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/PCX/Loader.cpp b/src/Nazara/Utility/Loaders/PCX/Loader.cpp index ee9a20cbc..579b9ca6f 100644 --- a/src/Nazara/Utility/Loaders/PCX/Loader.cpp +++ b/src/Nazara/Utility/Loaders/PCX/Loader.cpp @@ -39,6 +39,11 @@ namespace //static_assert(sizeof(pcx_header) == 1024, "PCX header must be 1024 bytes sized"); + bool IsSupported(const NzString& extension) + { + return (extension == "pcx"); + } + bool Check(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -339,10 +344,10 @@ namespace void NzLoaders_PCX_Register() { - NzImageLoader::RegisterLoader("pcx", Check, Load); + NzImageLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_PCX_Unregister() { - NzImageLoader::UnregisterLoader("pcx", Check, Load); + NzImageLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/STB/Loader.cpp b/src/Nazara/Utility/Loaders/STB/Loader.cpp index 6baad965a..7b75d33c7 100644 --- a/src/Nazara/Utility/Loaders/STB/Loader.cpp +++ b/src/Nazara/Utility/Loaders/STB/Loader.cpp @@ -37,6 +37,12 @@ namespace static stbi_io_callbacks callbacks = {Read, Skip, Eof}; + bool IsSupported(const NzString& extension) + { + static std::set supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "psd", "tga"}; + return supportedExtensions.find(extension) != supportedExtensions.end(); + } + bool Check(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -117,10 +123,10 @@ namespace void NzLoaders_STB_Register() { - NzImageLoader::RegisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzImageLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_STB_Unregister() { - NzImageLoader::UnregisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzImageLoader::UnregisterLoader(IsSupported, Check, Load); }