浏览代码

Some work to make it work on a mac

Roger Hughston 19 年之前
父节点
当前提交
0e87c509ce

+ 90 - 193
panda/src/audiotraits/milesAudioManager.cxx

@@ -27,14 +27,12 @@
 #include "config_express.h"
 #include "virtualFileSystem.h"
 #include "nullAudioSound.h"
-#include "mutexHolder.h"
 
 #include <algorithm>
 
 
 TypeHandle MilesAudioManager::_type_handle;
 
-Mutex *MilesAudioManager::_static_lock;
 int MilesAudioManager::_active_managers = 0;
 bool MilesAudioManager::_miles_active = false;
 HDLSFILEID MilesAudioManager::_dls_field = NULL;
@@ -61,23 +59,10 @@ MilesAudioManager::
 MilesAudioManager() {
   audio_debug("MilesAudioManager::MilesAudioManager(), this = " 
               << (void *)this);
-  if (_static_lock == NULL) {
-    Mutex *new_lock = new Mutex;
-    void *result = AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_static_lock, (void *)NULL, (void *)new_lock);
-    if (result != NULL) {
-      // Someone else must have assigned the mutex first.  OK.
-      nassertv(_static_lock != new_lock);
-      delete new_lock;
-    }
-    nassertv((Mutex * TVOLATILE &)_static_lock != NULL);
-  }
-
-  MutexHolder st_holder(*(Mutex * TVOLATILE &)_static_lock);
   if (_managers == (Managers *)NULL) {
     _managers = new Managers;
   }
   _managers->insert(this);
-
   audio_debug("  audio_active="<<audio_active);
   audio_debug("  audio_volume="<<audio_volume);
   _cleanup_required = true;
