Fixed streaming loaders when used with memory streams

Former-commit-id: ce39ee03f40682c00c78b08ac285b9ea36240fa5
This commit is contained in:
Lynix 2015-01-17 23:42:49 +01:00
parent 9f40fe12b1
commit c02fe6c8ff
4 changed files with 150 additions and 20 deletions

View File

@ -20,6 +20,7 @@ class NzResourceLoader
public: public:
using ExtensionGetter = bool (*)(const NzString& extension); using ExtensionGetter = bool (*)(const NzString& extension);
using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters);
using MemoryLoader = bool (*)(Type* resource, const void* data, std::size_t size, const Parameters& parameters);
using StreamChecker = nzTernary (*)(NzInputStream& stream, const Parameters& parameters); using StreamChecker = nzTernary (*)(NzInputStream& stream, const Parameters& parameters);
using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters);
@ -29,10 +30,10 @@ class NzResourceLoader
static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, 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 bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters());
static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr);
static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr);
using Loader = std::tuple<ExtensionGetter, StreamChecker, StreamLoader, FileLoader>; using Loader = std::tuple<ExtensionGetter, StreamChecker, StreamLoader, FileLoader, MemoryLoader>;
using LoaderList = std::list<Loader>; using LoaderList = std::list<Loader>;
}; };

View File

@ -117,9 +117,77 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters)
{ {
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
if (size == 0)
{
NazaraError("No data to load");
return false;
}
#endif
NzMemoryStream stream(data, size); NzMemoryStream stream(data, size);
return LoadFromStream(resource, stream, parameters); bool found = false;
for (Loader& loader : Type::s_loaders)
{
StreamChecker checkFunc = std::get<1>(loader);
StreamLoader streamLoader = std::get<2>(loader);
MemoryLoader memoryLoader = std::get<4>(loader);
nzTernary recognized = nzTernary_Unknown;
if (memoryLoader)
{
if (checkFunc)
{
stream.SetCursorPos(0);
recognized = checkFunc(stream, parameters);
if (recognized == nzTernary_False)
continue;
else
found = true;
}
else
{
recognized = nzTernary_Unknown;
found = true;
}
if (memoryLoader(resource, data, size, parameters))
return true;
}
else
{
stream.SetCursorPos(0);
recognized = checkFunc(stream, parameters);
if (recognized == nzTernary_False)
continue;
else if (recognized == nzTernary_True)
found = true;
stream.SetCursorPos(0);
if (streamLoader(resource, stream, parameters))
return true;
}
if (recognized == nzTernary_True)
NazaraWarning("Loader failed");
}
if (found)
NazaraError("Failed to load file: all loaders failed");
else
NazaraError("Failed to load file: no loader found");
return false;
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
@ -175,7 +243,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) void NzResourceLoader<Type, Parameters>::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
{ {
#if NAZARA_CORE_SAFE #if NAZARA_CORE_SAFE
if (streamLoader) if (streamLoader)
@ -186,20 +254,20 @@ void NzResourceLoader<Type, Parameters>::RegisterLoader(ExtensionGetter extensio
return; return;
} }
} }
else if (!fileLoader) else if (!fileLoader && !memoryLoader)
{ {
NazaraError("Neither FileLoader nor StreamLoader were present"); NazaraError("Neither FileLoader nor MemoryLoader nor StreamLoader were present");
return; return;
} }
#endif #endif
Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader));
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) void NzResourceLoader<Type, Parameters>::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
{ {
Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader));
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -106,13 +106,21 @@ namespace
bool Open(const NzString& filePath, bool forceMono) bool Open(const NzString& filePath, bool forceMono)
{ {
if (!m_file.Open(filePath, NzFile::ReadOnly)) std::unique_ptr<NzFile> file(new NzFile);
if (!file->Open(filePath, NzFile::ReadOnly))
{ {
NazaraError("Failed to open stream from file: " + NzError::GetLastError()); NazaraError("Failed to open stream from file: " + NzError::GetLastError());
return false; return false;
} }
m_ownedStream = std::move(file);
return Open(m_file, forceMono); return Open(*m_ownedStream, forceMono);
}
bool Open(const void* data, std::size_t size, bool forceMono)
{
m_ownedStream.reset(new NzMemoryStream(data, size));
return Open(*m_ownedStream, forceMono);
} }
bool Open(NzInputStream& stream, bool forceMono) bool Open(NzInputStream& stream, bool forceMono)
@ -185,8 +193,8 @@ namespace
private: private:
std::vector<nzInt16> m_mixBuffer; std::vector<nzInt16> m_mixBuffer;
std::unique_ptr<NzInputStream> m_ownedStream;
nzAudioFormat m_format; nzAudioFormat m_format;
NzFile m_file;
SNDFILE* m_handle; SNDFILE* m_handle;
bool m_mixToMono; bool m_mixToMono;
unsigned int m_duration; unsigned int m_duration;
@ -243,6 +251,28 @@ namespace
return true; return true;
} }
bool LoadMusicMemory(NzMusic* music, const void* data, std::size_t size, const NzMusicParams& parameters)
{
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(data, size, parameters.forceMono))
{
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 LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters)
{ {
NazaraUnused(parameters); NazaraUnused(parameters);
@ -342,12 +372,12 @@ namespace
void NzLoaders_sndfile_Register() void NzLoaders_sndfile_Register()
{ {
NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory);
NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer);
} }
void NzLoaders_sndfile_Unregister() void NzLoaders_sndfile_Unregister()
{ {
NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile, LoadMusicMemory);
NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer);
} }

