Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/audiotraits/milesAudioManager.cxx

Go to the documentation of this file.
00001 // Filename: milesAudioManager.cxx
00002 // Created by:  skyler (June 6, 2001)
00003 // Prior system by: cary
00004 //
00005 ////////////////////////////////////////////////////////////////////
00006 //
00007 // PANDA 3D SOFTWARE
00008 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00009 //
00010 // All use of this software is subject to the terms of the Panda 3d
00011 // Software license.  You should have received a copy of this license
00012 // along with this source code; you will also find a current copy of
00013 // the license at http://www.panda3d.org/license.txt .
00014 //
00015 // To contact the maintainers of this program write to
00016 // panda3d@yahoogroups.com .
00017 //
00018 ////////////////////////////////////////////////////////////////////
00019 
00020 #include "pandabase.h"
00021 #ifdef HAVE_RAD_MSS //[
00022 
00023 #include "milesAudioSound.h"
00024 #include "milesAudioManager.h"
00025 #include "config_audio.h"
00026 #include "config_util.h"
00027 #include "config_express.h"
00028 #include "virtualFileSystem.h"
00029 #include "nullAudioSound.h"
00030 #include <algorithm>
00031 
00032 int MilesAudioManager::_active_managers = 0;
00033 HDLSFILEID MilesAudioManager::_dls_field = NULL;
00034 bool bMilesShutdownCalled = false;
00035 bool bMilesShutdownAtExitRegistered = false;
00036 
00037 PT(AudioManager) Create_AudioManager() {
00038   audio_debug("Create_AudioManager() Miles.");
00039   return new MilesAudioManager();
00040 }
00041 
00042 void fMilesShutdown(void) {
00043     if(bMilesShutdownCalled)
00044       return;
00045 
00046     bMilesShutdownCalled = true;
00047 
00048     if (MilesAudioManager::_dls_field!=NULL) {
00049       HDLSDEVICE dls= NULL;
00050       AIL_quick_handles(0, 0, &dls);
00051       if(dls!=NULL) {
00052           AIL_DLS_unload(dls,MilesAudioManager::_dls_field);
00053       }
00054 
00055       #ifndef NDEBUG //[
00056         // Clear _dls_field in debug version (for assert in ctor):
00057         MilesAudioManager::_dls_field = NULL;  
00058       #endif //]
00059     }
00060 
00061 
00062    #define SHUTDOWN_HACK
00063    
00064    // if python crashes, the midi notes are left on,
00065    // so we need to turn them off.  Unfortunately
00066    // in Miles 6.5, AIL_quick_shutdown() crashes
00067    // when it's called from atexit after a python crash, probably
00068    // because mss32.dll has already been unloaded
00069    // workaround: use these internal values in the miles struct
00070    //             to reset the win32 midi ourselves
00071    
00072    #ifdef SHUTDOWN_HACK
00073     HMDIDRIVER hMid=NULL;
00074     AIL_quick_handles(0, &hMid, 0);
00075     if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
00076       midiOutReset(hMid->hMidiOut);
00077       midiOutClose(hMid->hMidiOut);
00078     }
00079    #else
00080     audio_debug("  AIL_quick_shutdown()");
00081     AIL_quick_shutdown();
00082    #endif
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: MilesAudioManager::MilesAudioManager
00087 //       Access: Public
00088 //  Description:
00089 ////////////////////////////////////////////////////////////////////
00090 MilesAudioManager::
00091 MilesAudioManager() {
00092   audio_debug("MilesAudioManager::MilesAudioManager()");
00093   audio_debug("  audio_active="<<audio_active);
00094   audio_debug("  audio_volume="<<audio_volume);
00095   _active = audio_active;
00096   _volume = audio_volume;
00097   _cache_limit = audio_cache_limit;
00098   _is_valid = true;
00099   _bHasMidiSounds = false;
00100   if (_active_managers==0) {
00101     S32 use_digital=(audio_play_wave || audio_play_mp3)?1:0;
00102     S32 use_MIDI=(audio_play_midi)?1:0;
00103     if (audio_play_midi && audio_software_midi) {
00104       use_MIDI=AIL_QUICK_DLS_ONLY;
00105     }
00106     audio_debug("  use_digital="<<use_digital);
00107     audio_debug("  use_MIDI="<<use_MIDI);
00108     audio_debug("  audio_output_rate="<<audio_output_rate);
00109     audio_debug("  audio_output_bits="<<audio_output_bits);
00110     audio_debug("  audio_output_channels="<<audio_output_channels);
00111     audio_debug("  audio_software_midi="<<audio_software_midi);
00112     #ifndef NDEBUG //[
00113       char version[8];
00114       AIL_MSS_version(version, 8);
00115       audio_debug("  Mss32.dll Version: "<<version);
00116     #endif //]
00117     if (AIL_quick_startup(use_digital,
00118         use_MIDI, audio_output_rate,
00119         audio_output_bits, audio_output_channels)) {
00120       if (audio_software_midi) {
00121         // Load the downloadable sounds file:
00122 
00123         HDLSDEVICE dls;
00124         AIL_quick_handles(0, 0, &dls);
00125         nassertv(audio_dls_file);
00126         nassertv(!_dls_field);
00127         if (audio_dls_file->empty()) {
00128           get_gm_file_path(*audio_dls_file);
00129           // we need more dbg info in logs, so bumping the msgs from 'debug' status to 'info' status
00130           audio_info("  using default audio_dls_file: "<< (*audio_dls_file) );
00131         }
00132 
00133         audio_debug("  audio_dls_file=\""<<*audio_dls_file<<"\"");
00134 
00135         // note: if AIL_DLS_load_file is not done, midi fails to play on some machines.
00136         _dls_field=AIL_DLS_load_file(dls, audio_dls_file->c_str(), 0);
00137         if (!_dls_field) {
00138           audio_error("  AIL_DLS_load_file() failed, \""<<AIL_last_error() <<"\" Switching to hardware midi");
00139           AIL_quick_shutdown();
00140           if (!AIL_quick_startup(use_digital, 1, audio_output_rate,
00141               audio_output_bits, audio_output_channels)) {
00142             audio_error("  midi hardware startup failed, "<<AIL_last_error());
00143             _is_valid = false;
00144           }
00145         } else {
00146           audio_info("  using Miles software midi");
00147         }
00148       } else {
00149           audio_info("  using Miles hardware midi");
00150       }
00151 
00152       if (use_vfs) {
00153         AIL_set_file_callbacks(vfs_open_callback,
00154                                vfs_close_callback,
00155                                vfs_seek_callback,
00156                                vfs_read_callback);
00157       }
00158     } else {
00159       audio_debug("  AIL_quick_startup failed: "<<AIL_last_error());
00160       _is_valid = false;
00161     }
00162   }
00163   // We increment _active_managers regardless of possible errors above.
00164   // The miles shutdown call will do the right thing when it's called,
00165   // either way.
00166   ++_active_managers;
00167   audio_debug("  _active_managers="<<_active_managers);
00168 
00169   if (_is_valid)  {
00170     assert(is_valid());
00171 
00172     if(!bMilesShutdownAtExitRegistered) {
00173        bMilesShutdownAtExitRegistered = true;
00174        atexit(fMilesShutdown);
00175     }
00176   }
00177 }
00178 
00179 ////////////////////////////////////////////////////////////////////
00180 //     Function: MilesAudioManager::~MilesAudioManager
00181 //       Access: Public
00182 //  Description:
00183 ////////////////////////////////////////////////////////////////////
00184 MilesAudioManager::
00185 ~MilesAudioManager() {
00186   audio_debug("MilesAudioManager::~MilesAudioManager()");
00187   // Be sure to delete associated sounds before deleting the manager:
00188   nassertv(_soundsOnLoan.empty());
00189   clear_cache();
00190   --_active_managers;
00191   audio_debug("  _active_managers="<<_active_managers);
00192   if (_active_managers==0) {
00193     if (audio_software_midi) {
00194       HDLSDEVICE dls;
00195       AIL_quick_handles(0, 0, &dls);
00196       AIL_DLS_unload(dls, _dls_field);
00197       #ifndef NDEBUG //[
00198         // Clear _dls_field in debug version (for assert in ctor):
00199         _dls_field=0;
00200       #endif //]
00201     }
00202     audio_debug("  AIL_quick_shutdown()");
00203     AIL_quick_shutdown();
00204     bMilesShutdownCalled = true;
00205   }
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: MilesAudioManager::is_valid
00210 //       Access:
00211 //  Description:
00212 ////////////////////////////////////////////////////////////////////
00213 bool MilesAudioManager::
00214 is_valid() {
00215   bool check=true;
00216   if (_sounds.size() != _lru.size()) {
00217     audio_debug("--sizes--");
00218     check=false;
00219   } else {
00220     LRU::const_iterator i=_lru.begin();
00221     for (; i != _lru.end(); ++i) {
00222       SoundMap::const_iterator smi=_sounds.find(**i);
00223       if (smi == _sounds.end()) {
00224         audio_debug("--"<<**i<<"--");
00225         check=false;
00226         break;
00227       }
00228     }
00229   }
00230   return _is_valid && check;
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: MilesAudioManager::load
00235 //       Access:
00236 //  Description:
00237 ////////////////////////////////////////////////////////////////////
00238 HAUDIO MilesAudioManager::
00239 load(Filename file_name) {
00240   HAUDIO audio;
00241 
00242   if (use_vfs) {
00243     audio = AIL_quick_load(file_name.c_str());
00244 
00245   } else {
00246     string stmp = file_name.to_os_specific();
00247     audio_debug("  \"" << stmp << "\"");
00248     audio = AIL_quick_load(stmp.c_str());
00249   }
00250    
00251   if (!audio) {
00252     audio_error("  MilesAudioManager::load failed "<< AIL_last_error());
00253   }
00254   return audio;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: MilesAudioManager::get_sound
00259 //       Access: Public
00260 //  Description:
00261 ////////////////////////////////////////////////////////////////////
00262 PT(AudioSound) MilesAudioManager::
00263 get_sound(const string& file_name) {
00264   audio_debug("MilesAudioManager::get_sound(file_name=\""<<file_name<<"\")");
00265 
00266   if(!is_valid()) {
00267      audio_debug("invalid MilesAudioManager returning NullSound");
00268      return get_null_sound();
00269   }
00270 
00271   assert(is_valid());
00272   Filename path = file_name;
00273 
00274   if (use_vfs) {
00275     VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00276     vfs->resolve_filename(path, get_sound_path());
00277   } else {
00278     path.resolve_filename(get_sound_path());
00279   }
00280 
00281   audio_debug("  resolved file_name is '"<<path<<"'");
00282 
00283   HAUDIO audio=0;
00284   // Get the sound, either from the cache or from a loader:
00285   SoundMap::const_iterator si=_sounds.find(path);
00286   if (si != _sounds.end()) {
00287     // ...found the sound in the cache.
00288     audio = (*si).second;
00289     audio_debug("  sound found in pool 0x" << (void*)audio);
00290   } else {
00291     // ...the sound was not found in the cache/pool.
00292     audio=load(path);
00293     if (audio) {
00294       while (_sounds.size() >= (unsigned int)_cache_limit) {
00295         uncache_a_sound();
00296       }
00297       // Put it in the pool:
00298       // The following is roughly like: _sounds[path] = audio;
00299       // But, it gives us an iterator into the map.
00300       pair<SoundMap::const_iterator, bool> ib
00301           =_sounds.insert(pair<string, HAUDIO>(path, audio));
00302       if (!ib.second) {
00303         // The insert failed.
00304         audio_debug("  failed map insert of "<<path);
00305         assert(is_valid());
00306         return get_null_sound();
00307       }
00308       // Set si, so that we can get a reference to the path
00309       // for the MilesAudioSound.
00310       si=ib.first;
00311     }
00312   }
00313   // Create an AudioSound from the sound:
00314   PT(AudioSound) audioSound = 0;
00315   if (audio) {
00316     most_recently_used((*si).first);
00317     PT(MilesAudioSound) milesAudioSound
00318         =new MilesAudioSound(this, audio, (*si).first);
00319     nassertr(milesAudioSound, 0);
00320     milesAudioSound->set_active(_active);
00321     _soundsOnLoan.insert(milesAudioSound);
00322     audioSound=milesAudioSound;
00323   }
00324 
00325   _bHasMidiSounds |= (file_name.find(".mid")!=string::npos);
00326   audio_debug("  returning 0x" << (void*)audioSound);
00327   assert(is_valid());
00328   return audioSound;
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: MilesAudioManager::uncache_sound
00333 //       Access: Public
00334 //  Description:
00335 ////////////////////////////////////////////////////////////////////
00336 void MilesAudioManager::
00337 uncache_sound(const string& file_name) {
00338   audio_debug("MilesAudioManager::uncache_sound(file_name=\""
00339       <<file_name<<"\")");
00340   assert(is_valid());
00341   Filename path = file_name;
00342 
00343   if (use_vfs) {
00344     VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00345     vfs->resolve_filename(path, get_sound_path());
00346   } else {
00347     path.resolve_filename(get_sound_path());
00348   }
00349 
00350   audio_debug("  path=\""<<path<<"\"");
00351   SoundMap::iterator i=_sounds.find(path);
00352   if (i != _sounds.end()) {
00353     assert(_lru.size()>0);
00354     LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first));
00355     assert(lru_i != _lru.end());
00356     _lru.erase(lru_i);
00357     AIL_quick_unload(i->second);
00358     _sounds.erase(i);
00359   }
00360   assert(is_valid());
00361 }
00362 
00363 ////////////////////////////////////////////////////////////////////
00364 //     Function: MilesAudioManager::uncache_a_sound
00365 //       Access: Public
00366 //  Description:
00367 ////////////////////////////////////////////////////////////////////
00368 void MilesAudioManager::
00369 uncache_a_sound() {
00370   audio_debug("MilesAudioManager::uncache_a_sound()");
00371   assert(is_valid());
00372   // uncache least recently used:
00373   assert(_lru.size()>0);
00374   LRU::reference path=_lru.front();
00375   SoundMap::iterator i = _sounds.find(*path);
00376   assert(i != _sounds.end());
00377   _lru.pop_front();
00378 
00379   if (i != _sounds.end()) {
00380     audio_debug("  uncaching \""<<i->first<<"\"");
00381     AIL_quick_unload(i->second);
00382     _sounds.erase(i);
00383   }
00384   assert(is_valid());
00385 }
00386 
00387 ////////////////////////////////////////////////////////////////////
00388 //     Function: MilesAudioManager::most_recently_used
00389 //       Access: Public
00390 //  Description:
00391 ////////////////////////////////////////////////////////////////////
00392 void MilesAudioManager::
00393 most_recently_used(const string& path) {
00394   audio_debug("MilesAudioManager::most_recently_used(path=\""
00395       <<path<<"\")");
00396   LRU::iterator i=find(_lru.begin(), _lru.end(), &path);
00397   if (i != _lru.end()) {
00398     _lru.erase(i);
00399   }
00400   // At this point, path should not exist in the _lru:
00401   assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
00402   _lru.push_back(&path);
00403   assert(is_valid());
00404 }
00405 
00406 ////////////////////////////////////////////////////////////////////
00407 //     Function: MilesAudioManager::clear_cache
00408 //       Access: Public
00409 //  Description:
00410 ////////////////////////////////////////////////////////////////////
00411 void MilesAudioManager::
00412 clear_cache() {
00413   audio_debug("MilesAudioManager::clear_cache()");
00414   if (_is_valid) { assert(is_valid()); }
00415   SoundMap::iterator i=_sounds.begin();
00416   for (; i!=_sounds.end(); ++i) {
00417     AIL_quick_unload(i->second);
00418   }
00419   _sounds.clear();
00420   _lru.clear();
00421   if (_is_valid) { assert(is_valid()); }
00422 }
00423 
00424 ////////////////////////////////////////////////////////////////////
00425 //     Function: MilesAudioManager::set_cache_limit
00426 //       Access: Public
00427 //  Description:
00428 ////////////////////////////////////////////////////////////////////
00429 void MilesAudioManager::
00430 set_cache_limit(int count) {
00431   audio_debug("MilesAudioManager::set_cache_limit(count="
00432       <<count<<")");
00433   assert(is_valid());
00434   while (_lru.size() > (unsigned int) count) {
00435     uncache_a_sound();
00436   }
00437   _cache_limit=count;
00438   assert(is_valid());
00439 }
00440 
00441 ////////////////////////////////////////////////////////////////////
00442 //     Function: MilesAudioManager::get_cache_limit
00443 //       Access: Public
00444 //  Description:
00445 ////////////////////////////////////////////////////////////////////
00446 int MilesAudioManager::
00447 get_cache_limit() {
00448   audio_debug("MilesAudioManager::get_cache_limit() returning "
00449       <<_cache_limit);
00450   return _cache_limit;
00451 }
00452 
00453 ////////////////////////////////////////////////////////////////////
00454 //     Function: MilesAudioManager::release_sound
00455 //       Access: Public
00456 //  Description:
00457 ////////////////////////////////////////////////////////////////////
00458 void MilesAudioManager::
00459 release_sound(MilesAudioSound* audioSound) {
00460   audio_debug("MilesAudioManager::release_sound(audioSound=\""
00461       <<audioSound->get_name()<<"\")");
00462   _soundsOnLoan.erase(audioSound);
00463 }
00464 
00465 ////////////////////////////////////////////////////////////////////
00466 //     Function: MilesAudioManager::set_volume
00467 //       Access: Public
00468 //  Description: set the overall volume
00469 ////////////////////////////////////////////////////////////////////
00470 void MilesAudioManager::
00471 set_volume(float volume) {
00472   audio_debug("MilesAudioManager::set_volume(volume="<<volume<<")");
00473   if (_volume!=volume) {
00474     _volume = volume;
00475     // Tell our AudioSounds to adjust:
00476     AudioSet::iterator i=_soundsOnLoan.begin();
00477     for (; i!=_soundsOnLoan.end(); ++i) {
00478       (**i).set_volume((**i).get_volume());
00479     }
00480   }
00481 }
00482 
00483 void MilesAudioManager::
00484 stop_all_sounds(void) {
00485   audio_debug("MilesAudioManager::stop_all_sounds()");
00486   AudioSet::iterator i=_soundsOnLoan.begin();
00487   for (; i!=_soundsOnLoan.end(); ++i) {
00488       if((**i).status()==AudioSound::PLAYING)
00489           (**i).stop();
00490   }
00491 
00492   if(_bHasMidiSounds) {
00493       forceMidiReset();
00494   }
00495 }
00496 
00497 void MilesAudioManager::
00498 forceMidiReset(void) {
00499     if(!miles_audio_force_midi_reset) {
00500         audio_debug("MilesAudioManager::skipping forceMidiReset");  
00501         return;
00502     }
00503 
00504     audio_debug("MilesAudioManager::ForceMidiReset");
00505 
00506     // sometimes Miles seems to leave midi notes hanging, even after stop is called,
00507     // so perform an explicit reset using winMM.dll calls, just to ensure silence.
00508     HMDIDRIVER hMid=NULL;
00509     AIL_quick_handles(0, &hMid, 0);
00510     if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
00511         audio_debug("MilesAudioManager::calling midiOutReset");
00512         midiOutReset(hMid->hMidiOut);
00513     }
00514 }
00515 
00516 ////////////////////////////////////////////////////////////////////
00517 //     Function: MilesAudioManager::get_volume
00518 //       Access: Public
00519 //  Description: get the overall volume
00520 ////////////////////////////////////////////////////////////////////
00521 float MilesAudioManager::
00522 get_volume() {
00523   audio_debug("MilesAudioManager::get_volume() returning "<<_volume);
00524   return _volume;
00525 }
00526 
00527 ////////////////////////////////////////////////////////////////////
00528 //     Function: MilesAudioManager::set_active
00529 //       Access: Public
00530 //  Description: turn on/off
00531 ////////////////////////////////////////////////////////////////////
00532 void MilesAudioManager::
00533 set_active(bool active) {
00534   audio_debug("MilesAudioManager::set_active(flag="<<active<<")");
00535   if (_active!=active) {
00536     _active=active;
00537     // Tell our AudioSounds to adjust:
00538     AudioSet::iterator i=_soundsOnLoan.begin();
00539     for (; i!=_soundsOnLoan.end(); ++i) {
00540       (**i).set_active(_active);
00541     }
00542 
00543     if((!_active) && _bHasMidiSounds) {
00544         forceMidiReset();
00545     }
00546   }
00547 }
00548 
00549 ////////////////////////////////////////////////////////////////////
00550 //     Function: MilesAudioManager::get_active
00551 //       Access: Public
00552 //  Description:
00553 ////////////////////////////////////////////////////////////////////
00554 bool MilesAudioManager::
00555 get_active() {
00556   audio_debug("MilesAudioManager::get_active() returning "<<_active);
00557   return _active;
00558 }
00559 
00560 ////////////////////////////////////////////////////////////////////
00561 //     Function: MilesAudioManager::get_registry_entry
00562 //       Access: private
00563 //  Description: Combine base\\subKeyname\\keyName to get
00564 //               'result' from the Windows registry.
00565 ////////////////////////////////////////////////////////////////////
00566 bool MilesAudioManager::
00567 get_registry_entry(HKEY base, const char* subKeyName,
00568     const char* keyName, string& result) {
00569   // Open the key to access the registry:
00570   HKEY key;
00571   long r=RegOpenKeyEx(base, subKeyName, 0, KEY_QUERY_VALUE, &key);
00572   if (r==ERROR_SUCCESS) {
00573     DWORD len=0;
00574     // Read the size of the value at keyName:
00575     r=RegQueryValueEx(key, keyName, 0, 0, 0, &len);
00576     if (r==ERROR_SUCCESS) {
00577       char* src = new char[len];
00578       DWORD type;
00579       // Read the value at keyName:
00580       r=RegQueryValueEx(key, keyName, 0, &type, (unsigned char*)src, &len);
00581       if (r==ERROR_SUCCESS) {
00582         if (type==REG_EXPAND_SZ) {
00583           // Find the size of the expanded string:
00584           DWORD destSize=ExpandEnvironmentStrings(src, 0, 0);
00585           // Get a destination buffer of that size:
00586           char* dest = new char[destSize];
00587           // Do the expansion:
00588           ExpandEnvironmentStrings(src, dest, destSize);
00589           // Propagate the result:
00590           result=dest;
00591           delete [] dest;
00592         } else if (type==REG_SZ) {
00593           result=src;
00594         } else {
00595           audio_error("MilesAudioManager::get_reg_entry(): Unknown key type.");
00596         }
00597       }
00598       delete [] src;
00599     }
00600     RegCloseKey(key);
00601   }
00602 
00603   return (r==ERROR_SUCCESS);
00604 }
00605 
00606 ////////////////////////////////////////////////////////////////////
00607 //     Function: MilesAudioManager::get_gm_file_path
00608 //       Access: private
00609 //  Description: Get path of downloadable sound midi instruments file.
00610 ////////////////////////////////////////////////////////////////////
00611 void MilesAudioManager::
00612 get_gm_file_path(string& result) {
00613   if(!get_registry_entry(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\DirectMusic", "GMFilePath", result)) {
00614           char sysdir[MAX_PATH+1];
00615           GetSystemDirectory(sysdir,MAX_PATH+1);
00616           result = sysdir;
00617           result.append("\\drivers\\gm.dls");
00618   }
00619 
00620   audio_debug("MilesAudioManager::get_gm_file_path() result out=\""<<result<<"\"");
00621 }
00622 
00623 ////////////////////////////////////////////////////////////////////
00624 //     Function: MilesAudioManager::vfs_open_callback
00625 //       Access: Private, Static
00626 //  Description: A Miles callback to open a file for reading from the
00627 //               VFS system.
00628 ////////////////////////////////////////////////////////////////////
00629 U32 MilesAudioManager::
00630 vfs_open_callback(const char *filename, U32 *file_handle) {
00631   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00632   istream *istr = vfs->open_read_file(filename);
00633   if (istr == (istream *)NULL) {
00634     // Unable to open.
00635     milesAudio_cat.warning()
00636       << "Unable to open " << filename << "\n";
00637     *file_handle = 0;
00638     return 0;
00639   }
00640 
00641   // Successfully opened.  Now we should return a U32 that we can
00642   // map back into this istream pointer later.  Strictly speaking,
00643   // we should allocate a table of istream pointers and assign each
00644   // one a unique number, but for now we'll cheat because we know
00645   // that the Miles code (presently) only runs on Win32, which
00646   // always has 32-bit pointers.
00647   *file_handle = (U32)istr;
00648   return 1;
00649 }
00650 
00651 ////////////////////////////////////////////////////////////////////
00652 //     Function: MilesAudioManager::vfs_read_callback
00653 //       Access: Private, Static
00654 //  Description: A Miles callback to read data from a file opened via
00655 //               vfs_open_callback().
00656 ////////////////////////////////////////////////////////////////////
00657 U32 MilesAudioManager::
00658 vfs_read_callback(U32 file_handle, void *buffer, U32 bytes) {
00659   if (file_handle == 0) {
00660     // File was not opened.
00661     return 0;
00662   }
00663   istream *istr = (istream *)file_handle;
00664   istr->read((char *)buffer, bytes);
00665   size_t bytes_read = istr->gcount();
00666 
00667   return bytes_read;
00668 }
00669 
00670 ////////////////////////////////////////////////////////////////////
00671 //     Function: MilesAudioManager::vfs_seek_callback
00672 //       Access: Private, Static
00673 //  Description: A Miles callback to seek within a file opened via
00674 //               vfs_open_callback().
00675 ////////////////////////////////////////////////////////////////////
00676 S32 MilesAudioManager::
00677 vfs_seek_callback(U32 file_handle, S32 offset, U32 type) {
00678   if (file_handle == 0) {
00679     // File was not opened.
00680     return 0;
00681   }
00682   istream *istr = (istream *)file_handle;
00683 
00684   ios::seekdir dir = ios::beg;
00685   switch (type) {
00686   case AIL_FILE_SEEK_BEGIN:
00687     dir = ios::beg;
00688     break;
00689   case AIL_FILE_SEEK_CURRENT:
00690     dir = ios::cur;
00691     break;
00692   case AIL_FILE_SEEK_END:
00693     dir = ios::end;
00694     break;
00695   }
00696 
00697   istr->seekg(offset, dir);
00698   return istr->tellg();
00699 }
00700 
00701 ////////////////////////////////////////////////////////////////////
00702 //     Function: MilesAudioManager::vfs_close_callback
00703 //       Access: Private, Static
00704 //  Description: A Miles callback to close a file opened via
00705 //               vfs_open_callback().
00706 ////////////////////////////////////////////////////////////////////
00707 void MilesAudioManager::
00708 vfs_close_callback(U32 file_handle) {
00709   if (file_handle == 0) {
00710     // File was not opened.
00711     return;
00712   }
00713   istream *istr = (istream *)file_handle;
00714   delete istr;
00715 }
00716 
00717 
00718 #endif //]

Generated on Fri May 2 00:34:33 2003 for Panda by doxygen1.3