@@ -93,7 +78,14 @@ MilesAudioManager() {
     S32 use_MIDI=(audio_play_midi)?1:0;
     if (audio_play_midi && audio_software_midi) {
       use_MIDI=AIL_QUICK_DLS_ONLY;
+
     }
+
+#ifdef IS_OSX 
+use_MIDI=AIL_QUICK_DLS_ONLY;
+audio_software_midi=true;
+#endif
+
     audio_debug("  use_digital="<<use_digital);
     audio_debug("  use_MIDI="<<use_MIDI);
     audio_debug("  audio_output_rate="<<audio_output_rate);
@@ -124,7 +116,6 @@ MilesAudioManager() {
           }
           
           audio_debug("  dls_file=\""<<dls_file<<"\"");
-          
           // note: if AIL_DLS_load_file is not done, midi fails to play on some machines.
           nassertv(_dls_field == NULL);
           audio_debug("  AIL_DLS_load_file(dls, " << dls_file << ", 0)");
@@ -179,21 +170,14 @@ MilesAudioManager() {
 ////////////////////////////////////////////////////////////////////
 MilesAudioManager::
 ~MilesAudioManager() {
-  {
-    MutexHolder st_holder(*_static_lock);
-    audio_debug("MilesAudioManager::~MilesAudioManager(), this = " 
-                << (void *)this);
-    nassertv(_managers != (Managers *)NULL);
-    Managers::iterator mi = _managers->find(this);
-    if (mi != _managers->end()) {
-      // The manager might already have been removed from the list, if
-      // the user has already called shutdown().
-      _managers->erase(mi);
-    }
-  }
+  audio_debug("MilesAudioManager::~MilesAudioManager(), this = " 
+              << (void *)this);
+  nassertv(_managers != (Managers *)NULL);
+  Managers::iterator mi = _managers->find(this);
+  nassertv(mi != _managers->end());
+  _managers->erase(mi);
 
   cleanup();
-
   audio_debug("MilesAudioManager::~MilesAudioManager() finished");
 }
 
@@ -208,60 +192,27 @@ MilesAudioManager::
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 shutdown() {
-  Managers old_managers;
-  {
-    MutexHolder st_holder(*_static_lock);
-    
-    audio_debug("shutdown(), _miles_active = " << _miles_active);
-    if (_managers != (Managers *)NULL) {
-      old_managers.swap(*_managers);
+  audio_debug("shutdown(), _miles_active = " << _miles_active);
+  if (_managers != (Managers *)NULL) {
+    Managers::iterator mi;
+    for (mi = _managers->begin(); mi != _managers->end(); ++mi) {
+      (*mi)->cleanup();
     }
   }
 
-  // We insist on cleaning up our manager pointers, rather than
-  // relying on their destructors, since there might be outstanding
-  // pointers to these somewhere that would otherwise prevent them
-  // from being cleaned up and therefore prevent Miles from being shut
-  // down properly.  In order for this to work, we must write
-  // cleanup() so that it is safe to call it twice.
-  Managers::iterator mi;
-  for (mi = old_managers.begin(); mi != old_managers.end(); ++mi) {
-    (*mi)->cleanup();
-  }
-
-  // Another thread might conceivably have started up a new manager
-  // after we called shutdown(), which is technically legal and would
-  // incorrectly trigger the following assertion.  However, presumably
-  // shutdown() will only be called as the application is shutting
-  // down anyway, and there won't be any other threads still out there
-  // creating audio managers (and if there were, it would defeat the
-  // purpose of shutdown() anyway).
   nassertv(_active_managers == 0);
-
   audio_debug("shutdown() finished");
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: MilesAudioManager::is_valid
-//       Access: Public
+//       Access:
 //  Description: This is mostly for debugging, but it it could be
 //               used to detect errors in a release build if you
 //               don't mind the cpu cost.
 ////////////////////////////////////////////////////////////////////
 bool MilesAudioManager::
 is_valid() {
-  MutexHolder holder(_lock);
-
-  return do_is_valid();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: MilesAudioManager::do_is_valid
-//       Access: Private
-//  Description: Assumes the lock is already held.
-////////////////////////////////////////////////////////////////////
-bool MilesAudioManager::
-do_is_valid() {
   bool check=true;
   if (_sounds.size() != _lru.size()) {
     audio_debug("-- Error _sounds.size() != _lru.size() --");
@@ -374,88 +325,59 @@ get_sound(const string& file_name, bool) {
      return get_null_sound();
   }
 
+  assert(is_valid());
   Filename path = file_name;
 
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   vfs->resolve_filename(path, get_sound_path());
   audio_debug("  resolved file_name is '"<<path<<"'");
 
-  const string *cache_path = NULL;
   PT(SoundData) sd;
-
   // Get the sound, either from the cache or from a loader:
-  MutexHolder holder(_lock);
-
-  assert(do_is_valid());
-
-  SoundMap::const_iterator si = _sounds.find(path);
+  SoundMap::const_iterator si=_sounds.find(path);
   if (si != _sounds.end()) {
     // ...found the sound in the cache.
-    cache_path = &((*si).first);
     sd = (*si).second;
     audio_debug("  sound found in pool 0x" << (void*)sd);
-  }
-
-  if (sd == (SoundData *)NULL) {
+  } else {
     // ...the sound was not found in the cache/pool.
-
-    // Ideally, we should release the lock while we're performing the
-    // actual load, so multiple threads can be loading sounds in
-    // parallel.  However, it appears that Miles is internally not
-    // thread-safe, so we can't do that.
-
-    //_lock.release();
     sd = load(path);
-    //_lock.lock();
-
     if (sd != (SoundData *)NULL) {
-      SoundMap::const_iterator si = _sounds.find(path);
-      if (si != _sounds.end()) {
-        // Oops, someone else must have just put it in the cache.
-        // Throw away the sound object we just loaded.
-        cache_path = &((*si).first);
-        sd = (*si).second;
-        audio_debug("  sound found in pool 0x" << (void*)sd);
-        
-      } else {
-        // OK, put the sound object we just loaded into the cache.
-        while (_sounds.size() >= (unsigned int)_cache_limit) {
-          uncache_a_sound();
-        }
-
-        // The following is roughly like: _sounds[path] = sd;
-        // But, it gives us an iterator into the map.
-        pair<SoundMap::const_iterator, bool> ib =
-          _sounds.insert(SoundMap::value_type(path, sd));
-        if (!ib.second) {
-          // The insert failed.
-          audio_debug("  failed map insert of "<<path);
-          assert(do_is_valid());
-          return get_null_sound();
-        }
-        // Get a reference to the path for the MilesAudioSound.
-        SoundMap::const_iterator si = ib.first;
-        cache_path = &((*si).first);
+      while (_sounds.size() >= (unsigned int)_cache_limit) {
+        uncache_a_sound();
       }
+      // Put it in the pool:
+      // The following is roughly like: _sounds[path] = sd;
+      // But, it gives us an iterator into the map.
+      pair<SoundMap::const_iterator, bool> ib
+          =_sounds.insert(SoundMap::value_type(path, sd));
+      if (!ib.second) {
+        // The insert failed.
+        audio_debug("  failed map insert of "<<path);
+        assert(is_valid());
+        return get_null_sound();
+      }
+      // Set si, so that we can get a reference to the path
+      // for the MilesAudioSound.
+      si=ib.first;
     }
   }
-
   // Create an AudioSound from the sound:
-  PT(AudioSound) audioSound;
+  PT(AudioSound) audioSound = 0;
   if (sd != (SoundData *)NULL) {
-    nassertr(cache_path != NULL, NULL);
-    most_recently_used(cache_path);
-    PT(MilesAudioSound) milesAudioSound = new MilesAudioSound(this, sd, path);
-    nassertr(milesAudioSound, NULL);
+    most_recently_used((*si).first);
+    PT(MilesAudioSound) milesAudioSound
+        =new MilesAudioSound(this, sd, (*si).first);
+    nassertr(milesAudioSound, 0);
     milesAudioSound->set_active(_active);
     bool inserted = _sounds_on_loan.insert(milesAudioSound).second;
     nassertr(inserted, milesAudioSound.p());
-    audioSound = milesAudioSound;
+    audioSound=milesAudioSound;
   }
 
   _hasMidiSounds |= (file_name.find(".mid")!=string::npos);
   audio_debug("  returning 0x" << (void*)audioSound);
-  assert(do_is_valid());
+  assert(is_valid());
   return audioSound;
 }
 
@@ -465,19 +387,17 @@ get_sound(const string& file_name, bool) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
-uncache_sound(const string &file_name) {
-  MutexHolder holder(_lock);
-
+uncache_sound(const string& file_name) {
   audio_debug("MilesAudioManager::uncache_sound(file_name=\""
       <<file_name<<"\")");
-  assert(do_is_valid());
+  assert(is_valid());
   Filename path = file_name;
 
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   vfs->resolve_filename(path, get_sound_path());
 
   audio_debug("  path=\""<<path<<"\"");
-  SoundMap::iterator i = _sounds.find(path);
+  SoundMap::iterator i=_sounds.find(path);
   if (i != _sounds.end()) {
     assert(_lru.size()>0);
     LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first));
@@ -485,18 +405,18 @@ uncache_sound(const string &file_name) {
     _lru.erase(lru_i);
     _sounds.erase(i);
   }
-  assert(do_is_valid());
+  assert(is_valid());
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: MilesAudioManager::uncache_a_sound
-//       Access: Private
-//  Description: Assumes the lock is already held.
+//       Access: Public
+//  Description:
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 uncache_a_sound() {
   audio_debug("MilesAudioManager::uncache_a_sound()");
-  assert(do_is_valid());
+  assert(is_valid());
   // uncache least recently used:
   assert(_lru.size()>0);
   LRU::reference path=_lru.front();
@@ -508,26 +428,26 @@ uncache_a_sound() {
     audio_debug("  uncaching \""<<i->first<<"\"");
     _sounds.erase(i);
   }
-  assert(do_is_valid());
+  assert(is_valid());
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: MilesAudioManager::most_recently_used
-//       Access: Private
-//  Description: Assumes the lock is already held.
+//       Access: Public
+//  Description:
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
-most_recently_used(const string *path) {
+most_recently_used(const string& path) {
   audio_debug("MilesAudioManager::most_recently_used(path=\""
       <<path<<"\")");
-  LRU::iterator i=find(_lru.begin(), _lru.end(), path);
+  LRU::iterator i=find(_lru.begin(), _lru.end(), &path);
   if (i != _lru.end()) {
     _lru.erase(i);
   }
   // At this point, path should not exist in the _lru:
-  assert(find(_lru.begin(), _lru.end(), path) == _lru.end());
-  _lru.push_back(path);
-  assert(do_is_valid());
+  assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
+  _lru.push_back(&path);
+  assert(is_valid());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -537,22 +457,11 @@ most_recently_used(const string *path) {
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 clear_cache() {
-  MutexHolder holder(_lock);
-  do_clear_cache();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: MilesAudioManager::do_clear_cache
-//       Access: Private
-//  Description: Assumes the lock is already held.
-////////////////////////////////////////////////////////////////////
-void MilesAudioManager::
-do_clear_cache() {
   audio_debug("MilesAudioManager::clear_cache()");
-  if (_is_valid) { assert(do_is_valid()); }
+  if (_is_valid) { assert(is_valid()); }
   _sounds.clear();
   _lru.clear();
-  if (_is_valid) { assert(do_is_valid()); }
+  if (_is_valid) { assert(is_valid()); }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -562,15 +471,13 @@ do_clear_cache() {
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 set_cache_limit(unsigned int count) {
-  MutexHolder holder(_lock);
-
   audio_debug("MilesAudioManager::set_cache_limit(count="<<count<<")");
-  assert(do_is_valid());
+  assert(is_valid());
   while (_lru.size() > count) {
     uncache_a_sound();
   }
   _cache_limit=count;
-  assert(do_is_valid());
+  assert(is_valid());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -580,8 +487,6 @@ set_cache_limit(unsigned int count) {
 ////////////////////////////////////////////////////////////////////
 unsigned int MilesAudioManager::
 get_cache_limit() const {
-  MutexHolder holder(_lock);
-
   audio_debug("MilesAudioManager::get_cache_limit() returning "
       <<_cache_limit);
   return _cache_limit;
@@ -594,8 +499,6 @@ get_cache_limit() const {
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 release_sound(MilesAudioSound* audioSound) {
-  MutexHolder holder(_lock);
-
   audio_debug("MilesAudioManager::release_sound(audioSound=\""
               <<audioSound->get_name()<<"\"), this = " << (void *)this);
   AudioSet::iterator ai = _sounds_on_loan.find(audioSound);
@@ -771,6 +674,8 @@ stop_all_sounds() {
   reduce_sounds_playing_to(0);
 }
 
+
+#ifdef WIN32
 ////////////////////////////////////////////////////////////////////
 //     Function: MilesAudioManager::get_registry_entry
 //       Access: private
@@ -816,7 +721,7 @@ get_registry_entry(HKEY base, const char* subKeyName,
 
   return (r==ERROR_SUCCESS);
 }
-
+#endif
 ////////////////////////////////////////////////////////////////////
 //     Function: MilesAudioManager::get_gm_file_path
 //       Access: private
@@ -824,12 +729,21 @@ get_registry_entry(HKEY base, const char* subKeyName,
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 get_gm_file_path(string& result) {
+#ifdef WIN32
   if(!get_registry_entry(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\DirectMusic", "GMFilePath", result)) {
           char sysdir[MAX_PATH+1];
           GetSystemDirectory(sysdir,MAX_PATH+1);
           result = sysdir;
           result.append("\\drivers\\gm.dls");
   }
+#endif
+
+#ifdef IS_OSX 
+result = 
+//"gs_instruments.dls";
+"/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls";
+#endif
+
 
   audio_debug("MilesAudioManager::get_gm_file_path() result out=\""<<result<<"\"");
 }
@@ -855,7 +769,9 @@ force_midi_reset() {
   AIL_quick_handles(0, &hMid, 0);
   if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
     audio_debug("MilesAudioManager::calling midiOutReset");
+#ifdef WIN32
     midiOutReset(hMid->hMidiOut);
+#endif
   }
 }
 
@@ -868,40 +784,19 @@ force_midi_reset() {
 ////////////////////////////////////////////////////////////////////
 void MilesAudioManager::
 cleanup() {
-  {
-    MutexHolder holder(_lock);
-    
-    audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this
-                << ", _cleanup_required = " << _cleanup_required);
-    if (!_cleanup_required) {
-      return;
-    }
-    
-    // Be sure to cleanup associated sounds before cleaning up the manager:
-    AudioSet::iterator ai;
-    for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
-      (*ai)->cleanup();
-    }
-
-    do_clear_cache();
-
-    _cleanup_required = false;
+  audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this
+              << ", _cleanup_required = " << _cleanup_required);
+  if (!_cleanup_required) {
+    return;
   }
 
-  deactivate();
-
-  audio_debug("MilesAudioManager::cleanup() finished");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: MilesAudioManager::deactivate
-//       Access: Private, Static
-//  Description: Deactivates one manager.  Grabs the static lock.
-////////////////////////////////////////////////////////////////////
-void MilesAudioManager::
-deactivate() {
-  MutexHolder st_holder(*_static_lock);
+  // Be sure to cleanup associated sounds before cleaning up the manager:
+  AudioSet::iterator ai;
+  for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
+    (*ai)->cleanup();
+  }
 
+  clear_cache();
   nassertv(_active_managers > 0);
   --_active_managers;
   audio_debug("  _active_managers="<<_active_managers);
@@ -921,6 +816,8 @@ deactivate() {
       _miles_active = false;
     }
   }
+  _cleanup_required = false;
+  audio_debug("MilesAudioManager::cleanup() finished");
 }
 
 ////////////////////////////////////////////////////////////////////

+ 10 - 23
panda/src/audiotraits/milesAudioManager.h

@@ -28,7 +28,6 @@
 #include "pset.h"
 #include "pmap.h"
 #include "pdeque.h"
-#include "pmutex.h"
 
 class MilesAudioSound;
 
@@ -66,8 +65,6 @@ public:
   void stop_all_sounds();
 
 private:
-  Mutex _lock; // Protects all the members of this class.
-
   // The sound cache:
   class SoundData : public ReferenceCount {
   public:
@@ -85,16 +82,16 @@ private:
   typedef pmap<string, PT(SoundData) > SoundMap;
   SoundMap _sounds;
 
-  typedef pset<MilesAudioSound *> AudioSet;
+  typedef pset<MilesAudioSound* > AudioSet;
   // The offspring of this manager:
   AudioSet _sounds_on_loan;
 
-  typedef pset<MilesAudioSound *> SoundsPlaying;
+  typedef pset<MilesAudioSound* > SoundsPlaying;
   // The sounds from this manager that are currently playing:
   SoundsPlaying _sounds_playing;
 
   // The Least Recently Used mechanism:
-  typedef pdeque<const string *> LRU;
+  typedef pdeque<const string* > LRU;
   LRU _lru;
   // State:
   float _volume;
@@ -102,51 +99,41 @@ private:
   bool _active;
   int _cache_limit;
   bool _cleanup_required;
-
+  // keep a count for startup and shutdown:
+  static int _active_managers;
+  static bool _miles_active;
   unsigned int _concurrent_sound_limit;
   
   bool _is_valid;
   bool _hasMidiSounds;
 
-private:
-  // Static members.  Protected by the following lock.
-  static Mutex *_static_lock;
-
-  // keep a count for startup and shutdown:
-  static int _active_managers;
-  static bool _miles_active;
-
   // Optional Downloadable Sound field for software midi
   static HDLSFILEID _dls_field;
 
   typedef pset<MilesAudioManager *> Managers;
   static Managers *_managers;
-
-private:  
-  bool do_is_valid();
-  void do_clear_cache();
-
+  
   PT(SoundData) load(Filename file_name);
   // Tell the manager that the sound dtor was called.
   void release_sound(MilesAudioSound* audioSound);
   
-  void most_recently_used(const string *path);
+  void most_recently_used(const string& path);
   void uncache_a_sound();
 
   void starting_sound(MilesAudioSound* audio);
   void stopping_sound(MilesAudioSound* audio);
-
+#ifdef WIN32
   // utility function that should be moved to another class:
   bool get_registry_entry(HKEY base, 
                           const char* subKeyName, 
                           const char* keyName, 
                           string& result);
+#endif
   // get the default dls file path:
   void get_gm_file_path(string& result);
 
   void force_midi_reset();
   void cleanup();
-  static void deactivate();
 
   friend class MilesAudioSound;
 

+ 4 - 4
panda/src/audiotraits/milesAudioSound.cxx

@@ -66,7 +66,7 @@ namespace {
 namespace {
   AILSEQUENCECB sequence_callback = 0;
   AILSAMPLECB sample_callback = 0;
-  const user_data_index = 7;
+  const int user_data_index = 7;
 
   ////////////////////////////////////////////////////////////////////
   //     Function: pandaAudioAilCallback_Sequence
@@ -363,7 +363,7 @@ set_time(float time) {
     time = max_time;
   }
 
-  S32 millisecond_time=S32(1000*time);
+  S32 millisecond_time=(S32)(1000*time);
   AIL_quick_set_ms_position(_audio, millisecond_time);
 }
 
@@ -462,7 +462,7 @@ set_play_rate(float play_rate) {
     case AIL_QUICK_XMIDI_TYPE:
     case AIL_QUICK_DLS_XMIDI_TYPE:
       // midi uses whole percentage values 100 == 100%
-      _audio->speed = S32(play_rate*100.0f);
+      _audio->speed = (S32)(play_rate*100.0f);
       if ((_audio->speed != -1) && (AIL_quick_status(_audio) == QSTAT_PLAYING)) {
         AIL_set_sequence_tempo((HSEQUENCE)_audio->handle, _audio->speed, 0);
       }
@@ -471,7 +471,7 @@ set_play_rate(float play_rate) {
     case AIL_QUICK_DIGITAL_TYPE:
     case AIL_QUICK_MPEG_DIGITAL_TYPE:
       // wave and mp3 use sample rate (e.g. 44100)
-      _audio->speed = S32(play_rate*float(_original_playback_rate));
+      _audio->speed = (S32)(play_rate*float(_original_playback_rate));
       if ((_audio->speed != -1) && (AIL_quick_status(_audio) == QSTAT_PLAYING)) {
         AIL_set_sample_playback_rate((HSAMPLE)_audio->handle, _audio->speed);
       }

+ 1 - 1
panda/src/audiotraits/milesAudioSound.h

@@ -149,7 +149,7 @@ private:
   // itwas set inactive.
   bool _paused;
 
-  MilesAudioSound(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
+  MilesAudioSound(MilesAudioManager* manager, MilesAudioManager::SoundData *sd,
                   string file_name, float length=0.0f);
   void cleanup();