mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
fix fmod threading issues
This commit is contained in:
parent
8fd5dff01c
commit
5b2c80e5f3
@ -29,6 +29,14 @@ ConfigureFn(config_fmodAudio) {
|
||||
init_libFmodAudio();
|
||||
}
|
||||
|
||||
ConfigVariableInt fmod_audio_preload_threshold
|
||||
("fmod-audio-preload-threshold", 1048576,
|
||||
PRC_DESC("Files that are smaller "
|
||||
"than this number of bytes will be preloaded and kept "
|
||||
"resident in memory, while files that are this size or larger "
|
||||
"will be streamed from disk. Set this to -1 to preload "
|
||||
"every file."));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libFmodAudio
|
||||
// Description: Initializes the library. This must be called at
|
||||
|
@ -46,9 +46,8 @@ ConfigVariableInt miles_audio_expand_mp3_threshold
|
||||
|
||||
ConfigVariableInt miles_audio_preload_threshold
|
||||
("miles-audio-preload-threshold", -1,
|
||||
PRC_DESC("This is the last Miles fallback size, and should be no smaller "
|
||||
"than both miles-audio-expand-mp3-threshold and "
|
||||
"miles-audio-calc-mp3-threshold. Files that are smaller "
|
||||
PRC_DESC("This should be no smaller "
|
||||
"than miles-audio-expand-mp3-threshold. Files that are smaller "
|
||||
"than this number of bytes will be preloaded and kept "
|
||||
"resident in memory, while files that are this size or larger "
|
||||
"will be streamed from disk. Set this to -1 to preload "
|
||||
|
@ -142,13 +142,6 @@ FmodAudioManager() {
|
||||
if (_system_is_valid) {
|
||||
result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor);
|
||||
fmod_audio_errcheck("_system->set3DSettings()", result);
|
||||
|
||||
#if (FMOD_VERSION >= 0x00043100) // FMod 4.31.00 changed this API
|
||||
result = _system->setFileSystem(open_callback, close_callback, read_callback, seek_callback, 0, 0, -1);
|
||||
#else
|
||||
result = _system->setFileSystem(open_callback, close_callback, read_callback, seek_callback, -1);
|
||||
#endif
|
||||
fmod_audio_errcheck("_system->setFileSystem()", result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -833,97 +826,4 @@ get_cache_limit() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::open_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
open_callback(const char *name, int, unsigned int *file_size,
|
||||
void **handle, void **user_data) {
|
||||
if (name == (const char *)NULL || name[0] == '\0') {
|
||||
// An invalid attempt to open an unnamed file.
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
PT(VirtualFile) file = vfs->get_file(Filename(name));
|
||||
if (file == (VirtualFile *)NULL) {
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
istream *str = file->open_read_file(true);
|
||||
|
||||
(*file_size) = file->get_file_size(str);
|
||||
(*handle) = (void *)str;
|
||||
(*user_data) = NULL;
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::close_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
close_callback(void *handle, void *user_data) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
istream *str = (istream *)handle;
|
||||
vfs->close_read_file(str);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::read_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data) {
|
||||
istream *str = (istream *)handle;
|
||||
str->read((char *)buffer, size_bytes);
|
||||
(*bytes_read) = str->gcount();
|
||||
|
||||
// We can't yield here, since this callback is made within a
|
||||
// sub-thread--an OS-level sub-thread spawned by FMod, not a Panda
|
||||
// thread.
|
||||
//thread_consider_yield();
|
||||
|
||||
if (str->eof()) {
|
||||
if ((*bytes_read) == 0) {
|
||||
return FMOD_ERR_FILE_EOF;
|
||||
} else {
|
||||
// Report the EOF next time.
|
||||
return FMOD_OK;
|
||||
}
|
||||
} if (str->fail()) {
|
||||
return FMOD_ERR_FILE_BAD;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::seek_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioManager::
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data) {
|
||||
istream *str = (istream *)handle;
|
||||
str->clear();
|
||||
str->seekg(pos);
|
||||
|
||||
if (str->fail() && !str->eof()) {
|
||||
return FMOD_ERR_FILE_COULDNOTSEEK;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //]
|
||||
|
@ -164,20 +164,6 @@ class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
open_callback(const char *name, int unicode, unsigned int *file_size,
|
||||
void **handle, void **user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
close_callback(void *handle, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data);
|
||||
|
||||
FMOD::DSP *make_dsp(const FilterProperties::FilterConfig &conf);
|
||||
void update_dsp_chain(FMOD::DSP *head, FilterProperties *config);
|
||||
virtual bool configure_filters(FilterProperties *config);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "config_audio.h"
|
||||
#include "fmodAudioSound.h"
|
||||
#include "string_utils.h"
|
||||
#include "fileSystemInfo.h"
|
||||
|
||||
TypeHandle FmodAudioSound::_type_handle;
|
||||
|
||||
@ -71,46 +72,119 @@ FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) {
|
||||
|
||||
_channel = 0;
|
||||
_file_name = file_name;
|
||||
|
||||
FMOD_CREATESOUNDEXINFO *sound_info = NULL;
|
||||
_file_name.set_binary();
|
||||
|
||||
//Get the Speaker Mode [Important for later on.]
|
||||
result = _manager->_system->getSpeakerMode( &_speakermode );
|
||||
fmod_audio_errcheck("_system->getSpeakerMode()", result);
|
||||
|
||||
// Calculate the approximate uncompressed size of the sound.
|
||||
int size = file_name.get_file_size();
|
||||
string ext = downcase(file_name.get_extension());
|
||||
if (ext != "wav") size *= 10;
|
||||
|
||||
int flag = positional ? FMOD_3D : FMOD_2D;
|
||||
int streamflag = (size > 250000) ? FMOD_CREATESTREAM : FMOD_CREATESAMPLE;
|
||||
if (ext == "mid") {
|
||||
streamflag = FMOD_CREATESTREAM;
|
||||
sound_info = &_manager->_midi_info;
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
PT(VirtualFile) file = vfs->get_file(_file_name);
|
||||
if (file == (VirtualFile *)NULL) {
|
||||
// File not found. We will display the appropriate error message
|
||||
// below.
|
||||
result = FMOD_ERR_FILE_NOTFOUND;
|
||||
|
||||
} else {
|
||||
bool preload = (fmod_audio_preload_threshold < 0) || (file->get_file_size() < fmod_audio_preload_threshold);
|
||||
int flags = FMOD_SOFTWARE;
|
||||
flags |= positional ? FMOD_3D : FMOD_2D;
|
||||
|
||||
if (sound_info->dlsname != NULL) {
|
||||
audio_debug("Using DLS file " << sound_info->dlsname);
|
||||
FMOD_CREATESOUNDEXINFO sound_info;
|
||||
memset(&sound_info, 0, sizeof(sound_info));
|
||||
sound_info.cbsize = sizeof(sound_info);
|
||||
|
||||
string ext = downcase(_file_name.get_extension());
|
||||
if (ext == "mid") {
|
||||
// Get the MIDI parameters.
|
||||
memcpy(&sound_info, &_manager->_midi_info, sizeof(sound_info));
|
||||
if (sound_info.dlsname != NULL) {
|
||||
audio_debug("Using DLS file " << sound_info.dlsname);
|
||||
}
|
||||
}
|
||||
|
||||
const char *name_or_data = _file_name.c_str();
|
||||
|
||||
pvector<unsigned char> mem_buffer;
|
||||
FileSystemInfo info;
|
||||
if (preload) {
|
||||
// Pre-read the file right now, and pass it in as a memory
|
||||
// buffer. This avoids threading issues completely, because all
|
||||
// of the reading happens right here.
|
||||
file->read_file(mem_buffer, true);
|
||||
sound_info.length = mem_buffer.size();
|
||||
if (mem_buffer.size() != 0) {
|
||||
name_or_data = (const char *)&mem_buffer[0];
|
||||
}
|
||||
flags |= FMOD_OPENMEMORY;
|
||||
if (fmodAudio_cat.is_debug()) {
|
||||
fmodAudio_cat.debug()
|
||||
<< "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 I/O operations
|
||||
// that don't involve Panda, so this can safely happen in an
|
||||
// FMod thread.
|
||||
name_or_data = info.get_os_file_name().c_str();
|
||||
sound_info.fileoffset = (unsigned int)info.get_file_start();
|
||||
sound_info.length = (unsigned int)info.get_file_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.p();
|
||||
sound_info.length = (unsigned int)info.get_file_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);
|
||||
}
|
||||
|
||||
result = _manager->_system->createSound( file_name.c_str(), FMOD_SOFTWARE | streamflag | flag ,
|
||||
sound_info, &_sound);
|
||||
|
||||
if (result != FMOD_OK) {
|
||||
audio_error("createSound(" << file_name << "): " << FMOD_ErrorString(result));
|
||||
|
||||
audio_error("createSound(" << _file_name << "): " << FMOD_ErrorString(result));
|
||||
|
||||
// We couldn't load the sound file. Create a blank sound record
|
||||
// instead.
|
||||
FMOD_CREATESOUNDEXINFO sound_info;
|
||||
memset(&sound_info, 0, sizeof(sound_info));
|
||||
char blank_data[100];
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
memset(&exinfo, 0, sizeof(exinfo));
|
||||
memset(blank_data, 0, sizeof(blank_data));
|
||||
exinfo.cbsize = sizeof(exinfo);
|
||||
exinfo.length = sizeof(blank_data);
|
||||
exinfo.numchannels = 1;
|
||||
exinfo.defaultfrequency = 8000;
|
||||
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
|
||||
result = _manager->_system->createSound( blank_data, FMOD_SOFTWARE | flag | FMOD_OPENMEMORY | FMOD_OPENRAW, &exinfo, &_sound);
|
||||
sound_info.cbsize = sizeof(sound_info);
|
||||
sound_info.length = sizeof(blank_data);
|
||||
sound_info.numchannels = 1;
|
||||
sound_info.defaultfrequency = 8000;
|
||||
sound_info.format = FMOD_SOUND_FORMAT_PCM16;
|
||||
int flags = FMOD_SOFTWARE | FMOD_OPENMEMORY | FMOD_OPENRAW;
|
||||
|
||||
result = _manager->_system->createSound( blank_data, flags, &sound_info, &_sound);
|
||||
fmod_audio_errcheck("createSound (blank)", result);
|
||||
}
|
||||
|
||||
@ -157,27 +231,6 @@ play() {
|
||||
start_playing();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: sound_end_callback
|
||||
// Access: Static
|
||||
// Description: When fmod finishes playing a sound, decrements the
|
||||
// reference count of the associated FmodAudioSound.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL * channel,
|
||||
FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
void *commanddata1,
|
||||
void *commanddata2) {
|
||||
if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
|
||||
FMOD::Channel *fc = (FMOD::Channel *)channel;
|
||||
void *userdata = NULL;
|
||||
FMOD_RESULT result = fc->getUserData(&userdata);
|
||||
fmod_audio_errcheck("channel->getUserData()", result);
|
||||
FmodAudioSound *fsound = (FmodAudioSound*)userdata;
|
||||
fsound->_self_ref = fsound;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::stop
|
||||
// Access: public
|
||||
@ -884,4 +937,147 @@ get_finished_event() const {
|
||||
return _finished_event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::sound_end_callback
|
||||
// Access: Private, Static
|
||||
// Description: When fmod finishes playing a sound, decrements the
|
||||
// reference count of the associated FmodAudioSound.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioSound::
|
||||
sound_end_callback(FMOD_CHANNEL * channel,
|
||||
FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
void *commanddata1,
|
||||
void *commanddata2) {
|
||||
// Fortunately, this callback is made synchronously rather than
|
||||
// asynchronously (it is triggered during System::update()), so we
|
||||
// don't have to worry about thread-related issues here.
|
||||
if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
|
||||
FMOD::Channel *fc = (FMOD::Channel *)channel;
|
||||
void *userdata = NULL;
|
||||
FMOD_RESULT result = fc->getUserData(&userdata);
|
||||
fmod_audio_errcheck("channel->getUserData()", result);
|
||||
FmodAudioSound *fsound = (FmodAudioSound*)userdata;
|
||||
fsound->_self_ref = fsound;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::open_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioSound::
|
||||
open_callback(const char *name, int, unsigned int *file_size,
|
||||
void **handle, void **user_data) {
|
||||
// We actually pass in the VirtualFile pointer as the "name".
|
||||
VirtualFile *file = (VirtualFile *)name;
|
||||
if (file == (VirtualFile *)NULL) {
|
||||
return FMOD_ERR_FILE_NOTFOUND;
|
||||
}
|
||||
if (fmodAudio_cat.is_spam()) {
|
||||
fmodAudio_cat.spam()
|
||||
<< "open_callback(" << *file << ")\n";
|
||||
}
|
||||
|
||||
istream *str = file->open_read_file(true);
|
||||
|
||||
(*file_size) = file->get_file_size(str);
|
||||
(*handle) = (void *)str;
|
||||
(*user_data) = (void *)file;
|
||||
|
||||
// Explicitly ref the VirtualFile since we're storing it in a void
|
||||
// pointer instead of a PT(VirtualFile).
|
||||
file->ref();
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::close_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioSound::
|
||||
close_callback(void *handle, void *user_data) {
|
||||
VirtualFile *file = (VirtualFile *)user_data;
|
||||
if (fmodAudio_cat.is_spam()) {
|
||||
fmodAudio_cat.spam()
|
||||
<< "close_callback(" << *file << ")\n";
|
||||
}
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
istream *str = (istream *)handle;
|
||||
vfs->close_read_file(str);
|
||||
|
||||
// Explicitly unref the VirtualFile pointer.
|
||||
unref_delete(file);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::read_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioSound::
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data) {
|
||||
VirtualFile *file = (VirtualFile *)user_data;
|
||||
if (fmodAudio_cat.is_spam()) {
|
||||
fmodAudio_cat.spam()
|
||||
<< "read_callback(" << *file << ", " << size_bytes << ")\n";
|
||||
}
|
||||
|
||||
istream *str = (istream *)handle;
|
||||
str->read((char *)buffer, size_bytes);
|
||||
(*bytes_read) = str->gcount();
|
||||
|
||||
// We can't yield here, since this callback is made within a
|
||||
// sub-thread--an OS-level sub-thread spawned by FMod, not a Panda
|
||||
// thread. But we will only execute this code in the true-threads
|
||||
// case anyway.
|
||||
//thread_consider_yield();
|
||||
|
||||
if (str->eof()) {
|
||||
if ((*bytes_read) == 0) {
|
||||
return FMOD_ERR_FILE_EOF;
|
||||
} else {
|
||||
// Report the EOF next time.
|
||||
return FMOD_OK;
|
||||
}
|
||||
} if (str->fail()) {
|
||||
return FMOD_ERR_FILE_BAD;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioSound::seek_callback
|
||||
// Access: Private, Static
|
||||
// Description: A hook into Panda's virtual file system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FMOD_RESULT F_CALLBACK FmodAudioSound::
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data) {
|
||||
VirtualFile *file = (VirtualFile *)user_data;
|
||||
if (fmodAudio_cat.is_spam()) {
|
||||
fmodAudio_cat.spam()
|
||||
<< "seek_callback(" << *file << ", " << pos << ")\n";
|
||||
}
|
||||
|
||||
istream *str = (istream *)handle;
|
||||
str->clear();
|
||||
str->seekg(pos);
|
||||
|
||||
if (str->fail() && !str->eof()) {
|
||||
return FMOD_ERR_FILE_COULDNOTSEEK;
|
||||
} else {
|
||||
return FMOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //]
|
||||
|
@ -204,10 +204,26 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
|
||||
// other mismanagement.
|
||||
PT(FmodAudioSound) _self_ref;
|
||||
|
||||
friend FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL * channel,
|
||||
FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
void *commanddata1,
|
||||
void *commanddata2);
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
sound_end_callback(FMOD_CHANNEL * channel,
|
||||
FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
void *commanddata1,
|
||||
void *commanddata2);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
open_callback(const char *name, int unicode, unsigned int *file_size,
|
||||
void **handle, void **user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
close_callback(void *handle, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
read_callback(void *handle, void *buffer, unsigned int size_bytes,
|
||||
unsigned int *bytes_read, void *user_data);
|
||||
|
||||
static FMOD_RESULT F_CALLBACK
|
||||
seek_callback(void *handle, unsigned int pos, void *user_data);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//These are needed for Panda's Pointer System. DO NOT ERASE!
|
||||
|
@ -23,6 +23,7 @@
|
||||
encrypt_string.h \
|
||||
error_utils.h \
|
||||
export_dtool.h \
|
||||
fileSystemInfo.h fileSystemInfo.I \
|
||||
hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h \
|
||||
indirectLess.I indirectLess.h \
|
||||
@ -84,6 +85,7 @@
|
||||
datagramSink.cxx dcast.cxx \
|
||||
encrypt_string.cxx \
|
||||
error_utils.cxx \
|
||||
fileSystemInfo.cxx \
|
||||
hashGeneratorBase.cxx hashVal.cxx \
|
||||
memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
|
||||
memoryUsagePointers.cxx multifile.cxx \
|
||||
@ -140,6 +142,7 @@
|
||||
dcast.T dcast.h \
|
||||
encrypt_string.h \
|
||||
error_utils.h \
|
||||
fileSystemInfo.h fileSystemInfo.I \
|
||||
hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h \
|
||||
indirectLess.I indirectLess.h \
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "dcast.cxx"
|
||||
#include "encrypt_string.cxx"
|
||||
#include "error_utils.cxx"
|
||||
#include "fileSystemInfo.cxx"
|
||||
#include "hashGeneratorBase.cxx"
|
||||
#include "hashVal.cxx"
|
||||
#include "memoryInfo.cxx"
|
||||
|
103
panda/src/express/fileSystemInfo.I
Normal file
103
panda/src/express/fileSystemInfo.I
Normal file
@ -0,0 +1,103 @@
|
||||
// Filename: fileSystemInfo.I
|
||||
// Created by: drose (20Jun11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::Default Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE FileSystemInfo::
|
||||
FileSystemInfo() :
|
||||
_file_start(0),
|
||||
_file_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE FileSystemInfo::
|
||||
FileSystemInfo(const string &os_file_name, streampos file_start, streamsize file_size) :
|
||||
_os_file_name(os_file_name),
|
||||
_file_start(file_start),
|
||||
_file_size(file_size)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE FileSystemInfo::
|
||||
FileSystemInfo(const FileSystemInfo ©) :
|
||||
_os_file_name(copy._os_file_name),
|
||||
_file_start(copy._file_start),
|
||||
_file_size(copy._file_size)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void FileSystemInfo::
|
||||
operator = (const FileSystemInfo ©) {
|
||||
_os_file_name = copy._os_file_name;
|
||||
_file_start = copy._file_start;
|
||||
_file_size = copy._file_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::get_os_file_name
|
||||
// Access: Published
|
||||
// Description: Returns the os-specific filename that may be used to
|
||||
// open this file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &FileSystemInfo::
|
||||
get_os_file_name() const {
|
||||
return _os_file_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::get_file_start
|
||||
// Access: Published
|
||||
// Description: Returns the offset within the file at which this file
|
||||
// data begins.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE streampos FileSystemInfo::
|
||||
get_file_start() const {
|
||||
return _file_start;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::get_file_size
|
||||
// Access: Published
|
||||
// Description: Returns the number of consecutive bytes, beginning at
|
||||
// get_file_start(), that correspond to this file data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE streamsize FileSystemInfo::
|
||||
get_file_size() const {
|
||||
return _file_size;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const FileSystemInfo &info) {
|
||||
info.output(out);
|
||||
return out;
|
||||
}
|
26
panda/src/express/fileSystemInfo.cxx
Normal file
26
panda/src/express/fileSystemInfo.cxx
Normal file
@ -0,0 +1,26 @@
|
||||
// Filename: fileSystemInfo.cxx
|
||||
// Created by: drose (20Jun11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "fileSystemInfo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FileSystemInfo::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FileSystemInfo::
|
||||
output(ostream &out) const {
|
||||
out << "FileSystemInfo(" << _os_file_name << ", " << _file_start
|
||||
<< ", " << _file_size << ")";
|
||||
}
|
48
panda/src/express/fileSystemInfo.h
Normal file
48
panda/src/express/fileSystemInfo.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Filename: fileSystemInfo.h
|
||||
// Created by: drose (20Jun11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FILESYSTEMINFO_H
|
||||
#define FILESYSTEMINFO_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : FileSystemInfo
|
||||
// Description : This class is used to return data about an actual
|
||||
// file on disk by VirtualFile::get_system_info().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS FileSystemInfo {
|
||||
PUBLISHED:
|
||||
INLINE FileSystemInfo();
|
||||
INLINE FileSystemInfo(const string &os_file_name, streampos file_start, streamsize file_size);
|
||||
INLINE FileSystemInfo(const FileSystemInfo ©);
|
||||
INLINE void operator = (const FileSystemInfo ©);
|
||||
|
||||
INLINE const string &get_os_file_name() const;
|
||||
INLINE streampos get_file_start() const;
|
||||
INLINE streamsize get_file_size() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
string _os_file_name;
|
||||
streampos _file_start;
|
||||
streamsize _file_size;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const FileSystemInfo &info);
|
||||
|
||||
#include "fileSystemInfo.I"
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include "referenceCount.h"
|
||||
#include "pvector.h"
|
||||
#include "openSSLWrapper.h"
|
||||
#include "fileSystemInfo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Multifile
|
||||
|
@ -213,6 +213,21 @@ get_timestamp() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFile::get_system_info
|
||||
// Access: Published, Virtual
|
||||
// Description: Populates the FileSystemInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it does not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFile::
|
||||
get_system_info(FileSystemInfo &info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFile::close_read_file
|
||||
// Access: Public
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "filename.h"
|
||||
#include "fileSystemInfo.h"
|
||||
#include "pointerTo.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "ordered_vector.h"
|
||||
@ -60,6 +61,8 @@ PUBLISHED:
|
||||
BLOCKING virtual off_t get_file_size() const;
|
||||
BLOCKING virtual time_t get_timestamp() const;
|
||||
|
||||
virtual bool get_system_info(FileSystemInfo &info);
|
||||
|
||||
public:
|
||||
INLINE void set_original_filename(const Filename &filename);
|
||||
bool read_file(string &result, bool auto_unwrap) const;
|
||||
|
@ -140,6 +140,21 @@ close_read_file(istream *stream) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMount::get_system_info
|
||||
// Access: Public, Virtual
|
||||
// Description: Populates the FileSystemInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it does not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMount::
|
||||
get_system_info(const Filename &file, FileSystemInfo &info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMount::output
|
||||
// Access: Public, Virtual
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
virtual off_t get_file_size(const Filename &file, istream *stream) const=0;
|
||||
virtual off_t get_file_size(const Filename &file) const=0;
|
||||
virtual time_t get_timestamp(const Filename &file) const=0;
|
||||
virtual bool get_system_info(const Filename &file, FileSystemInfo &info);
|
||||
|
||||
virtual bool scan_directory(vector_string &contents,
|
||||
const Filename &dir) const=0;
|
||||
|
@ -171,6 +171,38 @@ get_timestamp(const Filename &file) const {
|
||||
return _multifile->get_subfile_timestamp(subfile_index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountMultifile::get_system_info
|
||||
// Access: Public, Virtual
|
||||
// Description: Populates the FileSystemInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it might not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountMultifile::
|
||||
get_system_info(const Filename &file, FileSystemInfo &info) {
|
||||
Filename multifile_name = _multifile->get_multifile_name();
|
||||
if (multifile_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
int subfile_index = _multifile->find_subfile(file);
|
||||
if (subfile_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (_multifile->is_subfile_compressed(subfile_index) ||
|
||||
_multifile->is_subfile_encrypted(subfile_index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
streampos start = _multifile->get_subfile_internal_start(subfile_index);
|
||||
size_t length = _multifile->get_subfile_internal_length(subfile_index);
|
||||
|
||||
info = FileSystemInfo(multifile_name.to_os_specific(), start, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountMultifile::scan_directory
|
||||
// Access: Public, Virtual
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
virtual off_t get_file_size(const Filename &file, istream *stream) const;
|
||||
virtual off_t get_file_size(const Filename &file) const;
|
||||
virtual time_t get_timestamp(const Filename &file) const;
|
||||
virtual bool get_system_info(const Filename &file, FileSystemInfo &info);
|
||||
|
||||
virtual bool scan_directory(vector_string &contents,
|
||||
const Filename &dir) const;
|
||||
|
@ -181,6 +181,23 @@ get_timestamp(const Filename &file) const {
|
||||
return pathname.get_timestamp();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountSystem::get_system_info
|
||||
// Access: Public, Virtual
|
||||
// Description: Populates the FileSystemInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it does not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountSystem::
|
||||
get_system_info(const Filename &file, FileSystemInfo &info) {
|
||||
Filename pathname(_physical_filename, file);
|
||||
info = FileSystemInfo(pathname.to_os_specific(), 0, pathname.get_file_size());
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountSystem::scan_directory
|
||||
// Access: Public, Virtual
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
virtual off_t get_file_size(const Filename &file, istream *stream) const;
|
||||
virtual off_t get_file_size(const Filename &file) const;
|
||||
virtual time_t get_timestamp(const Filename &file) const;
|
||||
virtual bool get_system_info(const Filename &file, FileSystemInfo &info);
|
||||
|
||||
virtual bool scan_directory(vector_string &contents,
|
||||
const Filename &dir) const;
|
||||
|
@ -160,6 +160,21 @@ get_timestamp() const {
|
||||
return _mount->get_timestamp(_local_filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileSimple::get_system_info
|
||||
// Access: Published, Virtual
|
||||
// Description: Populates the FileSystemInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it does not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileSimple::
|
||||
get_system_info(FileSystemInfo &info) {
|
||||
return _mount->get_system_info(_local_filename, info);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileSimple::read_file
|
||||
// Access: Public, Virtual
|
||||
|
@ -46,6 +46,7 @@ PUBLISHED:
|
||||
virtual off_t get_file_size(istream *stream) const;
|
||||
virtual off_t get_file_size() const;
|
||||
virtual time_t get_timestamp() const;
|
||||
virtual bool get_system_info(FileSystemInfo &info);
|
||||
|
||||
public:
|
||||
virtual bool read_file(pvector<unsigned char> &result, bool auto_unwrap) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user