mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
finish callbacks
This commit is contained in:
parent
4c6b2a4698
commit
de34468d87
@ -27,3 +27,27 @@ INLINE bool GlobalMilesManager::
|
|||||||
is_open() const {
|
is_open() const {
|
||||||
return _is_open;
|
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();
|
||||||
|
}
|
||||||
|
@ -25,11 +25,16 @@
|
|||||||
#include "mss.h"
|
#include "mss.h"
|
||||||
#include "pset.h"
|
#include "pset.h"
|
||||||
#include "pmutex.h"
|
#include "pmutex.h"
|
||||||
|
#include "mutexHolder.h"
|
||||||
|
|
||||||
#ifndef UINTa
|
#ifndef UINTa
|
||||||
#define UINTa U32
|
#define UINTa U32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SINTa
|
||||||
|
#define SINTa S32
|
||||||
|
#endif
|
||||||
|
|
||||||
class MilesAudioSample;
|
class MilesAudioSample;
|
||||||
class MilesAudioSequence;
|
class MilesAudioSequence;
|
||||||
|
|
||||||
@ -51,9 +56,11 @@ public:
|
|||||||
|
|
||||||
bool get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound);
|
bool get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound);
|
||||||
void release_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);
|
bool get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound);
|
||||||
void release_sequence(size_t index, MilesAudioSequence *sound);
|
void release_sequence(size_t index, MilesAudioSequence *sound);
|
||||||
|
INLINE int get_num_sequences() const;
|
||||||
|
|
||||||
void force_midi_reset();
|
void force_midi_reset();
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "nullAudioSound.h"
|
#include "nullAudioSound.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
#include "mutexHolder.h"
|
#include "mutexHolder.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -52,7 +53,9 @@ PT(AudioManager) Create_AudioManager() {
|
|||||||
// Miles resources.
|
// Miles resources.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
MilesAudioManager::
|
MilesAudioManager::
|
||||||
MilesAudioManager() : _streams_lock("MilesAudioManager::_streams_lock"),
|
MilesAudioManager() :
|
||||||
|
_lock("MilesAudioManager::_lock"),
|
||||||
|
_streams_lock("MilesAudioManager::_streams_lock"),
|
||||||
_streams_cvar(_streams_lock)
|
_streams_cvar(_streams_lock)
|
||||||
{
|
{
|
||||||
audio_debug("MilesAudioManager::MilesAudioManager(), this = "
|
audio_debug("MilesAudioManager::MilesAudioManager(), this = "
|
||||||
@ -68,6 +71,7 @@ MilesAudioManager() : _streams_lock("MilesAudioManager::_streams_lock"),
|
|||||||
_concurrent_sound_limit = 0;
|
_concurrent_sound_limit = 0;
|
||||||
_is_valid = true;
|
_is_valid = true;
|
||||||
_hasMidiSounds = false;
|
_hasMidiSounds = false;
|
||||||
|
_sounds_finished = false;
|
||||||
|
|
||||||
// We used to hang a call to a force-shutdown function on atexit(),
|
// We used to hang a call to a force-shutdown function on atexit(),
|
||||||
// so that any running sounds (particularly MIDI sounds) would be
|
// so that any running sounds (particularly MIDI sounds) would be
|
||||||
@ -125,22 +129,8 @@ shutdown() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool MilesAudioManager::
|
bool MilesAudioManager::
|
||||||
is_valid() {
|
is_valid() {
|
||||||
bool check=true;
|
ReMutexHolder holder(_lock);
|
||||||
if (_sounds.size() != _lru.size()) {
|
return do_is_valid();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -149,15 +139,15 @@ is_valid() {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(AudioSound) MilesAudioManager::
|
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=\""<<file_name<<"\")");
|
audio_debug("MilesAudioManager::get_sound(file_name=\""<<file_name<<"\")");
|
||||||
|
|
||||||
if(!is_valid()) {
|
if (!do_is_valid()) {
|
||||||
audio_debug("invalid MilesAudioManager returning NullSound");
|
audio_debug("invalid MilesAudioManager returning NullSound");
|
||||||
return get_null_sound();
|
return get_null_sound();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(is_valid());
|
|
||||||
Filename path = file_name;
|
Filename path = file_name;
|
||||||
|
|
||||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||||
@ -172,6 +162,7 @@ get_sound(const string& file_name, bool) {
|
|||||||
// ...found the sound in the cache.
|
// ...found the sound in the cache.
|
||||||
sd = (*si).second;
|
sd = (*si).second;
|
||||||
audio_debug(" sound found in pool 0x" << (void*)sd);
|
audio_debug(" sound found in pool 0x" << (void*)sd);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// ...the sound was not found in the cache/pool.
|
// ...the sound was not found in the cache/pool.
|
||||||
sd = load(path);
|
sd = load(path);
|
||||||
@ -183,11 +174,11 @@ get_sound(const string& file_name, bool) {
|
|||||||
// The following is roughly like: _sounds[path] = sd;
|
// The following is roughly like: _sounds[path] = sd;
|
||||||
// But, it gives us an iterator into the map.
|
// But, it gives us an iterator into the map.
|
||||||
pair<SoundMap::const_iterator, bool> ib
|
pair<SoundMap::const_iterator, bool> ib
|
||||||
=_sounds.insert(SoundMap::value_type(path, sd));
|
= _sounds.insert(SoundMap::value_type(path, sd));
|
||||||
if (!ib.second) {
|
if (!ib.second) {
|
||||||
// The insert failed.
|
// The insert failed.
|
||||||
audio_debug(" failed map insert of "<<path);
|
audio_debug(" failed map insert of "<<path);
|
||||||
assert(is_valid());
|
nassertr(do_is_valid(), NULL);
|
||||||
return get_null_sound();
|
return get_null_sound();
|
||||||
}
|
}
|
||||||
// Set si, so that we can get a reference to the path
|
// Set si, so that we can get a reference to the path
|
||||||
@ -228,7 +219,7 @@ get_sound(const string& file_name, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio_debug(" returning 0x" << (void*)audioSound);
|
audio_debug(" returning 0x" << (void*)audioSound);
|
||||||
assert(is_valid());
|
nassertr(do_is_valid(), NULL);
|
||||||
return audioSound;
|
return audioSound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,10 +229,11 @@ get_sound(const string& file_name, bool) {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
uncache_sound(const string& file_name) {
|
uncache_sound(const string &file_name) {
|
||||||
audio_debug("MilesAudioManager::uncache_sound(file_name=\""
|
audio_debug("MilesAudioManager::uncache_sound(file_name=\""
|
||||||
<<file_name<<"\")");
|
<<file_name<<"\")");
|
||||||
assert(is_valid());
|
ReMutexHolder holder(_lock);
|
||||||
|
nassertv(do_is_valid());
|
||||||
Filename path = file_name;
|
Filename path = file_name;
|
||||||
|
|
||||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||||
@ -249,15 +241,15 @@ uncache_sound(const string& file_name) {
|
|||||||
vfs->resolve_filename(path, get_model_path());
|
vfs->resolve_filename(path, get_model_path());
|
||||||
|
|
||||||
audio_debug(" path=\""<<path<<"\"");
|
audio_debug(" path=\""<<path<<"\"");
|
||||||
SoundMap::iterator i=_sounds.find(path);
|
SoundMap::iterator i = _sounds.find(path);
|
||||||
if (i != _sounds.end()) {
|
if (i != _sounds.end()) {
|
||||||
assert(_lru.size()>0);
|
nassertv(_lru.size() > 0);
|
||||||
LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first));
|
LRU::iterator lru_i = find(_lru.begin(), _lru.end(), &(i->first));
|
||||||
assert(lru_i != _lru.end());
|
nassertv(lru_i != _lru.end());
|
||||||
_lru.erase(lru_i);
|
_lru.erase(lru_i);
|
||||||
_sounds.erase(i);
|
_sounds.erase(i);
|
||||||
}
|
}
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -268,10 +260,8 @@ uncache_sound(const string& file_name) {
|
|||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
clear_cache() {
|
clear_cache() {
|
||||||
audio_debug("MilesAudioManager::clear_cache()");
|
audio_debug("MilesAudioManager::clear_cache()");
|
||||||
if (_is_valid) { assert(is_valid()); }
|
ReMutexHolder holder(_lock);
|
||||||
_sounds.clear();
|
do_clear_cache();
|
||||||
_lru.clear();
|
|
||||||
if (_is_valid) { assert(is_valid()); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -281,13 +271,15 @@ clear_cache() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
set_cache_limit(unsigned int count) {
|
set_cache_limit(unsigned int count) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
audio_debug("MilesAudioManager::set_cache_limit(count="<<count<<")");
|
audio_debug("MilesAudioManager::set_cache_limit(count="<<count<<")");
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
while (_lru.size() > count) {
|
while (_lru.size() > count) {
|
||||||
uncache_a_sound();
|
uncache_a_sound();
|
||||||
}
|
}
|
||||||
_cache_limit=count;
|
_cache_limit=count;
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -308,10 +300,11 @@ get_cache_limit() const {
|
|||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
set_volume(float volume) {
|
set_volume(float volume) {
|
||||||
audio_debug("MilesAudioManager::set_volume(volume="<<volume<<")");
|
audio_debug("MilesAudioManager::set_volume(volume="<<volume<<")");
|
||||||
if (_volume!=volume) {
|
ReMutexHolder holder(_lock);
|
||||||
|
if (_volume != volume) {
|
||||||
_volume = volume;
|
_volume = volume;
|
||||||
// Tell our AudioSounds to adjust:
|
// Tell our AudioSounds to adjust:
|
||||||
AudioSet::iterator i=_sounds_on_loan.begin();
|
AudioSet::iterator i = _sounds_on_loan.begin();
|
||||||
for (; i!=_sounds_on_loan.end(); ++i) {
|
for (; i!=_sounds_on_loan.end(); ++i) {
|
||||||
(*i)->set_volume((*i)->get_volume());
|
(*i)->set_volume((*i)->get_volume());
|
||||||
}
|
}
|
||||||
@ -336,11 +329,12 @@ get_volume() const {
|
|||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
set_play_rate(float play_rate) {
|
set_play_rate(float play_rate) {
|
||||||
audio_debug("MilesAudioManager::set_play_rate(play_rate="<<play_rate<<")");
|
audio_debug("MilesAudioManager::set_play_rate(play_rate="<<play_rate<<")");
|
||||||
if (_play_rate!=play_rate) {
|
ReMutexHolder holder(_lock);
|
||||||
|
if (_play_rate != play_rate) {
|
||||||
_play_rate = play_rate;
|
_play_rate = play_rate;
|
||||||
// Tell our AudioSounds to adjust:
|
// Tell our AudioSounds to adjust:
|
||||||
AudioSet::iterator i=_sounds_on_loan.begin();
|
AudioSet::iterator i = _sounds_on_loan.begin();
|
||||||
for (; i!=_sounds_on_loan.end(); ++i) {
|
for (; i != _sounds_on_loan.end(); ++i) {
|
||||||
(*i)->set_play_rate((*i)->get_play_rate());
|
(*i)->set_play_rate((*i)->get_play_rate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,11 +358,12 @@ get_play_rate() const {
|
|||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
set_active(bool active) {
|
set_active(bool active) {
|
||||||
audio_debug("MilesAudioManager::set_active(flag="<<active<<")");
|
audio_debug("MilesAudioManager::set_active(flag="<<active<<")");
|
||||||
if (_active!=active) {
|
ReMutexHolder holder(_lock);
|
||||||
|
if (_active != active) {
|
||||||
_active=active;
|
_active=active;
|
||||||
// Tell our AudioSounds to adjust:
|
// Tell our AudioSounds to adjust:
|
||||||
AudioSet::iterator i=_sounds_on_loan.begin();
|
AudioSet::iterator i = _sounds_on_loan.begin();
|
||||||
for (; i!=_sounds_on_loan.end(); ++i) {
|
for (; i != _sounds_on_loan.end(); ++i) {
|
||||||
(*i)->set_active(_active);
|
(*i)->set_active(_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,8 +390,9 @@ get_active() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
set_concurrent_sound_limit(unsigned int limit) {
|
set_concurrent_sound_limit(unsigned int limit) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
_concurrent_sound_limit = limit;
|
_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
|
// Function: MilesAudioManager::reduce_sounds_playing_to
|
||||||
// Access: Private, Virtual
|
// Access: Public, Virtual
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
reduce_sounds_playing_to(unsigned int count) {
|
reduce_sounds_playing_to(unsigned int count) {
|
||||||
int limit = _sounds_playing.size() - count;
|
ReMutexHolder holder(_lock);
|
||||||
while (limit-- > 0) {
|
do_reduce_sounds_playing_to(count);
|
||||||
SoundsPlaying::iterator sound = _sounds_playing.begin();
|
|
||||||
assert(sound != _sounds_playing.end());
|
|
||||||
(**sound).stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -444,12 +436,33 @@ stop_all_sounds() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
update() {
|
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 (_sounds_finished) {
|
||||||
// If we don't have a sub-thread, we have to service the streams
|
_sounds_finished = false;
|
||||||
// in the main thread.
|
|
||||||
do_service_streams();
|
// 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) {
|
release_sound(MilesAudioSound *audioSound) {
|
||||||
audio_debug("MilesAudioManager::release_sound(audioSound=\""
|
audio_debug("MilesAudioManager::release_sound(audioSound=\""
|
||||||
<<audioSound->get_name()<<"\"), this = " << (void *)this);
|
<<audioSound->get_name()<<"\"), this = " << (void *)this);
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
AudioSet::iterator ai = _sounds_on_loan.find(audioSound);
|
AudioSet::iterator ai = _sounds_on_loan.find(audioSound);
|
||||||
nassertv(ai != _sounds_on_loan.end());
|
nassertv(ai != _sounds_on_loan.end());
|
||||||
_sounds_on_loan.erase(ai);
|
_sounds_on_loan.erase(ai);
|
||||||
@ -480,6 +494,7 @@ void MilesAudioManager::
|
|||||||
cleanup() {
|
cleanup() {
|
||||||
audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this
|
audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this
|
||||||
<< ", _cleanup_required = " << _cleanup_required);
|
<< ", _cleanup_required = " << _cleanup_required);
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
if (!_cleanup_required) {
|
if (!_cleanup_required) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -490,7 +505,7 @@ cleanup() {
|
|||||||
(*ai)->cleanup();
|
(*ai)->cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_cache();
|
do_clear_cache();
|
||||||
|
|
||||||
// Now stop the thread, if it has been started.
|
// Now stop the thread, if it has been started.
|
||||||
if (!_stream_thread.is_null()) {
|
if (!_stream_thread.is_null()) {
|
||||||
@ -519,6 +534,7 @@ cleanup() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
output(ostream &out) const {
|
output(ostream &out) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
out << get_type() << ": " << _sounds_playing.size()
|
out << get_type() << ": " << _sounds_playing.size()
|
||||||
<< " / " << _sounds_on_loan.size() << " sounds playing / total";
|
<< " / " << _sounds_on_loan.size() << " sounds playing / total";
|
||||||
}
|
}
|
||||||
@ -530,15 +546,88 @@ output(ostream &out) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
write(ostream &out) const {
|
write(ostream &out) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
out << (*this) << "\n";
|
out << (*this) << "\n";
|
||||||
AudioSet::const_iterator ai;
|
AudioSet::const_iterator ai;
|
||||||
for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
|
for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
|
||||||
MilesAudioSound *sound = (*ai);
|
MilesAudioSound *sound = (*ai);
|
||||||
out << " " << *sound << "\n";
|
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
|
// Function: MilesAudioManager::start_service_stream
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -580,7 +669,7 @@ stop_service_stream(HSTREAM stream) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MilesAudioManager::most_recently_used
|
// Function: MilesAudioManager::most_recently_used
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description:
|
// Description: Assumes the lock is already held.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
most_recently_used(const string &path) {
|
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:
|
// At this point, path should not exist in the _lru:
|
||||||
assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
|
assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
|
||||||
_lru.push_back(&path);
|
_lru.push_back(&path);
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: MilesAudioManager::uncache_a_sound
|
// Function: MilesAudioManager::uncache_a_sound
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description:
|
// Description: Assumes the lock is already held.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
uncache_a_sound() {
|
uncache_a_sound() {
|
||||||
audio_debug("MilesAudioManager::uncache_a_sound()");
|
audio_debug("MilesAudioManager::uncache_a_sound()");
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
// uncache least recently used:
|
// uncache least recently used:
|
||||||
assert(_lru.size()>0);
|
assert(_lru.size()>0);
|
||||||
LRU::reference path=_lru.front();
|
LRU::reference path=_lru.front();
|
||||||
@ -616,7 +705,7 @@ uncache_a_sound() {
|
|||||||
audio_debug(" uncaching \""<<i->first<<"\"");
|
audio_debug(" uncaching \""<<i->first<<"\"");
|
||||||
_sounds.erase(i);
|
_sounds.erase(i);
|
||||||
}
|
}
|
||||||
assert(is_valid());
|
nassertv(do_is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -626,8 +715,9 @@ uncache_a_sound() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
starting_sound(MilesAudioSound *audio) {
|
starting_sound(MilesAudioSound *audio) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
if (_concurrent_sound_limit) {
|
if (_concurrent_sound_limit) {
|
||||||
reduce_sounds_playing_to(_concurrent_sound_limit);
|
do_reduce_sounds_playing_to(_concurrent_sound_limit);
|
||||||
}
|
}
|
||||||
_sounds_playing.insert(audio);
|
_sounds_playing.insert(audio);
|
||||||
}
|
}
|
||||||
@ -641,6 +731,7 @@ starting_sound(MilesAudioSound *audio) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MilesAudioManager::
|
void MilesAudioManager::
|
||||||
stopping_sound(MilesAudioSound *audio) {
|
stopping_sound(MilesAudioSound *audio) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
_sounds_playing.erase(audio);
|
_sounds_playing.erase(audio);
|
||||||
if (_hasMidiSounds && _sounds_playing.size() == 0) {
|
if (_hasMidiSounds && _sounds_playing.size() == 0) {
|
||||||
GlobalMilesManager::get_global_ptr()->force_midi_reset();
|
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
|
// Description: Reads a sound file and allocates a SoundData pointer
|
||||||
// for it. Returns NULL if the sound file cannot be
|
// for it. Returns NULL if the sound file cannot be
|
||||||
// loaded.
|
// loaded.
|
||||||
|
//
|
||||||
|
// Assumes the lock is already held.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(MilesAudioManager::SoundData) MilesAudioManager::
|
PT(MilesAudioManager::SoundData) MilesAudioManager::
|
||||||
load(const Filename &file_name) {
|
load(const Filename &file_name) {
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "pmutex.h"
|
#include "pmutex.h"
|
||||||
|
#include "reMutex.h"
|
||||||
#include "conditionVar.h"
|
#include "conditionVar.h"
|
||||||
|
|
||||||
class MilesAudioSound;
|
class MilesAudioSound;
|
||||||
@ -65,7 +66,6 @@ public:
|
|||||||
virtual unsigned int get_concurrent_sound_limit() const;
|
virtual unsigned int get_concurrent_sound_limit() const;
|
||||||
|
|
||||||
virtual void reduce_sounds_playing_to(unsigned int count);
|
virtual void reduce_sounds_playing_to(unsigned int count);
|
||||||
|
|
||||||
virtual void stop_all_sounds();
|
virtual void stop_all_sounds();
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
@ -78,6 +78,10 @@ public:
|
|||||||
virtual void write(ostream &out) const;
|
virtual void write(ostream &out) const;
|
||||||
|
|
||||||
private:
|
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 start_service_stream(HSTREAM stream);
|
||||||
void stop_service_stream(HSTREAM stream);
|
void stop_service_stream(HSTREAM stream);
|
||||||
|
|
||||||
@ -123,12 +127,12 @@ private:
|
|||||||
// The offspring of this manager:
|
// The offspring of this manager:
|
||||||
AudioSet _sounds_on_loan;
|
AudioSet _sounds_on_loan;
|
||||||
|
|
||||||
typedef pset<MilesAudioSound* > SoundsPlaying;
|
typedef pset<MilesAudioSound *> SoundsPlaying;
|
||||||
// The sounds from this manager that are currently playing:
|
// The sounds from this manager that are currently playing:
|
||||||
SoundsPlaying _sounds_playing;
|
SoundsPlaying _sounds_playing;
|
||||||
|
|
||||||
// The Least Recently Used mechanism:
|
// The Least Recently Used mechanism:
|
||||||
typedef pdeque<const string* > LRU;
|
typedef pdeque<const string *> LRU;
|
||||||
LRU _lru;
|
LRU _lru;
|
||||||
// State:
|
// State:
|
||||||
float _volume;
|
float _volume;
|
||||||
@ -141,6 +145,10 @@ private:
|
|||||||
bool _is_valid;
|
bool _is_valid;
|
||||||
bool _hasMidiSounds;
|
bool _hasMidiSounds;
|
||||||
|
|
||||||
|
// This mutex protects everything above.
|
||||||
|
ReMutex _lock;
|
||||||
|
bool _sounds_finished;
|
||||||
|
|
||||||
typedef pvector<HSTREAM> Streams;
|
typedef pvector<HSTREAM> Streams;
|
||||||
PT(StreamThread) _stream_thread;
|
PT(StreamThread) _stream_thread;
|
||||||
Streams _streams;
|
Streams _streams;
|
||||||
|
@ -96,6 +96,8 @@ play() {
|
|||||||
&_sd->_raw_data[0], _sd->_raw_data.size(),
|
&_sd->_raw_data[0], _sd->_raw_data.size(),
|
||||||
0);
|
0);
|
||||||
_original_playback_rate = AIL_sample_playback_rate(_sample);
|
_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_volume(_volume);
|
||||||
set_play_rate(_play_rate);
|
set_play_rate(_play_rate);
|
||||||
@ -293,6 +295,19 @@ cleanup() {
|
|||||||
stop();
|
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
|
// Function: MilesAudioSample::internal_stop
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -306,4 +321,20 @@ internal_stop() {
|
|||||||
_sample_index = 0;
|
_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 //]
|
#endif //]
|
||||||
|
@ -56,9 +56,11 @@ public:
|
|||||||
virtual AudioSound::SoundStatus status() const;
|
virtual AudioSound::SoundStatus status() const;
|
||||||
|
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void internal_stop();
|
void internal_stop();
|
||||||
|
static void AILCALLBACK finish_callback(HSAMPLE sample);
|
||||||
|
|
||||||
PT(MilesAudioManager::SoundData) _sd;
|
PT(MilesAudioManager::SoundData) _sd;
|
||||||
HSAMPLE _sample;
|
HSAMPLE _sample;
|
||||||
|
@ -92,6 +92,8 @@ play() {
|
|||||||
_sequence = 0;
|
_sequence = 0;
|
||||||
} else {
|
} else {
|
||||||
AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0);
|
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_volume(_volume);
|
||||||
set_play_rate(_play_rate);
|
set_play_rate(_play_rate);
|
||||||
@ -296,4 +298,20 @@ internal_stop() {
|
|||||||
_sequence_index = 0;
|
_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 //]
|
#endif //]
|
||||||
|
@ -58,6 +58,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void internal_stop();
|
void internal_stop();
|
||||||
|
static void AILCALLBACK finish_callback(HSEQUENCE sequence);
|
||||||
|
|
||||||
PT(MilesAudioManager::SoundData) _sd;
|
PT(MilesAudioManager::SoundData) _sd;
|
||||||
HSEQUENCE _sequence;
|
HSEQUENCE _sequence;
|
||||||
|
@ -77,6 +77,14 @@ play() {
|
|||||||
if (_stream == 0) {
|
if (_stream == 0) {
|
||||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||||
_stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0);
|
_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 {
|
} else {
|
||||||
// We already had the stream open. Keep it open; just restart
|
// We already had the stream open. Keep it open; just restart
|
||||||
// it.
|
// it.
|
||||||
@ -84,29 +92,24 @@ play() {
|
|||||||
_manager->stop_service_stream(_stream);
|
_manager->stop_service_stream(_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stream == 0) {
|
// Start playing:
|
||||||
milesAudio_cat.warning()
|
nassertv(_stream != 0);
|
||||||
<< "Could not play " << _file_name << ": too many open streams\n";
|
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 {
|
} else {
|
||||||
// Start playing:
|
AIL_auto_service_stream(_stream, 1);
|
||||||
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_start_stream(_stream);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// In case _loop_count gets set to forever (zero):
|
// 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 //]
|
#endif //]
|
||||||
|
@ -58,6 +58,8 @@ public:
|
|||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void AILCALLBACK finish_callback(HSTREAM stream);
|
||||||
|
|
||||||
Filename _path;
|
Filename _path;
|
||||||
HSTREAM _stream;
|
HSTREAM _stream;
|
||||||
S32 _original_playback_rate;
|
S32 _original_playback_rate;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user