FileSystem: Fix file lookup if unrelated files with same name exist

Before, even though we did match all possible extensions,
we only took the first match and tried opening it.
If we were looking for a .png image, but there was an unrelated
.txt file with the same name (as it actually happens in RTPs),
we would potentially see the .txt first, try opening it,
and fail alltogether, even though the image file existed.

Now we try opening all matching files until we find one that
we can parse.

This fixes #101.
This commit is contained in:
Jonas Kulla 2015-07-09 13:00:56 +02:00
parent 533e69275a
commit 54c1107f19
5 changed files with 399 additions and 325 deletions

View file

@ -184,6 +184,44 @@ void SoundEmitter::stop()
AL::Source::stop(alSrcs[i]);
}
struct SoundOpenHandler : FileSystem::OpenHandler
{
SoundBuffer *buffer;
SoundOpenHandler()
: buffer(0)
{}
bool tryRead(SDL_RWops &ops, const char *ext)
{
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
if (!sample)
{
SDL_RWclose(&ops);
return false;
}
/* Do all of the decoding in the handler so we don't have
* to keep the source ops around */
uint32_t decBytes = Sound_DecodeAll(sample);
uint8_t sampleSize = formatSampleSize(sample->actual.format);
uint32_t sampleCount = decBytes / sampleSize;
buffer = new SoundBuffer;
buffer->bytes = sampleSize * sampleCount;
ALenum alFormat = chooseALFormat(sampleSize, sample->actual.channels);
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sample->buffer,
buffer->bytes, sample->actual.rate);
Sound_FreeSample(sample);
return true;
}
};
SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
{
SoundBuffer *buffer = bufferHash.value(filename, 0);
@ -199,40 +237,22 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
}
else
{
/* Buffer not in cashe, needs to be loaded */
SDL_RWops dataSource;
char ext[8];
/* Buffer not in cache, needs to be loaded */
SoundOpenHandler handler;
shState->fileSystem().openRead(handler, filename.c_str());
buffer = handler.buffer;
shState->fileSystem().openRead(dataSource, filename.c_str(),
false, ext, sizeof(ext));
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, ext, 0, STREAM_BUF_SIZE);
if (!sampleHandle)
if (!buffer)
{
char buf[512];
snprintf(buf, sizeof(buf), "Unable to decode sound: %s.%s: %s",
filename.c_str(), ext, Sound_GetError());
snprintf(buf, sizeof(buf), "Unable to decode sound: %s: %s",
filename.c_str(), Sound_GetError());
Debug() << buf;
return 0;
}
uint32_t decBytes = Sound_DecodeAll(sampleHandle);
uint8_t sampleSize = formatSampleSize(sampleHandle->actual.format);
uint32_t sampleCount = decBytes / sampleSize;
buffer = new SoundBuffer;
buffer->key = filename;
buffer->bytes = sampleSize * sampleCount;
ALenum alFormat = chooseALFormat(sampleSize, sampleHandle->actual.channels);
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sampleHandle->buffer,
buffer->bytes, sampleHandle->actual.rate);
Sound_FreeSample(sampleHandle);
uint32_t wouldBeBytes = bufferBytes + buffer->bytes;
/* If memory limit is reached, delete lowest priority buffer