Panda3D
audioManager.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file audioManager.cxx
10  * @author skyler
11  * @date 2001-06-06
12  * Prior system by: cary
13  */
14 
15 #include "config_audio.h"
16 #include "audioManager.h"
17 #include "atomicAdjust.h"
18 #include "nullAudioManager.h"
19 #include "windowsRegistry.h"
20 #include "virtualFileSystem.h"
21 #include "config_putil.h"
22 #include "load_dso.h"
23 
24 #ifdef WIN32
25 #include <windows.h> // For GetSystemDirectory()
26 #endif
27 
28 using std::string;
29 
30 
31 TypeHandle AudioManager::_type_handle;
32 
33 
34 namespace {
35  AudioManager *create_NullAudioManager() {
36  audio_debug("create_NullAudioManager()");
37  return new NullAudioManager();
38  }
39 }
40 
41 Create_AudioManager_proc *AudioManager::_create_AudioManager = nullptr;
42 
43 void AudioManager::
44 register_AudioManager_creator(Create_AudioManager_proc* proc) {
45  nassertv(_create_AudioManager == nullptr || _create_AudioManager == proc);
46  _create_AudioManager = proc;
47 }
48 
49 // Factory method for getting a platform specific AudioManager:
50 PT(AudioManager) AudioManager::create_AudioManager() {
51  audio_debug("create_AudioManager()\n audio_library_name=\""<<audio_library_name<<"\"");
52 
53  if (_create_AudioManager != nullptr) {
54  // Someone was already so good as to register an audio manager creation function,
55  // perhaps by statically linking the requested library. Let's use that, then.
56  PT(AudioManager) am = (*_create_AudioManager)();
57  if (!am->is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) {
58  audio_error(" " << am->get_type() << " is not valid, will use NullAudioManager");
59  am = create_NullAudioManager();
60  }
61  return am;
62  }
63 
64  static bool lib_load = false;
65  if (!lib_load) {
66  lib_load = true;
67  if (!audio_library_name.empty() && audio_library_name != "null") {
68  Filename dl_name = Filename::dso_filename(
69  "lib" + string(audio_library_name) + ".so");
70  dl_name.to_os_specific();
71  audio_debug(" dl_name=\""<<dl_name<<"\"");
72  void *handle = load_dso(get_plugin_path().get_value(), dl_name);
73  if (handle == nullptr) {
74  audio_error(" load_dso(" << dl_name << ") failed, will use NullAudioManager");
75  audio_error(" "<<load_dso_error());
76  nassertr(_create_AudioManager == nullptr, nullptr);
77  } else {
78  // Get the special function from the dso, which should return the
79  // AudioManager factory function.
80  string lib_name = audio_library_name;
81  if (lib_name.substr(0, 2) == "p3") {
82  lib_name = lib_name.substr(2);
83  }
84  string symbol_name = "get_audio_manager_func_" + lib_name;
85  void *dso_symbol = get_dso_symbol(handle, symbol_name);
86  if (audio_cat.is_debug()) {
87  audio_cat.debug()
88  << "symbol of " << symbol_name << " = " << dso_symbol << "\n";
89  }
90 
91  if (dso_symbol == nullptr) {
92  // Couldn't find the module function.
93  unload_dso(handle);
94  handle = nullptr;
95  audio_error(" Audio library did not provide get_audio_manager_func, will use NullAudioManager");
96  } else {
97  typedef Create_AudioManager_proc *FuncType();
98  Create_AudioManager_proc *factory_func = (*(FuncType *)dso_symbol)();
99 
100  // Note that the audio manager module may register itself upon load.
101  if (_create_AudioManager == nullptr) {
102  AudioManager::register_AudioManager_creator(factory_func);
103  }
104  }
105  }
106  }
107  }
108 
109  if (_create_AudioManager == nullptr) {
110  _create_AudioManager = create_NullAudioManager;
111  }
112 
113  PT(AudioManager) am = (*_create_AudioManager)();
114  if (!am->is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) {
115  audio_error(" " << am->get_type() << " is not valid, will use NullAudioManager");
116  am = create_NullAudioManager();
117  }
118  return am;
119 }
120 
121 /**
122  *
123  */
124 AudioManager::
125 ~AudioManager() {
126  if (_null_sound != nullptr) {
127  unref_delete((AudioSound *)_null_sound);
128  }
129 }
130 
131 /**
132  *
133  */
134 AudioManager::
135 AudioManager() {
136  _null_sound = nullptr;
137 }
138 
139 /**
140  * Call this at exit time to shut down the audio system. This will invalidate
141  * all currently-active AudioManagers and AudioSounds in the system. If you
142  * change your mind and want to play sounds again, you will have to recreate
143  * all of these objects.
144  */
145 void AudioManager::
147 }
148 
149 /**
150  * Returns a special NullAudioSound object that has all the interface of a
151  * normal sound object, but plays no sound. This same object may also be
152  * returned by get_sound() if it fails.
153  */
154 PT(AudioSound) AudioManager::
155 get_null_sound() {
156  if (_null_sound == nullptr) {
157  AudioSound *new_sound = new NullAudioSound;
158  new_sound->ref();
159  void *result = AtomicAdjust::compare_and_exchange_ptr(_null_sound, nullptr, (void *)new_sound);
160  if (result != nullptr) {
161  // Someone else must have assigned the AudioSound first. OK.
162  nassertr(_null_sound != new_sound, nullptr);
163  unref_delete(new_sound);
164  }
165  nassertr(_null_sound != nullptr, nullptr);
166  }
167 
168  return (AudioSound *)_null_sound;
169 }
170 
171 /**
172  *
173  */
174 int AudioManager::
175 get_speaker_setup() {
176  // intentionally blank
177  return 0;
178 }
179 
180 /**
181  *
182  */
183 void AudioManager::
184 set_speaker_setup(SpeakerModeCategory cat) {
185  // intentionally blank
186 }
187 
188 /**
189  * Configures the global DSP filter chain.
190  *
191  * There is no guarantee that any given configuration will be supported by the
192  * implementation. The only way to find out what's supported is to call
193  * configure_filters. If it returns true, the configuration is supported.
194  */
195 bool AudioManager::
197  const FilterProperties::ConfigVector &conf = config->get_config();
198  if (conf.empty()) {
199  return true;
200  } else {
201  return false;
202  }
203 }
204 
205 /**
206  * Must be called every frame. Failure to call this every frame could cause
207  * problems for some audio managers.
208  */
209 void AudioManager::
211  // Intentionally blank.
212 }
213 
214 /**
215  *
216  */
217 void AudioManager::audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz) {
218  // intentionally blank.
219 }
220 
221 /**
222  *
223  */
224 void AudioManager::audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz) {
225  // intentionally blank.
226 }
227 
228 /**
229  *
230  */
231 void AudioManager::audio_3d_set_distance_factor(PN_stdfloat factor) {
232  // intentionally blank.
233 }
234 
235 /**
236  *
237  */
238 PN_stdfloat AudioManager::audio_3d_get_distance_factor() const {
239  // intentionally blank.
240  return 0.0f;
241 }
242 
243 /**
244  *
245  */
246 void AudioManager::audio_3d_set_doppler_factor(PN_stdfloat factor) {
247  // intentionally blank.
248 }
249 
250 /**
251  *
252  */
253 PN_stdfloat AudioManager::audio_3d_get_doppler_factor() const {
254  // intentionally blank.
255  return 0.0f;
256 }
257 
258 /**
259  *
260  */
261 void AudioManager::audio_3d_set_drop_off_factor(PN_stdfloat factor) {
262  // intentionally blank.
263 }
264 
265 /**
266  *
267  */
268 PN_stdfloat AudioManager::audio_3d_get_drop_off_factor() const {
269  // intentionally blank.
270  return 0.0f;
271 }
272 
273 /**
274  * Returns the full pathname to the DLS file, as specified by the Config.prc
275  * file, or the default for the current OS if appropriate. Returns empty
276  * string if the DLS file is unavailable.
277  */
278 Filename AudioManager::
279 get_dls_pathname() {
280  Filename dls_filename = audio_dls_file;
281  if (!dls_filename.empty()) {
283  vfs->resolve_filename(dls_filename, get_model_path());
284 
285  return dls_filename;
286  }
287 
288 #ifdef WIN32
289  Filename pathname;
290 
291  // Get the registry key from DirectMusic
292  string os_filename = WindowsRegistry::get_string_value("SOFTWARE\\Microsoft\\DirectMusic", "GMFilePath", "");
293 
294  if (!os_filename.empty()) {
295  pathname = Filename::from_os_specific(os_filename);
296  } else {
297  char sysdir[MAX_PATH+1];
298  GetSystemDirectory(sysdir,MAX_PATH+1);
299  pathname = Filename(Filename::from_os_specific(sysdir), Filename("drivers/gm.dls"));
300  }
301  pathname.make_true_case();
302  return pathname;
303 
304 #elif defined(IS_OSX)
305  // This appears to be the standard place for this file on OSX 10.4.
306  return Filename("/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls");
307 
308 #else
309  return Filename();
310 #endif
311 }
312 
313 /**
314  *
315  */
316 void AudioManager::
317 output(std::ostream &out) const {
318  out << get_type();
319 }
320 
321 /**
322  *
323  */
324 void AudioManager::
325 write(std::ostream &out) const {
326  out << (*this) << "\n";
327 }
328 
329 /**
330  * For use only with Miles.
331  */
332 void AudioManager::
333 set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2, LVecBase3 *speaker3, LVecBase3 *speaker4, LVecBase3 *speaker5, LVecBase3 *speaker6, LVecBase3 *speaker7, LVecBase3 *speaker8, LVecBase3 *speaker9) {
334  // intentionally blank
335 }
virtual bool configure_filters(FilterProperties *config)
Configures the global DSP filter chain.
A hierarchy of directories and files that appears to be one continuous file system,...
PT(AudioSound) AudioManager
Returns a special NullAudioSound object that has all the interface of a normal sound object,...
Stores a configuration for a set of audio DSP filters.
bool make_true_case()
On a case-insensitive operating system (e.g.
Definition: filename.cxx:1053
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
const ConfigVector & get_config()
Intended for use by AudioManager and AudioSound implementations: allows access to the config vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void update()
Must be called every frame.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void ref() const
Explicitly increments the reference count.
virtual void shutdown()
Call this at exit time to shut down the audio system.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Definition: filename.cxx:1123
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
virtual void set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2=nullptr, LVecBase3 *speaker3=nullptr, LVecBase3 *speaker4=nullptr, LVecBase3 *speaker5=nullptr, LVecBase3 *speaker6=nullptr, LVecBase3 *speaker7=nullptr, LVecBase3 *speaker8=nullptr, LVecBase3 *speaker9=nullptr)
For use only with Miles.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.