From de34468d87229030e5036bfa1122f0a8723e8df9 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 2 Aug 2007 21:07:02 +0000 Subject: [PATCH] finish callbacks --- panda/src/audiotraits/globalMilesManager.I | 24 ++ panda/src/audiotraits/globalMilesManager.h | 7 + panda/src/audiotraits/milesAudioManager.cxx | 221 +++++++++++++------ panda/src/audiotraits/milesAudioManager.h | 14 +- panda/src/audiotraits/milesAudioSample.cxx | 31 +++ panda/src/audiotraits/milesAudioSample.h | 2 + panda/src/audiotraits/milesAudioSequence.cxx | 18 ++ panda/src/audiotraits/milesAudioSequence.h | 1 + panda/src/audiotraits/milesAudioStream.cxx | 61 +++-- panda/src/audiotraits/milesAudioStream.h | 2 + 10 files changed, 293 insertions(+), 88 deletions(-) diff --git a/panda/src/audiotraits/globalMilesManager.I b/panda/src/audiotraits/globalMilesManager.I index eae6117964..3d91b403a0 100644 --- a/panda/src/audiotraits/globalMilesManager.I +++ b/panda/src/audiotraits/globalMilesManager.I @@ -27,3 +27,27 @@ INLINE bool GlobalMilesManager:: is_open() const { return _is_open; } + +//////////////////////////////////////////////////////////////////// +// Function: GlobalMilesManager::get_num_samples +// Access: Public +// Description: Returns the number of sample handles that have been +// allocated. +//////////////////////////////////////////////////////////////////// +INLINE int GlobalMilesManager:: +get_num_samples() const { + MutexHolder holder(_samples_lock); + return _samples.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobalMilesManager::get_num_sequences +// Access: Public +// Description: Returns the number of sequence handles that have been +// allocated. +//////////////////////////////////////////////////////////////////// +INLINE int GlobalMilesManager:: +get_num_sequences() const { + MutexHolder holder(_sequences_lock); + return _sequences.size(); +} diff --git a/panda/src/audiotraits/globalMilesManager.h b/panda/src/audiotraits/globalMilesManager.h index de4c07d2ed..3d57af2ce9 100644 --- a/panda/src/audiotraits/globalMilesManager.h +++ b/panda/src/audiotraits/globalMilesManager.h @@ -25,11 +25,16 @@ #include "mss.h" #include "pset.h" #include "pmutex.h" +#include "mutexHolder.h" #ifndef UINTa #define UINTa U32 #endif +#ifndef SINTa +#define SINTa S32 +#endif + class MilesAudioSample; class MilesAudioSequence; @@ -51,9 +56,11 @@ public: bool get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound); void release_sample(size_t index, MilesAudioSample *sound); + INLINE int get_num_samples() const; bool get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound); void release_sequence(size_t index, MilesAudioSequence *sound); + INLINE int get_num_sequences() const; void force_midi_reset(); diff --git a/panda/src/audiotraits/milesAudioManager.cxx b/panda/src/audiotraits/milesAudioManager.cxx index d3e6bc7c91..3c913e834e 100644 --- a/panda/src/audiotraits/milesAudioManager.cxx +++ b/panda/src/audiotraits/milesAudioManager.cxx @@ -32,6 +32,7 @@ #include "nullAudioSound.h" #include "string_utils.h" #include "mutexHolder.h" +#include "reMutexHolder.h" #include @@ -52,7 +53,9 @@ PT(AudioManager) Create_AudioManager() { // Miles resources. //////////////////////////////////////////////////////////////////// MilesAudioManager:: -MilesAudioManager() : _streams_lock("MilesAudioManager::_streams_lock"), +MilesAudioManager() : + _lock("MilesAudioManager::_lock"), + _streams_lock("MilesAudioManager::_streams_lock"), _streams_cvar(_streams_lock) { audio_debug("MilesAudioManager::MilesAudioManager(), this = " @@ -68,6 +71,7 @@ MilesAudioManager() : _streams_lock("MilesAudioManager::_streams_lock"), _concurrent_sound_limit = 0; _is_valid = true; _hasMidiSounds = false; + _sounds_finished = false; // We used to hang a call to a force-shutdown function on atexit(), // so that any running sounds (particularly MIDI sounds) would be @@ -125,22 +129,8 @@ shutdown() { //////////////////////////////////////////////////////////////////// bool MilesAudioManager:: is_valid() { - bool check=true; - if (_sounds.size() != _lru.size()) { - audio_debug("-- Error _sounds.size() != _lru.size() --"); - check=false; - } else { - LRU::const_iterator i=_lru.begin(); - for (; i != _lru.end(); ++i) { - SoundMap::const_iterator smi=_sounds.find(**i); - if (smi == _sounds.end()) { - audio_debug("-- "<<**i<<" in _lru and not in _sounds --"); - check=false; - break; - } - } - } - return _is_valid && check; + ReMutexHolder holder(_lock); + return do_is_valid(); } //////////////////////////////////////////////////////////////////// @@ -149,15 +139,15 @@ is_valid() { // Description: //////////////////////////////////////////////////////////////////// PT(AudioSound) MilesAudioManager:: -get_sound(const string& file_name, bool) { +get_sound(const string &file_name, bool) { + ReMutexHolder holder(_lock); audio_debug("MilesAudioManager::get_sound(file_name=\""< ib - =_sounds.insert(SoundMap::value_type(path, sd)); + = _sounds.insert(SoundMap::value_type(path, sd)); if (!ib.second) { // The insert failed. audio_debug(" failed map insert of "<resolve_filename(path, get_model_path()); audio_debug(" path=\""<0); - LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first)); - assert(lru_i != _lru.end()); + nassertv(_lru.size() > 0); + LRU::iterator lru_i = find(_lru.begin(), _lru.end(), &(i->first)); + nassertv(lru_i != _lru.end()); _lru.erase(lru_i); _sounds.erase(i); } - assert(is_valid()); + nassertv(do_is_valid()); } //////////////////////////////////////////////////////////////////// @@ -268,10 +260,8 @@ uncache_sound(const string& file_name) { void MilesAudioManager:: clear_cache() { audio_debug("MilesAudioManager::clear_cache()"); - if (_is_valid) { assert(is_valid()); } - _sounds.clear(); - _lru.clear(); - if (_is_valid) { assert(is_valid()); } + ReMutexHolder holder(_lock); + do_clear_cache(); } //////////////////////////////////////////////////////////////////// @@ -281,13 +271,15 @@ clear_cache() { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: set_cache_limit(unsigned int count) { + ReMutexHolder holder(_lock); + audio_debug("MilesAudioManager::set_cache_limit(count="< count) { uncache_a_sound(); } _cache_limit=count; - assert(is_valid()); + nassertv(do_is_valid()); } //////////////////////////////////////////////////////////////////// @@ -308,10 +300,11 @@ get_cache_limit() const { void MilesAudioManager:: set_volume(float volume) { audio_debug("MilesAudioManager::set_volume(volume="<set_volume((*i)->get_volume()); } @@ -336,11 +329,12 @@ get_volume() const { void MilesAudioManager:: set_play_rate(float play_rate) { audio_debug("MilesAudioManager::set_play_rate(play_rate="<set_play_rate((*i)->get_play_rate()); } } @@ -364,11 +358,12 @@ get_play_rate() const { void MilesAudioManager:: set_active(bool active) { audio_debug("MilesAudioManager::set_active(flag="<set_active(_active); } @@ -395,8 +390,9 @@ get_active() const { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: set_concurrent_sound_limit(unsigned int limit) { + ReMutexHolder holder(_lock); _concurrent_sound_limit = limit; - reduce_sounds_playing_to(_concurrent_sound_limit); + do_reduce_sounds_playing_to(_concurrent_sound_limit); } //////////////////////////////////////////////////////////////////// @@ -411,17 +407,13 @@ get_concurrent_sound_limit() const { //////////////////////////////////////////////////////////////////// // Function: MilesAudioManager::reduce_sounds_playing_to -// Access: Private, Virtual +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// void MilesAudioManager:: reduce_sounds_playing_to(unsigned int count) { - int limit = _sounds_playing.size() - count; - while (limit-- > 0) { - SoundsPlaying::iterator sound = _sounds_playing.begin(); - assert(sound != _sounds_playing.end()); - (**sound).stop(); - } + ReMutexHolder holder(_lock); + do_reduce_sounds_playing_to(count); } //////////////////////////////////////////////////////////////////// @@ -444,12 +436,33 @@ stop_all_sounds() { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: update() { - MutexHolder holder(_streams_lock); + { + MutexHolder holder(_streams_lock); + if (_stream_thread.is_null() && !_streams.empty()) { + // If we don't have a sub-thread, we have to service the streams + // in the main thread. + do_service_streams(); + } + } - if (_stream_thread.is_null() && !_streams.empty()) { - // If we don't have a sub-thread, we have to service the streams - // in the main thread. - do_service_streams(); + if (_sounds_finished) { + _sounds_finished = false; + + // If the _sounds_finished flag was set, we should scan our list + // of playing sounds and see if any of them have finished + // recently. We don't do this in the finished callback, because + // that might have been called in a sub-thread (and we may not + // have threading supported--and mutex protection--compiled in). + + SoundsPlaying::iterator si = _sounds_playing.begin(); + while (si != _sounds_playing.end()) { + MilesAudioSound *sound = (*si); + ++si; + + if (sound->status() == AudioSound::READY) { + sound->stop(); + } + } } } @@ -462,6 +475,7 @@ void MilesAudioManager:: release_sound(MilesAudioSound *audioSound) { audio_debug("MilesAudioManager::release_sound(audioSound=\"" <get_name()<<"\"), this = " << (void *)this); + ReMutexHolder holder(_lock); AudioSet::iterator ai = _sounds_on_loan.find(audioSound); nassertv(ai != _sounds_on_loan.end()); _sounds_on_loan.erase(ai); @@ -480,6 +494,7 @@ void MilesAudioManager:: cleanup() { audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this << ", _cleanup_required = " << _cleanup_required); + ReMutexHolder holder(_lock); if (!_cleanup_required) { return; } @@ -490,7 +505,7 @@ cleanup() { (*ai)->cleanup(); } - clear_cache(); + do_clear_cache(); // Now stop the thread, if it has been started. if (!_stream_thread.is_null()) { @@ -519,6 +534,7 @@ cleanup() { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: output(ostream &out) const { + ReMutexHolder holder(_lock); out << get_type() << ": " << _sounds_playing.size() << " / " << _sounds_on_loan.size() << " sounds playing / total"; } @@ -530,15 +546,88 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: write(ostream &out) const { + ReMutexHolder holder(_lock); + out << (*this) << "\n"; AudioSet::const_iterator ai; for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) { MilesAudioSound *sound = (*ai); out << " " << *sound << "\n"; } + + { + MutexHolder holder(_streams_lock); + out << _streams.size() << " streams opened.\n"; + if (!_stream_thread.is_null()) { + out << "(Audio streaming thread has been started.)\n"; + } + } + + GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr(); + + int num_samples = mgr->get_num_samples(); + out << num_samples << " sample handles allocated globally.\n"; + + int num_sequences = mgr->get_num_sequences(); + out << num_sequences << " sequence handles allocated globally.\n"; } +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioManager::do_is_valid +// Access: Private +// Description: Implementation of is_valid(). 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() --"); + check = false; + + } else { + LRU::const_iterator i = _lru.begin(); + for (; i != _lru.end(); ++i) { + SoundMap::const_iterator smi = _sounds.find(**i); + if (smi == _sounds.end()) { + audio_debug("-- "<<**i<<" in _lru and not in _sounds --"); + check = false; + break; + } + } + } + return _is_valid && check; +} + +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioManager::do_reduce_sounds_playing_to +// Access: Private +// Description: Assumes the lock is already held. +//////////////////////////////////////////////////////////////////// +void MilesAudioManager:: +do_reduce_sounds_playing_to(unsigned int count) { + int limit = _sounds_playing.size() - count; + while (limit-- > 0) { + SoundsPlaying::iterator sound = _sounds_playing.begin(); + assert(sound != _sounds_playing.end()); + (**sound).stop(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioManager::do_clear_cache +// Access: Private +// Description: Assumes the lock is already held. +//////////////////////////////////////////////////////////////////// +void MilesAudioManager:: +do_clear_cache() { + if (_is_valid) { nassertv(do_is_valid()); } + _sounds.clear(); + _lru.clear(); + if (_is_valid) { nassertv(do_is_valid()); } +} + //////////////////////////////////////////////////////////////////// // Function: MilesAudioManager::start_service_stream // Access: Private @@ -580,7 +669,7 @@ stop_service_stream(HSTREAM stream) { //////////////////////////////////////////////////////////////////// // Function: MilesAudioManager::most_recently_used // Access: Private -// Description: +// Description: Assumes the lock is already held. //////////////////////////////////////////////////////////////////// void MilesAudioManager:: most_recently_used(const string &path) { @@ -593,18 +682,18 @@ most_recently_used(const string &path) { // At this point, path should not exist in the _lru: assert(find(_lru.begin(), _lru.end(), &path) == _lru.end()); _lru.push_back(&path); - assert(is_valid()); + nassertv(do_is_valid()); } //////////////////////////////////////////////////////////////////// // Function: MilesAudioManager::uncache_a_sound // Access: Private -// Description: +// Description: Assumes the lock is already held. //////////////////////////////////////////////////////////////////// void MilesAudioManager:: uncache_a_sound() { audio_debug("MilesAudioManager::uncache_a_sound()"); - assert(is_valid()); + nassertv(do_is_valid()); // uncache least recently used: assert(_lru.size()>0); LRU::reference path=_lru.front(); @@ -616,7 +705,7 @@ uncache_a_sound() { audio_debug(" uncaching \""<first<<"\""); _sounds.erase(i); } - assert(is_valid()); + nassertv(do_is_valid()); } //////////////////////////////////////////////////////////////////// @@ -626,8 +715,9 @@ uncache_a_sound() { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: starting_sound(MilesAudioSound *audio) { + ReMutexHolder holder(_lock); if (_concurrent_sound_limit) { - reduce_sounds_playing_to(_concurrent_sound_limit); + do_reduce_sounds_playing_to(_concurrent_sound_limit); } _sounds_playing.insert(audio); } @@ -641,6 +731,7 @@ starting_sound(MilesAudioSound *audio) { //////////////////////////////////////////////////////////////////// void MilesAudioManager:: stopping_sound(MilesAudioSound *audio) { + ReMutexHolder holder(_lock); _sounds_playing.erase(audio); if (_hasMidiSounds && _sounds_playing.size() == 0) { GlobalMilesManager::get_global_ptr()->force_midi_reset(); @@ -654,6 +745,8 @@ stopping_sound(MilesAudioSound *audio) { // Description: Reads a sound file and allocates a SoundData pointer // for it. Returns NULL if the sound file cannot be // loaded. +// +// Assumes the lock is already held. //////////////////////////////////////////////////////////////////// PT(MilesAudioManager::SoundData) MilesAudioManager:: load(const Filename &file_name) { diff --git a/panda/src/audiotraits/milesAudioManager.h b/panda/src/audiotraits/milesAudioManager.h index 4d0a9f8964..2bd4e13c03 100644 --- a/panda/src/audiotraits/milesAudioManager.h +++ b/panda/src/audiotraits/milesAudioManager.h @@ -31,6 +31,7 @@ #include "pvector.h" #include "thread.h" #include "pmutex.h" +#include "reMutex.h" #include "conditionVar.h" class MilesAudioSound; @@ -65,7 +66,6 @@ public: virtual unsigned int get_concurrent_sound_limit() const; virtual void reduce_sounds_playing_to(unsigned int count); - virtual void stop_all_sounds(); virtual void update(); @@ -78,6 +78,10 @@ public: virtual void write(ostream &out) const; private: + bool do_is_valid(); + void do_reduce_sounds_playing_to(unsigned int count); + void do_clear_cache(); + void start_service_stream(HSTREAM stream); void stop_service_stream(HSTREAM stream); @@ -123,12 +127,12 @@ private: // The offspring of this manager: AudioSet _sounds_on_loan; - typedef pset SoundsPlaying; + typedef pset SoundsPlaying; // The sounds from this manager that are currently playing: SoundsPlaying _sounds_playing; // The Least Recently Used mechanism: - typedef pdeque LRU; + typedef pdeque LRU; LRU _lru; // State: float _volume; @@ -141,6 +145,10 @@ private: bool _is_valid; bool _hasMidiSounds; + // This mutex protects everything above. + ReMutex _lock; + bool _sounds_finished; + typedef pvector Streams; PT(StreamThread) _stream_thread; Streams _streams; diff --git a/panda/src/audiotraits/milesAudioSample.cxx b/panda/src/audiotraits/milesAudioSample.cxx index 5194e15e18..1f0c347dc0 100644 --- a/panda/src/audiotraits/milesAudioSample.cxx +++ b/panda/src/audiotraits/milesAudioSample.cxx @@ -96,6 +96,8 @@ play() { &_sd->_raw_data[0], _sd->_raw_data.size(), 0); _original_playback_rate = AIL_sample_playback_rate(_sample); + AIL_set_sample_user_data(_sample, 0, (SINTa)this); + AIL_register_EOS_callback(_sample, finish_callback); set_volume(_volume); set_play_rate(_play_rate); @@ -293,6 +295,19 @@ cleanup() { stop(); } +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioSample::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void MilesAudioSample:: +output(ostream &out) const { + out << get_type() << " " << get_name() << " " << status(); + if (!_sd.is_null()) { + out << " " << (_sd->_raw_data.size() + 1023) / 1024 << "K"; + } +} + //////////////////////////////////////////////////////////////////// // Function: MilesAudioSample::internal_stop // Access: Private @@ -306,4 +321,20 @@ internal_stop() { _sample_index = 0; } +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioSample::finish_callback +// Access: Private, Static +// Description: This callback is made by Miles (possibly in a +// sub-thread) when the sample finishes. +//////////////////////////////////////////////////////////////////// +void AILCALLBACK MilesAudioSample:: +finish_callback(HSAMPLE sample) { + MilesAudioSample *self = (MilesAudioSample *)AIL_sample_user_data(sample, 0); + if (milesAudio_cat.is_debug()) { + milesAudio_cat.debug() + << "finished " << *self << "\n"; + } + self->_manager->_sounds_finished = true; +} + #endif //] diff --git a/panda/src/audiotraits/milesAudioSample.h b/panda/src/audiotraits/milesAudioSample.h index 498bc93415..95c626ab23 100644 --- a/panda/src/audiotraits/milesAudioSample.h +++ b/panda/src/audiotraits/milesAudioSample.h @@ -56,9 +56,11 @@ public: virtual AudioSound::SoundStatus status() const; virtual void cleanup(); + virtual void output(ostream &out) const; private: void internal_stop(); + static void AILCALLBACK finish_callback(HSAMPLE sample); PT(MilesAudioManager::SoundData) _sd; HSAMPLE _sample; diff --git a/panda/src/audiotraits/milesAudioSequence.cxx b/panda/src/audiotraits/milesAudioSequence.cxx index 0be1da19be..947be878b5 100644 --- a/panda/src/audiotraits/milesAudioSequence.cxx +++ b/panda/src/audiotraits/milesAudioSequence.cxx @@ -92,6 +92,8 @@ play() { _sequence = 0; } else { AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0); + AIL_set_sequence_user_data(_sequence, 0, (SINTa)this); + AIL_register_sequence_callback(_sequence, finish_callback); set_volume(_volume); set_play_rate(_play_rate); @@ -296,4 +298,20 @@ internal_stop() { _sequence_index = 0; } +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioSequence::finish_callback +// Access: Private, Static +// Description: This callback is made by Miles (possibly in a +// sub-thread) when the sequence finishes. +//////////////////////////////////////////////////////////////////// +void AILCALLBACK MilesAudioSequence:: +finish_callback(HSEQUENCE sequence) { + MilesAudioSequence *self = (MilesAudioSequence *)AIL_sequence_user_data(sequence, 0); + if (milesAudio_cat.is_debug()) { + milesAudio_cat.debug() + << "finished " << *self << "\n"; + } + self->_manager->_sounds_finished = true; +} + #endif //] diff --git a/panda/src/audiotraits/milesAudioSequence.h b/panda/src/audiotraits/milesAudioSequence.h index 26f7e6b611..18192c1db9 100644 --- a/panda/src/audiotraits/milesAudioSequence.h +++ b/panda/src/audiotraits/milesAudioSequence.h @@ -58,6 +58,7 @@ public: private: void internal_stop(); + static void AILCALLBACK finish_callback(HSEQUENCE sequence); PT(MilesAudioManager::SoundData) _sd; HSEQUENCE _sequence; diff --git a/panda/src/audiotraits/milesAudioStream.cxx b/panda/src/audiotraits/milesAudioStream.cxx index 7638a841ac..859512c319 100644 --- a/panda/src/audiotraits/milesAudioStream.cxx +++ b/panda/src/audiotraits/milesAudioStream.cxx @@ -77,6 +77,14 @@ play() { if (_stream == 0) { GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr(); _stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0); + if (_stream == 0) { + milesAudio_cat.warning() + << "Could not play " << _file_name << ": too many open streams\n"; + return; + } + AIL_set_stream_user_data(_stream, 0, (SINTa)this); + AIL_register_stream_callback(_stream, finish_callback); + } else { // We already had the stream open. Keep it open; just restart // it. @@ -84,29 +92,24 @@ play() { _manager->stop_service_stream(_stream); } - if (_stream == 0) { - milesAudio_cat.warning() - << "Could not play " << _file_name << ": too many open streams\n"; - + // Start playing: + nassertv(_stream != 0); + HSAMPLE sample = AIL_stream_sample_handle(_stream); + nassertv(sample != 0); + + _original_playback_rate = AIL_sample_playback_rate(sample); + set_volume(_volume); + set_play_rate(_play_rate); + + AIL_set_stream_loop_count(_stream, _loop_count); + + if (miles_audio_panda_threads) { + AIL_auto_service_stream(_stream, 0); + _manager->start_service_stream(_stream); } else { - // Start playing: - HSAMPLE sample = AIL_stream_sample_handle(_stream); - nassertv(sample != 0); - - _original_playback_rate = AIL_sample_playback_rate(sample); - set_volume(_volume); - set_play_rate(_play_rate); - - AIL_set_stream_loop_count(_stream, _loop_count); - - if (miles_audio_panda_threads) { - AIL_auto_service_stream(_stream, 0); - _manager->start_service_stream(_stream); - } else { - AIL_auto_service_stream(_stream, 1); - } - AIL_start_stream(_stream); + AIL_auto_service_stream(_stream, 1); } + AIL_start_stream(_stream); } else { // In case _loop_count gets set to forever (zero): @@ -295,5 +298,21 @@ cleanup() { } } +//////////////////////////////////////////////////////////////////// +// Function: MilesAudioStream::finish_callback +// Access: Private, Static +// Description: This callback is made by Miles (possibly in a +// sub-thread) when the stream finishes. +//////////////////////////////////////////////////////////////////// +void AILCALLBACK MilesAudioStream:: +finish_callback(HSTREAM stream) { + MilesAudioStream *self = (MilesAudioStream *)AIL_stream_user_data(stream, 0); + if (milesAudio_cat.is_debug()) { + milesAudio_cat.debug() + << "finished " << *self << "\n"; + } + self->_manager->_sounds_finished = true; +} + #endif //] diff --git a/panda/src/audiotraits/milesAudioStream.h b/panda/src/audiotraits/milesAudioStream.h index 8111c07aa2..fc61782797 100644 --- a/panda/src/audiotraits/milesAudioStream.h +++ b/panda/src/audiotraits/milesAudioStream.h @@ -58,6 +58,8 @@ public: virtual void cleanup(); private: + static void AILCALLBACK finish_callback(HSTREAM stream); + Filename _path; HSTREAM _stream; S32 _original_playback_rate;