//
// C++-ified by Curtis Olson, started March 2001.
//
-// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
# error This library requires C++
#endif
-#include <simgear/compiler.h>
-
-#include STL_STRING
+#include <string>
+#include <vector>
#include <map>
-#include <AL/al.h>
+#if defined(__APPLE__)
+# define AL_ILLEGAL_ENUM AL_INVALID_ENUM
+# define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
+# include <OpenAL/al.h>
+# include <OpenAL/alc.h>
+# include <OpenAL/alut.h>
+#else
+# include <AL/al.h>
+# include <AL/alc.h>
+# include <AL/alut.h>
+#endif
-#include "sample_openal.hxx"
+#include <simgear/compiler.h>
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/math/SGMathFwd.hxx>
-SG_USING_STD(map);
-SG_USING_STD(string);
+#include "sample_group.hxx"
+#include "sample_openal.hxx"
+using std::map;
+using std::string;
-typedef map < string, SGSoundSample * > sample_map;
-typedef sample_map::iterator sample_map_iterator;
-typedef sample_map::const_iterator const_sample_map_iterator;
+typedef map < string, SGSharedPtr<SGSampleGroup> > sample_group_map;
+typedef sample_group_map::iterator sample_group_map_iterator;
+typedef sample_group_map::const_iterator const_sample_group_map_iterator;
/**
- * Manage a collection of SGSoundSample instances
+ * Manage a collection of SGSampleGroup instances
*/
-class SGSoundMgr
+class SGSoundMgr : public SGSubsystem
{
-
- // Position of the listener.
- ALfloat listener_pos[3];
-
- // Velocity of the listener.
- ALfloat listener_vel[3];
-
- // Orientation of the listener. (first 3 elements are "at", second
- // 3 are "up")
- ALfloat listener_ori[6];
-
- sample_map samples;
-
- bool working;
- double safety;
-
public:
SGSoundMgr();
~SGSoundMgr();
-
- /**
- * (re) initialize the sound manager.
- */
void init();
-
-
- /**
- * Bind properties for the sound manager.
- */
void bind();
-
-
- /**
- * Unbind properties for the sound manager.
- */
void unbind();
-
-
- /**
- * Run the audio scheduler.
- */
void update(double dt);
-
-
- /**
- * Pause all sounds.
- */
- void pause();
-
-
- /**
- * Resume all sounds.
- */
+ void update_late(double dt);
+
+ void suspend();
void resume();
+ void stop();
+ inline void reinit() { stop(); init(); }
/**
* is audio working?
*/
- inline bool is_working() const { return working; }
+ inline bool is_working() const { return _working; }
/**
- * reinitialize the sound manager
+ * add a sample group, return true if successful
*/
- inline void reinit() { init(); }
-
- /**
- * add a sound effect, return true if successful
- */
- bool add( SGSoundSample *sound, const string& refname);
+ bool add( SGSampleGroup *sgrp, const string& refname );
/**
- * remove a sound effect, return true if successful
+ * remove a sample group, return true if successful
*/
bool remove( const string& refname );
bool exists( const string& refname );
/**
- * return a pointer to the SGSoundSample if the specified sound
+ * return a pointer to the SGSampleGroup if the specified sound
* exists in the sound manager system, otherwise return NULL
*/
- SGSoundSample *find( const string& refname );
+ SGSampleGroup *find( const string& refname, bool create = false );
/**
- * tell the scheduler to play the indexed sample in a continuous
- * loop
+ * set the position of the listener (in opengl coordinates)
*/
- bool play_looped( const string& refname );
+ inline void set_position( SGVec3d pos ) {
+ _listener_pos = pos;
+ _changed = true;
+ }
+
+ inline double *get_position() {
+ return _listener_pos.data();
+ }
/**
- * tell the scheduler to play the indexed sample once
+ * set the velocity of the listener (in opengl coordinates)
*/
- bool play_once( const string& refname );
+ inline void set_velocity( SGVec3f vel ) {
+ _listener_vel = vel;
+ _changed = true;
+ }
+
+ /**
+ * set the orientation of the listener (in opengl coordinates)
+ */
+ void set_orientation( SGQuatd ori );
+
+ enum {
+ NO_SOURCE = (unsigned int)-1,
+ NO_BUFFER = (unsigned int)-1
+ };
+
+ void set_volume( float v );
+ inline float get_volume() { return _volume; }
/**
- * return true of the specified sound is currently being played
+ * get a new OpenAL source id
+ * returns NO_SOURCE is no source is available
*/
- bool is_playing( const string& refname );
+ unsigned int request_source();
/**
- * immediate stop playing the sound
+ * give back an OpenAL source id for further use.
*/
- bool stop( const string& refname );
+ void release_source( unsigned int source );
+
+ static bool load(string &samplepath, void **data, int *format,
+ unsigned int*size, int *freq );
+
+
+private:
+ static int _alut_init;
+
+ bool _working;
+ bool _changed;
+ float _volume;
+
+ ALCdevice *_device;
+ ALCcontext *_context;
+
+ // Position of the listener.
+ SGVec3d _listener_pos;
+
+ // Velocity of the listener.
+ SGVec3f _listener_vel;
+
+ // Orientation of the listener.
+ // first 3 elements are "at" vector, second 3 are "up" vector
+ ALfloat _listener_ori[6];
+
+ sample_group_map _sample_groups;
+
+ vector<ALuint> _free_sources;
+ vector<ALuint> _sources_in_use;
+
+ char *_devname;
+
+ bool testForALError(string s);
+ bool testForALCError(string s);
+ bool testForALUTError(string s);
+ bool testForError(void *p, string s);
+ void update_sample_config( SGSampleGroup *sound );
};