fmod: Fallback to opening file via callbacks if direct doesn't work

Fixes #1002
This commit is contained in:
rdb 2020-09-01 10:41:34 +02:00
parent ab6bf5f4f7
commit 1cc82f47b6

View File

@ -123,50 +123,62 @@ FmodAudioSound(AudioManager *manager, VirtualFile *file, bool positional) {
<< "Reading " << _file_name << " into memory (" << sound_info.length
<< " bytes)\n";
}
} else if (file->get_system_info(info)) {
// The file exists on disk (or it's part of a multifile that exists on
// disk), so we can have FMod read the file directly. This is also
// safe, because FMod uses its own IO operations that don't involve
// Panda, so this can safely happen in an FMod thread.
os_filename = info.get_filename().to_os_specific();
name_or_data = os_filename.c_str();
sound_info.fileoffset = (unsigned int)info.get_start();
sound_info.length = (unsigned int)info.get_size();
flags |= FMOD_CREATESTREAM;
if (fmodAudio_cat.is_debug()) {
fmodAudio_cat.debug()
<< "Streaming " << _file_name << " from disk (" << name_or_data
<< ", " << sound_info.fileoffset << ", " << sound_info.length << ")\n";
}
} else {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
// Otherwise, if the Panda threading system is compiled in, we can
// assign callbacks to read the file through the VFS.
name_or_data = (const char *)file;
sound_info.length = (unsigned int)info.get_size();
sound_info.useropen = open_callback;
sound_info.userclose = close_callback;
sound_info.userread = read_callback;
sound_info.userseek = seek_callback;
flags |= FMOD_CREATESTREAM;
if (fmodAudio_cat.is_debug()) {
fmodAudio_cat.debug()
<< "Streaming " << _file_name << " from disk using callbacks\n";
}
#else // HAVE_THREADS && !SIMPLE_THREADS
// Without threads, we can't safely read this file.
name_or_data = "";
fmodAudio_cat.warning()
<< "Cannot stream " << _file_name << "; file is not literally on disk.\n";
#endif
result =
_manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
}
else {
result = FMOD_ERR_FILE_BAD;
result =
_manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
if (file->get_system_info(info)) {
// The file exists on disk (or it's part of a multifile that exists on
// disk), so we can have FMod read the file directly. This is also
// safe, because FMod uses its own IO operations that don't involve
// Panda, so this can safely happen in an FMod thread.
os_filename = info.get_filename().to_os_specific();
name_or_data = os_filename.c_str();
sound_info.fileoffset = (unsigned int)info.get_start();
sound_info.length = (unsigned int)info.get_size();
flags |= FMOD_CREATESTREAM;
if (fmodAudio_cat.is_debug()) {
fmodAudio_cat.debug()
<< "Streaming " << _file_name << " from disk (" << name_or_data
<< ", " << sound_info.fileoffset << ", " << sound_info.length << ")\n";
}
result =
_manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
}
// If FMOD can't directly read the file (eg. if Panda is locking it for
// write, or it's compressed) we have to use the callback interface.
if (result == FMOD_ERR_FILE_BAD) {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
// Otherwise, if the Panda threading system is compiled in, we can
// assign callbacks to read the file through the VFS.
name_or_data = (const char *)file;
sound_info.fileoffset = 0;
sound_info.length = (unsigned int)info.get_size();
sound_info.useropen = open_callback;
sound_info.userclose = close_callback;
sound_info.userread = read_callback;
sound_info.userseek = seek_callback;
flags |= FMOD_CREATESTREAM;
if (fmodAudio_cat.is_debug()) {
fmodAudio_cat.debug()
<< "Streaming " << _file_name << " from disk using callbacks\n";
}
result =
_manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
#else // HAVE_THREADS && !SIMPLE_THREADS
// Without threads, we can't safely read this file.
name_or_data = "";
fmodAudio_cat.warning()
<< "Cannot stream " << _file_name << "; file is not literally on disk.\n";
#endif
}
}
}
if (result != FMOD_OK) {