changed the sound code: added reduce sounds to and set finished event
This commit is contained in:
parent
8f02530c64
commit
24b2117dbc
|
|
@ -716,7 +716,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.musicManagerIsValid=self.musicManager!=None \
|
||||
and self.musicManager.isValid()
|
||||
if self.musicManagerIsValid:
|
||||
self.musicManager.setMutuallyExclusive(1) # ensure only 1 midi song is playing at a time
|
||||
# ensure only 1 midi song is playing at a time:
|
||||
self.musicManager.setConcurrentSoundLimit(1)
|
||||
self.musicManager.setActive(self.musicActive)
|
||||
|
||||
# enableMusic/enableSoundEffects are meant to be called in response to a user request
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ create_AudioManager() {
|
|||
if (!am->is_valid()) {
|
||||
am = create_NullAudioManger();
|
||||
}
|
||||
am->_bExclusive = false;
|
||||
return am;
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +98,3 @@ get_null_sound() {
|
|||
return _null_sound;
|
||||
}
|
||||
|
||||
void AudioManager::
|
||||
set_mutually_exclusive(bool bExclusive) {
|
||||
_bExclusive = bExclusive;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,14 @@ PUBLISHED:
|
|||
|
||||
static PT(AudioManager) create_AudioManager();
|
||||
virtual ~AudioManager() {}
|
||||
|
||||
// If you're interested in knowing whether this audio manager
|
||||
// is valid, here's the call to do it. It is not necessary
|
||||
// to check whether the audio manager is valid before making other
|
||||
// calls. You are free to use an invalid sound manager, you
|
||||
// may get silent sounds from it though. The sound manager and
|
||||
// the sounds it creates should not crash the application even
|
||||
// when the objects are not valid.
|
||||
virtual bool is_valid() = 0;
|
||||
|
||||
// Get a sound:
|
||||
|
|
@ -51,12 +59,8 @@ PUBLISHED:
|
|||
// in its pool/cache.
|
||||
virtual void uncache_sound(const string& file_name) = 0;
|
||||
virtual void clear_cache() = 0;
|
||||
virtual void set_cache_limit(int count) = 0;
|
||||
virtual int get_cache_limit() = 0;
|
||||
|
||||
// if set, turn off any currently-playing sounds before playing
|
||||
// a new one (useful for midi songs)
|
||||
void set_mutually_exclusive(bool bExclusive);
|
||||
virtual void set_cache_limit(unsigned int count) = 0;
|
||||
virtual unsigned int get_cache_limit() const = 0;
|
||||
|
||||
// Control volume:
|
||||
// FYI:
|
||||
|
|
@ -65,7 +69,7 @@ PUBLISHED:
|
|||
// 0 = minimum; 1.0 = maximum.
|
||||
// inits to 1.0.
|
||||
virtual void set_volume(float volume) = 0;
|
||||
virtual float get_volume() = 0;
|
||||
virtual float get_volume() const = 0;
|
||||
|
||||
// Turn the manager on or off.
|
||||
// If you play a sound while the manager is inactive, it won't start.
|
||||
|
|
@ -76,14 +80,42 @@ PUBLISHED:
|
|||
// they will start playing from the begining of their loop.
|
||||
// inits to true.
|
||||
virtual void set_active(bool flag) = 0;
|
||||
virtual bool get_active() = 0;
|
||||
virtual bool get_active() const = 0;
|
||||
|
||||
// This controls the number of sounds that you allow at once. This
|
||||
// is more of a user choice -- it avoids talk over and the creation
|
||||
// of a cacophony.
|
||||
// It can also be used to help performance.
|
||||
// 0 == unlimited.
|
||||
// 1 == mutually exclusive (one sound at a time). Which is an example of:
|
||||
// n == allow n sounds to be playing at the same time.
|
||||
virtual void set_concurrent_sound_limit(unsigned int limit = 0) = 0;
|
||||
virtual unsigned int get_concurrent_sound_limit() const = 0;
|
||||
|
||||
// This is likely to be a utility function for the concurrent_sound_limit
|
||||
// options. It is exposed as an API, because it's reasonable that it
|
||||
// may be useful to be here. It reduces the number of concurrently
|
||||
// playing sounds to count by some implementation specific means.
|
||||
// If the number of sounds currently playing is at or below count then
|
||||
// there is no effect.
|
||||
virtual void reduce_sounds_playing_to(unsigned int count) = 0;
|
||||
|
||||
// Stop playback on all sounds managed by this manager.
|
||||
// This is effectively the same as reduce_sounds_playing_to(0), but
|
||||
// this call may be for efficient on some implementations.
|
||||
virtual void stop_all_sounds() = 0;
|
||||
|
||||
public:
|
||||
static void register_AudioManager_creator(Create_AudioManager_proc* proc);
|
||||
|
||||
protected:
|
||||
friend class AudioSound;
|
||||
|
||||
// Avoid adding data members (instance variables) to this mostly abstract
|
||||
// base class. This allows implementors of various sound systems the
|
||||
// best flexibility.
|
||||
|
||||
static Create_AudioManager_proc* _create_AudioManager;
|
||||
bool _bExclusive;
|
||||
PT(AudioSound) _null_sound;
|
||||
|
||||
AudioManager() {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,11 @@ PUBLISHED:
|
|||
// inits to manager's state.
|
||||
virtual void set_active(bool flag=true) = 0;
|
||||
virtual bool get_active() const = 0;
|
||||
|
||||
// Set (or clear) the event that will be thrown when the sound
|
||||
// finishes playing. To clear the event, pass an empty string.
|
||||
virtual void set_finished_event(const string& event) = 0;
|
||||
virtual const string& get_finished_event() const = 0;
|
||||
|
||||
// There is no set_name(), this is intentional.
|
||||
virtual const string& get_name() const = 0;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ clear_cache() {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NullAudioManager::
|
||||
set_cache_limit(int) {
|
||||
set_cache_limit(unsigned int) {
|
||||
// intentionally blank.
|
||||
}
|
||||
|
||||
|
|
@ -95,8 +95,8 @@ set_cache_limit(int) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NullAudioManager::
|
||||
get_cache_limit() {
|
||||
unsigned int NullAudioManager::
|
||||
get_cache_limit() const {
|
||||
// intentionally blank.
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ set_volume(float) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NullAudioManager::
|
||||
get_volume() {
|
||||
get_volume() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +137,46 @@ set_active(bool) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NullAudioManager::
|
||||
get_active() {
|
||||
get_active() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NullAudioManager::set_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NullAudioManager::
|
||||
set_concurrent_sound_limit(unsigned int) {
|
||||
// intentionally blank.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NullAudioManager::get_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
unsigned int NullAudioManager::
|
||||
get_concurrent_sound_limit() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NullAudioManager::reduce_sounds_playing_to
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NullAudioManager::
|
||||
reduce_sounds_playing_to(unsigned int) {
|
||||
// intentionally blank.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NullAudioManager::stop_all_sounds
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NullAudioManager::
|
||||
stop_all_sounds() {
|
||||
// intentionally blank.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,21 @@ public:
|
|||
virtual PT(AudioSound) get_sound(const string&);
|
||||
virtual void uncache_sound(const string&);
|
||||
virtual void clear_cache();
|
||||
virtual void set_cache_limit(int);
|
||||
virtual int get_cache_limit();
|
||||
virtual void set_cache_limit(unsigned int);
|
||||
virtual unsigned int get_cache_limit() const;
|
||||
|
||||
virtual void set_volume(float);
|
||||
virtual float get_volume();
|
||||
virtual float get_volume() const;
|
||||
|
||||
virtual void set_active(bool);
|
||||
virtual bool get_active();
|
||||
virtual bool get_active() const;
|
||||
|
||||
virtual void set_concurrent_sound_limit(unsigned int limit);
|
||||
virtual unsigned int get_concurrent_sound_limit() const;
|
||||
|
||||
virtual void reduce_sounds_playing_to(unsigned int count);
|
||||
|
||||
virtual void stop_all_sounds();
|
||||
};
|
||||
|
||||
#endif /* __NULL_AUDIO_MANAGER_H__ */
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#include "nullAudioSound.h"
|
||||
|
||||
|
||||
namespace {
|
||||
static const string blank="";
|
||||
}
|
||||
|
||||
NullAudioSound::NullAudioSound() {
|
||||
// Intentionally blank.
|
||||
}
|
||||
|
|
@ -84,8 +88,15 @@ bool NullAudioSound::get_active() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void NullAudioSound::set_finished_event(const string& event) {
|
||||
// Intentionally blank.
|
||||
}
|
||||
|
||||
const string& NullAudioSound::get_finished_event() const {
|
||||
return blank;
|
||||
}
|
||||
|
||||
const string& NullAudioSound::get_name() const {
|
||||
static const string blank="";
|
||||
return blank;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ public:
|
|||
|
||||
void set_active(bool);
|
||||
bool get_active() const;
|
||||
|
||||
void set_finished_event(const string& event);
|
||||
const string& get_finished_event() const;
|
||||
|
||||
const string& get_name() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ FmodAudioManager() {
|
|||
|
||||
_active = audio_active;
|
||||
_cache_limit = audio_cache_limit;
|
||||
_concurrent_sound_limit = 0;
|
||||
|
||||
// Initialize FMOD, if this is the first manager created.
|
||||
_is_valid = true;
|
||||
|
|
@ -62,20 +63,19 @@ FmodAudioManager() {
|
|||
audio_debug("Initializing FMOD for real.");
|
||||
float fmod_dll_version = FSOUND_GetVersion();
|
||||
if (fmod_dll_version < FMOD_VERSION) {
|
||||
audio_error("Wrong FMOD DLL version. You have "<<fmod_dll_version
|
||||
<<". You need "<<FMOD_VERSION);
|
||||
_is_valid = false;
|
||||
break;
|
||||
audio_error("Wrong FMOD DLL version. You have "<<fmod_dll_version
|
||||
<<". You need "<<FMOD_VERSION);
|
||||
_is_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FSOUND_Init(44100, 32, 0) == 0) {
|
||||
audio_error("Fmod initialization failure.");
|
||||
_is_valid = false;
|
||||
break;
|
||||
audio_error("Fmod initialization failure.");
|
||||
_is_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while(0);
|
||||
while(0); // curious -- why is there a non-loop here?
|
||||
}
|
||||
|
||||
// increment regardless of whether an error has occured -- the
|
||||
|
|
@ -222,7 +222,7 @@ get_sound(const string &file_name) {
|
|||
// Build a new AudioSound from the audio data.
|
||||
PT(AudioSound) audioSound = 0;
|
||||
PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, stream, path,
|
||||
length);
|
||||
length);
|
||||
fmodAudioSound->set_active(_active);
|
||||
_soundsOnLoan.insert(fmodAudioSound);
|
||||
audioSound = fmodAudioSound;
|
||||
|
|
@ -263,7 +263,7 @@ uncache_sound(const string& file_name) {
|
|||
// If the refcount is already zero, it can be
|
||||
// purged right now!
|
||||
audio_debug("FmodAudioManager::uncache_sound: purging "<<path
|
||||
<< " from the cache.");
|
||||
<< " from the cache.");
|
||||
delete [] entry->data;
|
||||
|
||||
// Erase the sound from the LRU list as well.
|
||||
|
|
@ -324,7 +324,7 @@ most_recently_used(const string& path) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::clear_cache
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Clear out the sound cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
clear_cache() {
|
||||
|
|
@ -340,7 +340,7 @@ clear_cache() {
|
|||
SoundCacheEntry *entry = &(*itor).second;
|
||||
if (entry->refcount == 0) {
|
||||
audio_debug("FmodAudioManager::clear_cache: purging "<< (*itor).first
|
||||
<< " from the cache.");
|
||||
<< " from the cache.");
|
||||
delete [] entry->data;
|
||||
|
||||
// Erase the sound from the LRU list as well.
|
||||
|
|
@ -361,18 +361,15 @@ clear_cache() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::set_cache_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Set the number of sounds that the cache can hold.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
set_cache_limit(int count) {
|
||||
audio_debug("FmodAudioManager::set_cache_limit(count="
|
||||
<<count<<")");
|
||||
set_cache_limit(unsigned int count) {
|
||||
audio_debug("FmodAudioManager::set_cache_limit(count="<<count<<")");
|
||||
assert(is_valid());
|
||||
|
||||
while (_lru.size() > (unsigned int) count) {
|
||||
while (_lru.size() > count) {
|
||||
uncache_a_sound();
|
||||
}
|
||||
|
||||
_cache_limit = count;
|
||||
assert(is_valid());
|
||||
}
|
||||
|
|
@ -385,7 +382,7 @@ set_cache_limit(int count) {
|
|||
int FmodAudioManager::
|
||||
get_cache_limit() {
|
||||
audio_debug("FmodAudioManager::get_cache_limit() returning "
|
||||
<<_cache_limit);
|
||||
<<_cache_limit);
|
||||
return _cache_limit;
|
||||
}
|
||||
|
||||
|
|
@ -451,18 +448,56 @@ get_active() {
|
|||
return _active;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::set_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
set_concurrent_sound_limit(unsigned int limit) {
|
||||
_concurrent_sound_limit = limit;
|
||||
reduce_sounds_playing_to(_concurrent_sound_limit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::get_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
unsigned int FmodAudioManager::
|
||||
get_concurrent_sound_limit() const {
|
||||
return _concurrent_sound_limit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::reduce_sounds_playing_to
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
reduce_sounds_playing_to(unsigned int count) {
|
||||
// This is an example from Miles audio, this should be done for fmod:
|
||||
//int limit = _sounds_playing.size() - count;
|
||||
//while (limit-- > 0) {
|
||||
// SoundsPlaying::iterator sound = _sounds_playing.begin();
|
||||
// assert(sound != _sounds_playing.end());
|
||||
// (**sound).stop();
|
||||
//}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FmodAudioManager::stop_all_sounds
|
||||
// Access: Public
|
||||
// Description: Stop playback on all sounds managed by this manager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FmodAudioManager::
|
||||
stop_all_sounds(void) {
|
||||
stop_all_sounds() {
|
||||
audio_debug("FmodAudioManager::stop_all_sounds()");
|
||||
AudioSet::iterator i=_soundsOnLoan.begin();
|
||||
for (; i!=_soundsOnLoan.end(); ++i) {
|
||||
if((**i).status()==AudioSound::PLAYING)
|
||||
if ((**i).status()==AudioSound::PLAYING) {
|
||||
(**i).stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +519,7 @@ inc_refcount(const string& file_name) {
|
|||
entry->refcount++;
|
||||
entry->stale = false; // definitely not stale!
|
||||
audio_debug("FmodAudioManager: "<<path<<" has a refcount of "
|
||||
<< entry->refcount);
|
||||
<< entry->refcount);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -502,7 +537,7 @@ dec_refcount(const string& file_name) {
|
|||
SoundCacheEntry *entry = &(*itor).second;
|
||||
entry->refcount--;
|
||||
audio_debug("FmodAudioManager: "<<path<<" has a refcount of "
|
||||
<< entry->refcount);
|
||||
<< entry->refcount);
|
||||
if (entry->refcount == 0 && entry->stale) {
|
||||
audio_debug("FmodAudioManager::dec_refcount: purging "<<path<< " from the cache.");
|
||||
delete [] entry->data;
|
||||
|
|
@ -537,7 +572,7 @@ load(const Filename& filename, size_t &size) const {
|
|||
}
|
||||
if (!bSupported) {
|
||||
audio_error("FmodAudioManager::load: "<<filename
|
||||
<<" is not a supported file format.");
|
||||
<<" is not a supported file format.");
|
||||
audio_error("Supported formats are: WAV, MP3, MIDI");
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __FMOD_AUDIO_MANAGER_H__
|
||||
#define __FMOD_AUDIO_MANAGER_H__
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_FMOD //[
|
||||
|
||||
#include "audioManager.h"
|
||||
|
|
@ -30,7 +30,7 @@ class FmodAudioSound;
|
|||
#include "pmap.h"
|
||||
#include "pset.h"
|
||||
|
||||
#include <fmod.h>
|
||||
#include <fmod.h> // Is fmod.h really a system file? I think maybe this should be "fmod.h".
|
||||
|
||||
class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
|
||||
// All of these methods are stubbed out to some degree.
|
||||
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual PT(AudioSound) get_sound(const string&);
|
||||
virtual void uncache_sound(const string&);
|
||||
virtual void clear_cache();
|
||||
virtual void set_cache_limit(int);
|
||||
virtual void set_cache_limit(unsigned int count);
|
||||
virtual int get_cache_limit();
|
||||
|
||||
// Indicates that the given sound was the most recently used.
|
||||
|
|
@ -60,7 +60,13 @@ public:
|
|||
|
||||
virtual void set_active(bool);
|
||||
virtual bool get_active();
|
||||
void stop_all_sounds();
|
||||
|
||||
virtual void set_concurrent_sound_limit(unsigned int limit = 0);
|
||||
virtual unsigned int get_concurrent_sound_limit() const;
|
||||
|
||||
virtual void reduce_sounds_playing_to(unsigned int count);
|
||||
|
||||
virtual void stop_all_sounds();
|
||||
|
||||
protected:
|
||||
// increment or decrement the refcount of the given file's cache entry.
|
||||
|
|
@ -80,6 +86,7 @@ private:
|
|||
typedef pset<FmodAudioSound* > AudioSet;
|
||||
// The offspring of this manager:
|
||||
AudioSet _soundsOnLoan;
|
||||
unsigned int _concurrent_sound_limit;
|
||||
|
||||
// The Least Recently Used mechanism:
|
||||
typedef pdeque<string> LRU;
|
||||
|
|
|
|||
|
|
@ -34,14 +34,14 @@
|
|||
|
||||
FmodAudioSound::
|
||||
FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data,
|
||||
string file_name, float length)
|
||||
string file_name, float length)
|
||||
: _manager(manager), _audio(audio_data), _file_name(file_name),
|
||||
_volume(1.0f), _balance(0), _loop_count(1), _length(length),
|
||||
_active(true), _paused(false), _channel(-1) {
|
||||
nassertv(!file_name.empty());
|
||||
nassertv(audio_data != NULL);
|
||||
audio_debug("FmodAudioSound(manager=0x"<<(void*)&manager
|
||||
<<", file_name="<<file_name<<")");
|
||||
<<", file_name="<<file_name<<")");
|
||||
}
|
||||
|
||||
FmodAudioSound::
|
||||
|
|
@ -56,16 +56,14 @@ play() {
|
|||
if (!_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_manager->_bExclusive) {
|
||||
// stop any other sound that parent mgr is playing
|
||||
_manager->stop_all_sounds();
|
||||
}
|
||||
|
||||
// If the sound is already playing, stop it.
|
||||
if (this->status() == AudioSound::PLAYING) {
|
||||
this->stop();
|
||||
}
|
||||
if (_manager->stop_a_sound()) {
|
||||
// stop another sound that parent mgr is playing
|
||||
_manager->stop_all_sounds();
|
||||
}
|
||||
|
||||
// Play the stream, but start it paused so we can set the volume and
|
||||
// panning first.
|
||||
|
|
@ -92,7 +90,9 @@ play() {
|
|||
// Delay until the channel is actually playing. This shouldn't
|
||||
// result in a noticeable delay, and allows you to immediately test
|
||||
// the status of the sound after initiating playback.
|
||||
while (!FSOUND_IsPlaying(_channel));
|
||||
while (!FSOUND_IsPlaying(_channel)) {
|
||||
// intentinaly empty loop.
|
||||
}
|
||||
}
|
||||
|
||||
void FmodAudioSound::stop() {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ public:
|
|||
// inits to manager's state.
|
||||
void set_active(bool active=true);
|
||||
bool get_active() const;
|
||||
|
||||
void set_finished_event(const string& event);
|
||||
const string& get_finished_event() const;
|
||||
|
||||
const string& get_name() const;
|
||||
|
||||
|
|
@ -92,7 +95,7 @@ private:
|
|||
int _channel;
|
||||
|
||||
FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data,
|
||||
string file_name, float length=0.0f);
|
||||
string file_name, float length=0.0f);
|
||||
|
||||
// forbidden functions!
|
||||
FmodAudioSound(const FmodAudioSound& rhs) {}
|
||||
|
|
|
|||
|
|
@ -32,54 +32,49 @@
|
|||
int MilesAudioManager::_active_managers = 0;
|
||||
HDLSFILEID MilesAudioManager::_dls_field = NULL;
|
||||
bool bMilesShutdownCalled = false;
|
||||
bool bMilesShutdownAtExitRegistered = false;
|
||||
|
||||
PT(AudioManager) Create_AudioManager() {
|
||||
audio_debug("Create_AudioManager() Miles.");
|
||||
return new MilesAudioManager();
|
||||
}
|
||||
|
||||
void fMilesShutdown(void) {
|
||||
if(bMilesShutdownCalled)
|
||||
return;
|
||||
void CustomMilesShutdown() {
|
||||
if (bMilesShutdownCalled) {
|
||||
return;
|
||||
}
|
||||
bMilesShutdownCalled = true;
|
||||
|
||||
bMilesShutdownCalled = true;
|
||||
|
||||
if (MilesAudioManager::_dls_field!=NULL) {
|
||||
HDLSDEVICE dls= NULL;
|
||||
AIL_quick_handles(0, 0, &dls);
|
||||
if(dls!=NULL) {
|
||||
AIL_DLS_unload(dls,MilesAudioManager::_dls_field);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG //[
|
||||
// Clear _dls_field in debug version (for assert in ctor):
|
||||
MilesAudioManager::_dls_field = NULL;
|
||||
#endif //]
|
||||
if (MilesAudioManager::_dls_field!=NULL) {
|
||||
HDLSDEVICE dls= NULL;
|
||||
AIL_quick_handles(0, 0, &dls);
|
||||
if (dls!=NULL) {
|
||||
AIL_DLS_unload(dls,MilesAudioManager::_dls_field);
|
||||
}
|
||||
#ifndef NDEBUG //[
|
||||
// Clear _dls_field in debug version (for assert in ctor):
|
||||
MilesAudioManager::_dls_field = NULL;
|
||||
#endif //]
|
||||
}
|
||||
|
||||
|
||||
#define SHUTDOWN_HACK
|
||||
|
||||
// if python crashes, the midi notes are left on,
|
||||
// so we need to turn them off. Unfortunately
|
||||
// in Miles 6.5, AIL_quick_shutdown() crashes
|
||||
// when it's called from atexit after a python crash, probably
|
||||
// because mss32.dll has already been unloaded
|
||||
// workaround: use these internal values in the miles struct
|
||||
// to reset the win32 midi ourselves
|
||||
|
||||
#ifdef SHUTDOWN_HACK
|
||||
HMDIDRIVER hMid=NULL;
|
||||
AIL_quick_handles(0, &hMid, 0);
|
||||
if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
|
||||
midiOutReset(hMid->hMidiOut);
|
||||
midiOutClose(hMid->hMidiOut);
|
||||
}
|
||||
#else
|
||||
audio_debug(" AIL_quick_shutdown()");
|
||||
AIL_quick_shutdown();
|
||||
#endif
|
||||
#define SHUTDOWN_HACK
|
||||
// if python crashes, the midi notes are left on,
|
||||
// so we need to turn them off. Unfortunately
|
||||
// in Miles 6.5, AIL_quick_shutdown() crashes
|
||||
// when it's called from atexit after a python crash, probably
|
||||
// because mss32.dll has already been unloaded
|
||||
// workaround: use these internal values in the miles struct
|
||||
// to reset the win32 midi ourselves
|
||||
#ifdef SHUTDOWN_HACK
|
||||
HMDIDRIVER hMid=NULL;
|
||||
AIL_quick_handles(0, &hMid, 0);
|
||||
if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
|
||||
midiOutReset(hMid->hMidiOut);
|
||||
midiOutClose(hMid->hMidiOut);
|
||||
}
|
||||
#else
|
||||
audio_debug(" AIL_quick_shutdown()");
|
||||
AIL_quick_shutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -95,8 +90,9 @@ MilesAudioManager() {
|
|||
_active = audio_active;
|
||||
_volume = audio_volume;
|
||||
_cache_limit = audio_cache_limit;
|
||||
_concurrent_sound_limit = 0;
|
||||
_is_valid = true;
|
||||
_bHasMidiSounds = false;
|
||||
_hasMidiSounds = false;
|
||||
if (_active_managers==0) {
|
||||
S32 use_digital=(audio_play_wave || audio_play_mp3)?1:0;
|
||||
S32 use_MIDI=(audio_play_midi)?1:0;
|
||||
|
|
@ -146,7 +142,7 @@ MilesAudioManager() {
|
|||
audio_info(" using Miles software midi");
|
||||
}
|
||||
} else {
|
||||
audio_info(" using Miles hardware midi");
|
||||
audio_info(" using Miles hardware midi");
|
||||
}
|
||||
|
||||
if (use_vfs) {
|
||||
|
|
@ -169,9 +165,10 @@ MilesAudioManager() {
|
|||
if (_is_valid) {
|
||||
assert(is_valid());
|
||||
|
||||
if(!bMilesShutdownAtExitRegistered) {
|
||||
bMilesShutdownAtExitRegistered = true;
|
||||
atexit(fMilesShutdown);
|
||||
static bool atexit_registered = false;
|
||||
if(!atexit_registered) {
|
||||
atexit_registered = true;
|
||||
atexit(CustomMilesShutdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +182,7 @@ MilesAudioManager::
|
|||
~MilesAudioManager() {
|
||||
audio_debug("MilesAudioManager::~MilesAudioManager()");
|
||||
// Be sure to delete associated sounds before deleting the manager:
|
||||
nassertv(_soundsOnLoan.empty());
|
||||
nassertv(_sounds_on_loan.empty());
|
||||
clear_cache();
|
||||
--_active_managers;
|
||||
audio_debug(" _active_managers="<<_active_managers);
|
||||
|
|
@ -238,10 +235,8 @@ is_valid() {
|
|||
HAUDIO MilesAudioManager::
|
||||
load(Filename file_name) {
|
||||
HAUDIO audio;
|
||||
|
||||
if (use_vfs) {
|
||||
audio = AIL_quick_load(file_name.c_str());
|
||||
|
||||
} else {
|
||||
string stmp = file_name.to_os_specific();
|
||||
audio_debug(" \"" << stmp << "\"");
|
||||
|
|
@ -318,11 +313,11 @@ get_sound(const string& file_name) {
|
|||
=new MilesAudioSound(this, audio, (*si).first);
|
||||
nassertr(milesAudioSound, 0);
|
||||
milesAudioSound->set_active(_active);
|
||||
_soundsOnLoan.insert(milesAudioSound);
|
||||
_sounds_on_loan.insert(milesAudioSound);
|
||||
audioSound=milesAudioSound;
|
||||
}
|
||||
|
||||
_bHasMidiSounds |= (file_name.find(".mid")!=string::npos);
|
||||
_hasMidiSounds |= (file_name.find(".mid")!=string::npos);
|
||||
audio_debug(" returning 0x" << (void*)audioSound);
|
||||
assert(is_valid());
|
||||
return audioSound;
|
||||
|
|
@ -406,7 +401,7 @@ most_recently_used(const string& path) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::clear_cache
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Clear out the sound cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
clear_cache() {
|
||||
|
|
@ -424,14 +419,13 @@ clear_cache() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::set_cache_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Set the number of sounds that the cache can hold.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
set_cache_limit(int count) {
|
||||
audio_debug("MilesAudioManager::set_cache_limit(count="
|
||||
<<count<<")");
|
||||
set_cache_limit(unsigned int count) {
|
||||
audio_debug("MilesAudioManager::set_cache_limit(count="<<count<<")");
|
||||
assert(is_valid());
|
||||
while (_lru.size() > (unsigned int) count) {
|
||||
while (_lru.size() > count) {
|
||||
uncache_a_sound();
|
||||
}
|
||||
_cache_limit=count;
|
||||
|
|
@ -443,8 +437,8 @@ set_cache_limit(int count) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int MilesAudioManager::
|
||||
get_cache_limit() {
|
||||
unsigned int MilesAudioManager::
|
||||
get_cache_limit() const {
|
||||
audio_debug("MilesAudioManager::get_cache_limit() returning "
|
||||
<<_cache_limit);
|
||||
return _cache_limit;
|
||||
|
|
@ -459,7 +453,7 @@ void MilesAudioManager::
|
|||
release_sound(MilesAudioSound* audioSound) {
|
||||
audio_debug("MilesAudioManager::release_sound(audioSound=\""
|
||||
<<audioSound->get_name()<<"\")");
|
||||
_soundsOnLoan.erase(audioSound);
|
||||
_sounds_on_loan.erase(audioSound);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -473,53 +467,43 @@ set_volume(float volume) {
|
|||
if (_volume!=volume) {
|
||||
_volume = volume;
|
||||
// Tell our AudioSounds to adjust:
|
||||
AudioSet::iterator i=_soundsOnLoan.begin();
|
||||
for (; i!=_soundsOnLoan.end(); ++i) {
|
||||
AudioSet::iterator i=_sounds_on_loan.begin();
|
||||
for (; i!=_sounds_on_loan.end(); ++i) {
|
||||
(**i).set_volume((**i).get_volume());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::force_midi_reset
|
||||
// Access: Public
|
||||
// Description: ?????.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
stop_all_sounds(void) {
|
||||
audio_debug("MilesAudioManager::stop_all_sounds()");
|
||||
AudioSet::iterator i=_soundsOnLoan.begin();
|
||||
for (; i!=_soundsOnLoan.end(); ++i) {
|
||||
if((**i).status()==AudioSound::PLAYING)
|
||||
(**i).stop();
|
||||
force_midi_reset() {
|
||||
if (!miles_audio_force_midi_reset) {
|
||||
audio_debug("MilesAudioManager::skipping force_midi_reset");
|
||||
return;
|
||||
}
|
||||
audio_debug("MilesAudioManager::force_midi_reset");
|
||||
|
||||
if(_bHasMidiSounds) {
|
||||
forceMidiReset();
|
||||
// sometimes Miles seems to leave midi notes hanging, even after stop is called,
|
||||
// so perform an explicit reset using winMM.dll calls, just to ensure silence.
|
||||
HMDIDRIVER hMid=NULL;
|
||||
AIL_quick_handles(0, &hMid, 0);
|
||||
if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
|
||||
audio_debug("MilesAudioManager::calling midiOutReset");
|
||||
midiOutReset(hMid->hMidiOut);
|
||||
}
|
||||
}
|
||||
|
||||
void MilesAudioManager::
|
||||
forceMidiReset(void) {
|
||||
if(!miles_audio_force_midi_reset) {
|
||||
audio_debug("MilesAudioManager::skipping forceMidiReset");
|
||||
return;
|
||||
}
|
||||
|
||||
audio_debug("MilesAudioManager::ForceMidiReset");
|
||||
|
||||
// sometimes Miles seems to leave midi notes hanging, even after stop is called,
|
||||
// so perform an explicit reset using winMM.dll calls, just to ensure silence.
|
||||
HMDIDRIVER hMid=NULL;
|
||||
AIL_quick_handles(0, &hMid, 0);
|
||||
if ((hMid!=NULL) && (hMid->deviceid != MIDI_NULL_DRIVER) && (hMid->hMidiOut != NULL)) {
|
||||
audio_debug("MilesAudioManager::calling midiOutReset");
|
||||
midiOutReset(hMid->hMidiOut);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::get_volume
|
||||
// Access: Public
|
||||
// Description: get the overall volume
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioManager::
|
||||
get_volume() {
|
||||
get_volume() const {
|
||||
audio_debug("MilesAudioManager::get_volume() returning "<<_volume);
|
||||
return _volume;
|
||||
}
|
||||
|
|
@ -535,13 +519,13 @@ set_active(bool active) {
|
|||
if (_active!=active) {
|
||||
_active=active;
|
||||
// Tell our AudioSounds to adjust:
|
||||
AudioSet::iterator i=_soundsOnLoan.begin();
|
||||
for (; i!=_soundsOnLoan.end(); ++i) {
|
||||
AudioSet::iterator i=_sounds_on_loan.begin();
|
||||
for (; i!=_sounds_on_loan.end(); ++i) {
|
||||
(**i).set_active(_active);
|
||||
}
|
||||
|
||||
if((!_active) && _bHasMidiSounds) {
|
||||
forceMidiReset();
|
||||
if((!_active) && _hasMidiSounds) {
|
||||
force_midi_reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -552,11 +536,86 @@ set_active(bool active) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MilesAudioManager::
|
||||
get_active() {
|
||||
get_active() const {
|
||||
audio_debug("MilesAudioManager::get_active() returning "<<_active);
|
||||
return _active;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::starting_sound
|
||||
// Access:
|
||||
// Description: Inform the manager that a sound is about to play.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
starting_sound(MilesAudioSound* audio) {
|
||||
if (_concurrent_sound_limit) {
|
||||
reduce_sounds_playing_to(_concurrent_sound_limit);
|
||||
}
|
||||
_sounds_playing.insert(audio);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::stoping_sound
|
||||
// Access:
|
||||
// Description: Inform the manager that a sound is finished or
|
||||
// someone called stop on the sound (this should not
|
||||
// be called if a sound is only paused).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
stoping_sound(MilesAudioSound* audio) {
|
||||
_sounds_playing.erase(audio);
|
||||
if (_hasMidiSounds && _sounds_playing.size() == 0) {
|
||||
force_midi_reset();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::set_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
set_concurrent_sound_limit(unsigned int limit) {
|
||||
_concurrent_sound_limit = limit;
|
||||
reduce_sounds_playing_to(_concurrent_sound_limit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::get_concurrent_sound_limit
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
unsigned int MilesAudioManager::
|
||||
get_concurrent_sound_limit() const {
|
||||
return _concurrent_sound_limit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::reduce_sounds_playing_to
|
||||
// Access: Private
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::stop_all_sounds
|
||||
// Access: Public
|
||||
// Description: Stop playback on all sounds managed by this manager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioManager::
|
||||
stop_all_sounds() {
|
||||
audio_debug("MilesAudioManager::stop_all_sounds()");
|
||||
reduce_sounds_playing_to(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioManager::get_registry_entry
|
||||
// Access: private
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __MILES_AUDIO_MANAGER_H__ //[
|
||||
#define __MILES_AUDIO_MANAGER_H__
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "audioManager.h"
|
||||
|
|
@ -43,16 +43,21 @@ public:
|
|||
PT(AudioSound) get_sound(const string& file_name);
|
||||
void uncache_sound(const string& file_name);
|
||||
void clear_cache();
|
||||
void set_cache_limit(int count);
|
||||
int get_cache_limit();
|
||||
void set_cache_limit(unsigned int count);
|
||||
unsigned int get_cache_limit() const;
|
||||
|
||||
void set_volume(float volume);
|
||||
float get_volume();
|
||||
float get_volume() const;
|
||||
|
||||
void set_active(bool active);
|
||||
bool get_active();
|
||||
bool get_active() const;
|
||||
|
||||
void set_concurrent_sound_limit(unsigned int limit = 0);
|
||||
unsigned int get_concurrent_sound_limit() const;
|
||||
|
||||
void reduce_sounds_playing_to(unsigned int count);
|
||||
|
||||
void stop_all_sounds();
|
||||
void forceMidiReset();
|
||||
|
||||
// Optional Downloadable Sound field for software midi:
|
||||
// made public so C atexit fn can access it
|
||||
|
|
@ -65,7 +70,11 @@ private:
|
|||
|
||||
typedef pset<MilesAudioSound* > AudioSet;
|
||||
// The offspring of this manager:
|
||||
AudioSet _soundsOnLoan;
|
||||
AudioSet _sounds_on_loan;
|
||||
|
||||
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;
|
||||
|
|
@ -76,9 +85,10 @@ private:
|
|||
int _cache_limit;
|
||||
// keep a count for startup and shutdown:
|
||||
static int _active_managers;
|
||||
unsigned int _concurrent_sound_limit;
|
||||
|
||||
bool _is_valid;
|
||||
bool _bHasMidiSounds;
|
||||
bool _hasMidiSounds;
|
||||
|
||||
HAUDIO load(Filename file_name);
|
||||
// Tell the manager that the sound dtor was called.
|
||||
|
|
@ -87,6 +97,9 @@ private:
|
|||
void most_recently_used(const string& path);
|
||||
void uncache_a_sound();
|
||||
|
||||
void starting_sound(MilesAudioSound* audio);
|
||||
void stoping_sound(MilesAudioSound* audio);
|
||||
|
||||
// utility function that should be moved to another class:
|
||||
bool get_registry_entry(HKEY base,
|
||||
const char* subKeyName,
|
||||
|
|
@ -95,6 +108,8 @@ private:
|
|||
// get the default dls file path:
|
||||
void get_gm_file_path(string& result);
|
||||
|
||||
void force_midi_reset();
|
||||
|
||||
// These are "callback" functions that implement vfs-style I/O for
|
||||
// Miles.
|
||||
static U32 AILCALLBACK vfs_open_callback(const char *filename, U32 *file_handle);
|
||||
|
|
@ -102,7 +117,7 @@ private:
|
|||
static S32 AILCALLBACK vfs_seek_callback(U32 file_handle, S32 offset, U32 type);
|
||||
static void AILCALLBACK vfs_close_callback(U32 file_handle);
|
||||
|
||||
friend MilesAudioSound;
|
||||
friend class MilesAudioSound;
|
||||
};
|
||||
|
||||
EXPCL_MILES_AUDIO PT(AudioManager) Create_AudioManager();
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "throw_event.h"
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioManager.h"
|
||||
|
||||
|
|
@ -45,6 +46,72 @@
|
|||
return 'x'; // bad.
|
||||
}
|
||||
}
|
||||
|
||||
AILSEQUENCECB sequence_callback = 0;
|
||||
AILSAMPLECB sample_callback = 0;
|
||||
const user_data_index = 7;
|
||||
|
||||
void AILCALLBACK
|
||||
pandaAudioAilCallback_Sequence(HSEQUENCE S) {
|
||||
assert(S);
|
||||
audio_debug("pandaAudioAilCallback_Sequence(HSEQUENCE="<<((void*)S)<<")");
|
||||
MilesAudioSound* sound = (MilesAudioSound*)AIL_sequence_user_data(
|
||||
S, user_data_index);
|
||||
assert(sound);
|
||||
sound->finished();
|
||||
if (sequence_callback) {
|
||||
sequence_callback(S);
|
||||
}
|
||||
}
|
||||
|
||||
void AILCALLBACK
|
||||
pandaAudioAilCallback_Sample(HSAMPLE S) {
|
||||
assert(S);
|
||||
audio_debug("pandaAudioAilCallback_Sample(HSAMPLE="<<((void*)S)<<")");
|
||||
MilesAudioSound* sound = (MilesAudioSound*)AIL_sample_user_data(
|
||||
S, user_data_index);
|
||||
assert(sound);
|
||||
sound->finished();
|
||||
if (sample_callback) {
|
||||
sample_callback(S);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
panda_AIL_quick_set_finished_callback(HAUDIO audio, MilesAudioSound* sound) {
|
||||
audio_debug("panda_AIL_quick_set_finished_callback(audio="<<((void*)audio)
|
||||
<<", sound="<<((void*)sound)<<")");
|
||||
if (!audio || !sound) {
|
||||
return;
|
||||
}
|
||||
AIL_lock();
|
||||
if (audio->handle != NULL) {
|
||||
switch (audio->type) {
|
||||
case AIL_QUICK_XMIDI_TYPE:
|
||||
audio_debug(" AIL_register_sequence_callback");
|
||||
AIL_set_sequence_user_data(
|
||||
(HSEQUENCE)audio->handle, user_data_index, (long)sound);
|
||||
sequence_callback=AIL_register_sequence_callback(
|
||||
(HSEQUENCE)audio->handle, pandaAudioAilCallback_Sequence);
|
||||
audio_debug( "AILCALLBACK "<<((void*)sequence_callback));
|
||||
break;
|
||||
case AIL_QUICK_DIGITAL_TYPE:
|
||||
case AIL_QUICK_MPEG_DIGITAL_TYPE:
|
||||
audio_debug(" AIL_register_EOS_callback");
|
||||
AIL_set_sample_user_data(
|
||||
(HSAMPLE)audio->handle, user_data_index, (long)sound);
|
||||
sample_callback=AIL_register_EOS_callback(
|
||||
(HSAMPLE)audio->handle, pandaAudioAilCallback_Sample);
|
||||
audio_debug(" AILCALLBACK "<<((void*)sample_callback));
|
||||
break;
|
||||
default:
|
||||
audio_debug(" unknown audio type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
AIL_unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define miles_audio_debug(x) \
|
||||
|
|
@ -72,6 +139,7 @@ MilesAudioSound(MilesAudioManager* manager,
|
|||
MilesAudioSound::
|
||||
~MilesAudioSound() {
|
||||
miles_audio_debug("~MilesAudioSound()");
|
||||
stop();
|
||||
_manager->release_sound(this);
|
||||
AIL_quick_unload(_audio);
|
||||
}
|
||||
|
|
@ -86,12 +154,14 @@ play() {
|
|||
|
||||
miles_audio_debug("play()");
|
||||
if (_active) {
|
||||
if(_manager->_bExclusive) {
|
||||
// stop any other sound that parent mgr is playing
|
||||
_manager->stop_all_sounds();
|
||||
if (status() == AudioSound::PLAYING) {
|
||||
stop();
|
||||
}
|
||||
_manager->starting_sound(this);
|
||||
// Start playing:
|
||||
if (AIL_quick_play(_audio, _loop_count)) {
|
||||
panda_AIL_quick_set_finished_callback(_audio, this);
|
||||
assert(status()==PLAYING);
|
||||
audio_debug(" started sound " << _file_name );
|
||||
} else {
|
||||
audio_debug(" sound " << _file_name<<" failed to start, err: " <<AIL_last_error());
|
||||
|
|
@ -105,27 +175,25 @@ play() {
|
|||
|
||||
void MilesAudioSound::
|
||||
stop() {
|
||||
#if 0
|
||||
if(_file_name.find(".mid")!=string::npos) {
|
||||
miles_audio_debug("stop() midi");
|
||||
}
|
||||
#endif
|
||||
miles_audio_debug("stopping snd " << _file_name);
|
||||
_paused=false;
|
||||
miles_audio_debug("stop()");
|
||||
_manager->stoping_sound(this);
|
||||
// The _paused flag should not be cleared here. _paused is not like
|
||||
// the Pause button on a cd/dvd player. It is used as a flag to say
|
||||
// that it was looping when it was set inactive. There is no need to
|
||||
// make this symetrical with play(). set_active() is the 'owner' of
|
||||
// _paused. play() accesses _paused to help in the situation where
|
||||
// someone calls play on an inactive sound().
|
||||
// removing --> _paused=false;
|
||||
AIL_quick_halt(_audio);
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
halt() {
|
||||
#if 0
|
||||
if(_file_name.find(".mid")!=string::npos) {
|
||||
miles_audio_debug("halt() midi");
|
||||
int i=1;
|
||||
finished() {
|
||||
miles_audio_debug("finished()");
|
||||
_manager->stoping_sound(this);
|
||||
if (!_finished_event.empty()) {
|
||||
throw_event(_finished_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
miles_audio_debug("halt()");
|
||||
AIL_quick_halt(_audio);
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
|
|
@ -154,7 +222,7 @@ set_loop_count(unsigned long loop_count) {
|
|||
// need to stop and start the sound, feel free. Or, maybe I'll spend
|
||||
// time on it in the future. Please set the loop option before starting
|
||||
// the sound.
|
||||
halt();
|
||||
stop();
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
|
@ -234,43 +302,6 @@ get_volume() const {
|
|||
return _volume;
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
set_active(bool active) {
|
||||
miles_audio_debug("set_active(active="<<active<<")");
|
||||
if (_active!=active) {
|
||||
_active=active;
|
||||
if (_active) {
|
||||
// ...activate the sound.
|
||||
if (_paused
|
||||
&&
|
||||
_loop_count==0) {
|
||||
// ...this sound was looping when it was paused.
|
||||
_paused=false;
|
||||
play();
|
||||
}
|
||||
} else {
|
||||
// ...deactivate the sound.
|
||||
if (status()==PLAYING) {
|
||||
if (_loop_count==0) {
|
||||
// ...we're pausing a looping sound.
|
||||
_paused=true;
|
||||
}
|
||||
|
||||
// unlike the user fn stop(), halt() does NOT alter the 'paused' status
|
||||
// this is important, dont want to 'stop' infin looping sounds unless user
|
||||
// explicitly uses "stop()"
|
||||
halt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MilesAudioSound::
|
||||
get_active() const {
|
||||
miles_audio_debug("get_active() returning "<<_active);
|
||||
return _active;
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
set_balance(float balance_right) {
|
||||
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
|
||||
|
|
@ -327,6 +358,51 @@ length() const {
|
|||
return _length;
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
set_active(bool active) {
|
||||
miles_audio_debug("set_active(active="<<active<<")");
|
||||
if (_active!=active) {
|
||||
_active=active;
|
||||
if (_active) {
|
||||
// ...activate the sound.
|
||||
if (_paused
|
||||
&&
|
||||
_loop_count==0) {
|
||||
// ...this sound was looping when it was paused.
|
||||
_paused=false;
|
||||
play();
|
||||
}
|
||||
} else {
|
||||
// ...deactivate the sound.
|
||||
if (status()==PLAYING) {
|
||||
if (_loop_count==0) {
|
||||
// ...we're pausing a looping sound.
|
||||
_paused=true;
|
||||
}
|
||||
stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MilesAudioSound::
|
||||
get_active() const {
|
||||
miles_audio_debug("get_active() returning "<<_active);
|
||||
return _active;
|
||||
}
|
||||
|
||||
void MilesAudioSound::
|
||||
set_finished_event(const string& event) {
|
||||
miles_audio_debug("set_finished_event(event="<<event<<")");
|
||||
_finished_event = event;
|
||||
}
|
||||
|
||||
const string& MilesAudioSound::
|
||||
get_finished_event() const {
|
||||
miles_audio_debug("get_finished_event() returning "<<_finished_event);
|
||||
return _finished_event;
|
||||
}
|
||||
|
||||
const string& MilesAudioSound::
|
||||
get_name() const {
|
||||
//audio_debug("MilesAudioSound::get_name() returning "<<_file_name);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ public:
|
|||
// inits to manager's state.
|
||||
void set_active(bool active=true);
|
||||
bool get_active() const;
|
||||
|
||||
// This is the string that throw_event() will throw
|
||||
// when the sound finishes playing. It is not triggered
|
||||
// when the sound is stopped with stop().
|
||||
void set_finished_event(const string& event);
|
||||
const string& get_finished_event() const;
|
||||
|
||||
const string& get_name() const;
|
||||
|
||||
|
|
@ -91,11 +97,7 @@ public:
|
|||
|
||||
AudioSound::SoundStatus status() const;
|
||||
|
||||
protected:
|
||||
// halt is like stop(), except it should not be called by the user.
|
||||
// halt() does not change the "paused" status of a sound, it just stops
|
||||
// it from playing. This is useful when the sound needs to be deactivated
|
||||
void halt(void);
|
||||
void finished();
|
||||
|
||||
private:
|
||||
HAUDIO _audio;
|
||||
|
|
@ -104,14 +106,28 @@ private:
|
|||
float _balance; // -1..1
|
||||
mutable float _length; // in seconds.
|
||||
unsigned long _loop_count;
|
||||
|
||||
// This is the string that throw_event() will throw
|
||||
// when the sound finishes playing. It is not triggered
|
||||
// when the sound is stopped with stop().
|
||||
string _finished_event;
|
||||
|
||||
string _file_name;
|
||||
|
||||
// _active is for things like a 'turn off sound effects' in
|
||||
// a preferences pannel.
|
||||
// _active is not about whether a sound is currently playing.
|
||||
// Use status() for info on whether the sound is playing.
|
||||
bool _active;
|
||||
|
||||
// _paused is not like the Pause button on a cd/dvd player.
|
||||
// It is used as a flag to say that the sound was looping when
|
||||
// itwas set inactive.
|
||||
bool _paused;
|
||||
|
||||
MilesAudioSound(MilesAudioManager* manager,
|
||||
HAUDIO audio, string file_name, float length=0.0f);
|
||||
|
||||
|
||||
friend class MilesAudioManager;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <bamReader.h>
|
||||
#include <bamWriter.h>
|
||||
#include <compose_matrix.h>
|
||||
#include <datagram.h>
|
||||
#include <datagramIterator.h>
|
||||
#include <event.h>
|
||||
#include <fftCompressor.h>
|
||||
#include <indent.h>
|
||||
#include <throw_event.h>
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "compose_matrix.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "event.h"
|
||||
#include "fftCompressor.h"
|
||||
#include "indent.h"
|
||||
#include "throw_event.h"
|
||||
|
||||
#include "animBundle.h"
|
||||
#include "animBundleNode.h"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef THROW_EVENT_H
|
||||
#define THROW_EVENT_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "eventQueue.h"
|
||||
#include "pt_Event.h"
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
#include "lerp.h"
|
||||
|
||||
#include <clockObject.h>
|
||||
#include <throw_event.h>
|
||||
#include "clockObject.h"
|
||||
#include "throw_event.h"
|
||||
|
||||
TypeHandle Lerp::_type_handle;
|
||||
TypeHandle AutonomousLerp::_type_handle;
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ apply_linear_force(ColliderDef &def, const LVector3f &force) {
|
|||
LVector3f adjustment=force;
|
||||
physics_debug(" adjustment set "<<adjustment<<" len "<<adjustment.length());
|
||||
|
||||
NodePath np(def._node);
|
||||
CPT(TransformState) trans = np.get_net_transform();
|
||||
//NodePath np(def._node);
|
||||
//CPT(TransformState) trans = np.get_net_transform();
|
||||
//adjustment=adjustment*trans->get_mat();
|
||||
physics_debug(" adjustment trn "<<adjustment<<" len "<<adjustment.length());
|
||||
|
||||
|
|
@ -112,7 +112,10 @@ apply_linear_force(ColliderDef &def, const LVector3f &force) {
|
|||
physics_debug(" vel pre friction "<<vel<<" len "<<vel.length());
|
||||
float friction=frictionCoefficient*angle;
|
||||
physics_debug(" friction "<<friction);
|
||||
assert(friction>=0.0f && friction<=1.0f);
|
||||
if (friction<0.0f && friction>1.0f) {
|
||||
cerr<<"\n\nfriction error "<<friction<<endl;
|
||||
friction=1.0f;
|
||||
}
|
||||
#if 0
|
||||
float dt=ClockObject::get_global_clock()->get_dt();
|
||||
vel *= (1.0f-friction) * dt * dt;
|
||||
|
|
|
|||
Loading…
Reference in New Issue