use search path, vfs, fix dangling pointer references

This commit is contained in:
David Rose 2003-02-07 15:30:16 +00:00
parent 6e23b43ef3
commit 03c8de6eae
2 changed files with 69 additions and 54 deletions

View File

@ -27,12 +27,11 @@
#include "fmodAudioManager.h" #include "fmodAudioManager.h"
#include "fmodAudioSound.h" #include "fmodAudioSound.h"
#include "nullAudioSound.h" #include "nullAudioSound.h"
#include "virtualFileSystem.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <fmod.h> #include <fmod.h>
#include <iostream>
using std::cerr;
PT(AudioManager) Create_AudioManager() { PT(AudioManager) Create_AudioManager() {
audio_debug("Create_AudioManager() Fmod."); audio_debug("Create_AudioManager() Fmod.");
@ -131,6 +130,13 @@ get_sound(const string &file_name) {
assert(is_valid()); assert(is_valid());
Filename path = file_name; Filename path = file_name;
if (use_vfs) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
vfs->resolve_filename(path, get_sound_path());
} else {
path.resolve_filename(get_sound_path());
}
audio_debug(" resolved file_name is '"<<path<<"'"); audio_debug(" resolved file_name is '"<<path<<"'");
// Get the sound, either from the cache or from disk. // Get the sound, either from the cache or from disk.
@ -143,11 +149,6 @@ get_sound(const string &file_name) {
} else { } else {
// The sound was not found in the cache. Load it from disk. // The sound was not found in the cache. Load it from disk.
SoundCacheEntry new_entry; SoundCacheEntry new_entry;
new_entry.size = get_file_size(path);
if (new_entry.size == 0) {
audio_error("FmodAudioManager::get_file_size failed.");
return 0;
}
new_entry.data = load(path, new_entry.size); new_entry.data = load(path, new_entry.size);
if (!new_entry.data) { if (!new_entry.data) {
audio_error("FmodAudioManager::load failed."); audio_error("FmodAudioManager::load failed.");
@ -157,8 +158,13 @@ get_sound(const string &file_name) {
new_entry.stale = true; new_entry.stale = true;
// Add to the cache // Add to the cache
entry = &new_entry; si = _sounds.insert(SoundMap::value_type(path, new_entry)).first;
_sounds[path] = new_entry;
// It's important that we assign entry to the address of the entry
// we just added to the map, and not to the address of the
// temporary variable new_entry, which we just defined locally and
// is about to go out of scope.
entry = &(*si).second;
} }
assert(entry != NULL); assert(entry != NULL);
@ -224,7 +230,7 @@ uncache_sound(const string& file_name) {
// purged right now! // purged right now!
SoundCacheEntry *entry = &(*itor).second; SoundCacheEntry *entry = &(*itor).second;
if (entry->refcount == 0) { if (entry->refcount == 0) {
audio_debug("FmodAudioManager::dec_refcount: purging "<<path audio_debug("FmodAudioManager::uncache_sound: purging "<<path
<< " from the cache."); << " from the cache.");
delete [] entry->data; delete [] entry->data;
_sounds.erase(itor); _sounds.erase(itor);
@ -244,17 +250,22 @@ void FmodAudioManager::
clear_cache() { clear_cache() {
// Mark all cache entries as stale. Delete those which already have // Mark all cache entries as stale. Delete those which already have
// refcounts of zero. // refcounts of zero.
SoundMap::iterator itor = _sounds.begin(); SoundMap::iterator itor = _sounds.begin();
for( ; itor != _sounds.end(); ++itor) {
// Have to use a while loop, not a for loop, since we don't want to
// increment itor in the case in which we delete an entry.
while (itor != _sounds.end()) {
SoundCacheEntry *entry = &(*itor).second; SoundCacheEntry *entry = &(*itor).second;
if (entry->refcount == 0) { if (entry->refcount == 0) {
audio_debug("FmodAudioManager: purging "<< (*itor).first audio_debug("FmodAudioManager::clear_cache: purging "<< (*itor).first
<< " from the cache."); << " from the cache.");
delete [] entry->data; delete [] entry->data;
_sounds.erase(itor); _sounds.erase(itor);
itor = _sounds.begin(); itor = _sounds.begin();
} else { } else {
entry->stale = true; entry->stale = true;
++itor;
} }
} }
} }
@ -394,7 +405,7 @@ dec_refcount(const string& file_name) {
audio_debug("FmodAudioManager: "<<path<<" has a refcount of " audio_debug("FmodAudioManager: "<<path<<" has a refcount of "
<< entry->refcount); << entry->refcount);
if (entry->refcount == 0 && entry->stale) { if (entry->refcount == 0 && entry->stale) {
audio_debug("FmodAudioManager: purging "<<path<< " from the cache."); audio_debug("FmodAudioManager::dec_refcount: purging "<<path<< " from the cache.");
delete [] entry->data; delete [] entry->data;
_sounds.erase(itor); _sounds.erase(itor);
} }
@ -406,11 +417,12 @@ dec_refcount(const string& file_name) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::load // Function: FmodAudioManager::load
// Access: Private // Access: Private
// Description: Loads the specified file into memory. // Description: Loads the specified file into memory. Returns a
// Returns NULL if an error occurs. // newly-allocated buffer, and stores the size of the
// buffer in size. Returns NULL if an error occurs.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void* FmodAudioManager:: void* FmodAudioManager::
load(const Filename& filename, const size_t size) const { load(const Filename& filename, size_t &size) const {
// Check file type (based on filename suffix // Check file type (based on filename suffix
string suffix = filename.get_extension(); string suffix = filename.get_extension();
std::transform(suffix.begin(), suffix.end(), suffix.begin(), tolower); std::transform(suffix.begin(), suffix.end(), suffix.begin(), tolower);
@ -427,56 +439,60 @@ load(const Filename& filename, const size_t size) const {
} }
// open the file. // open the file.
string os_filename = filename.to_os_specific(); istream *audioFile = NULL;
FILE *audioFile = fopen(os_filename.c_str(), "rb");
if (!audioFile) { Filename binary_filename = Filename::binary_filename(filename);
audio_error("File "<<filename<<" does not exist."); if (use_vfs) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
if (!vfs->exists(filename)) {
audio_error("File " << filename << " does not exist.");
return NULL; return NULL;
} }
audioFile = vfs->open_read_file(binary_filename);
} else {
if (!filename.exists()) {
audio_error("File " << filename << " does not exist.");
return NULL;
}
audioFile = new ifstream;
if (!binary_filename.open_read(*(ifstream *)audioFile)) {
delete audioFile;
audioFile = NULL;
}
}
if (audioFile == (istream *)NULL) {
// Unable to open.
audio_error("Unable to read " << filename << ".");
return NULL;
}
// Determine the file size.
audioFile->seekg(0, ios::end);
size = (size_t)audioFile->tellg();
audioFile->seekg(0, ios::beg);
// Read the entire file into memory. // Read the entire file into memory.
char *buffer = new char[size]; char *buffer = new char[size];
if (buffer == NULL) { if (buffer == NULL) {
audio_error("out-of-memory error while loading "<<filename); audio_error("out-of-memory error while loading "<<filename);
fclose(audioFile); delete audioFile;
return NULL; return NULL;
} }
long bytes_read = fread(buffer, size, 1, audioFile); audioFile->read(buffer, size);
if (bytes_read != 1) { if (!(*audioFile)) {
audio_error("Read error while loading "<<filename); audio_error("Read error while loading "<<filename);
fclose(audioFile); delete audioFile;
delete [] buffer; delete [] buffer;
return NULL; return NULL;
} }
fclose(audioFile); delete audioFile;
return buffer; return buffer;
} }
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::get_file_size
// Access: Private
// Description: Calculates the size of the given file, in bytes.
////////////////////////////////////////////////////////////////////
size_t FmodAudioManager::
get_file_size(const Filename& filename) const {
// open the file.
string os_filename = filename.to_os_specific();
FILE *audioFile = fopen(os_filename.c_str(), "rb");
if (!audioFile) {
audio_error("File "<<filename<<" does not exist.");
return 0;
}
// Read the entire file into memory.
if (fseek(audioFile, 0, SEEK_END) != 0) {
audio_error("Seek error while loading "<<filename);
fclose(audioFile);
return 0;
}
size_t file_size = ftell(audioFile);
fclose(audioFile);
return file_size;
}
#endif //] #endif //]

View File

@ -80,8 +80,7 @@ private:
bool _is_valid; bool _is_valid;
bool _active; bool _active;
void* load(const Filename& filename, const size_t size) const; void* load(const Filename& filename, size_t &size) const;
size_t get_file_size(const Filename& filename) const;
friend FmodAudioSound; friend FmodAudioSound;
}; };