View File

@ -9,6 +9,7 @@
#include FT_OUTLINE_H #include FT_OUTLINE_H
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Utility/Font.hpp> #include <Nazara/Utility/Font.hpp>
#include <Nazara/Utility/FontData.hpp> #include <Nazara/Utility/FontData.hpp>
#include <Nazara/Utility/FontGlyph.hpp> #include <Nazara/Utility/FontGlyph.hpp>
@ -260,16 +261,24 @@ namespace
bool SetFile(const NzString& filePath) bool SetFile(const NzString& filePath)
{ {
if (!m_file.Open(filePath, NzFile::ReadOnly)) std::unique_ptr<NzFile> file(new NzFile);
if (!file->Open(filePath, NzFile::ReadOnly))
{ {
NazaraError("Failed to open stream from file: " + NzError::GetLastError()); NazaraError("Failed to open stream from file: " + NzError::GetLastError());
return false; return false;
} }
m_ownedStream = std::move(file);
SetStream(m_file); SetStream(*m_ownedStream);
return true; return true;
} }
void SetMemory(const void* data, std::size_t size)
{
m_ownedStream.reset(new NzMemoryStream(data, size));
SetStream(*m_ownedStream);
}
void SetStream(NzInputStream& stream) void SetStream(NzInputStream& stream)
{ {
m_stream.base = nullptr; m_stream.base = nullptr;
@ -303,7 +312,7 @@ namespace
FT_Open_Args m_args; FT_Open_Args m_args;
FT_Face m_face; FT_Face m_face;
FT_StreamRec m_stream; FT_StreamRec m_stream;
NzFile m_file; std::unique_ptr<NzInputStream> m_ownedStream;
mutable unsigned int m_characterSize; mutable unsigned int m_characterSize;
}; };
@ -357,6 +366,28 @@ namespace
return false; return false;
} }
bool LoadMemory(NzFont* font, const void* data, std::size_t size, const NzFontParams& parameters)
{
NazaraUnused(parameters);
std::unique_ptr<FreeTypeStream> face(new FreeTypeStream);
face->SetMemory(data, size);
if (!face->Open())
{
NazaraError("Failed to open face");
return false;
}
if (font->Create(face.get()))
{
face.release();
return true;
}
else
return false;
}
bool LoadStream(NzFont* font, NzInputStream& stream, const NzFontParams& parameters) bool LoadStream(NzFont* font, NzInputStream& stream, const NzFontParams& parameters)
{ {
NazaraUnused(parameters); NazaraUnused(parameters);
@ -383,7 +414,7 @@ namespace
void NzLoaders_FreeType_Register() void NzLoaders_FreeType_Register()
{ {
if (FT_Init_FreeType(&s_library) == 0) if (FT_Init_FreeType(&s_library) == 0)
NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile); NzFontLoader::RegisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory);
else else
{ {
s_library = nullptr; // On s'assure que le pointeur ne pointe pas sur n'importe quoi s_library = nullptr; // On s'assure que le pointeur ne pointe pas sur n'importe quoi
@ -395,7 +426,7 @@ void NzLoaders_FreeType_Unregister()
{ {
if (s_library) if (s_library)
{ {
NzFontLoader::UnregisterLoader(IsSupported, Check, LoadStream, LoadFile); NzFontLoader::UnregisterLoader(IsSupported, Check, LoadStream, LoadFile, LoadMemory);
FT_Done_FreeType(s_library); FT_Done_FreeType(s_library);
s_library = nullptr; s_library = nullptr;