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  */
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 }
NullAudioManager
Definition: nullAudioManager.h:21
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AudioManager::set_speaker_configuration
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.
Definition: audioManager.cxx:333
pvector< FilterConfig >
Filename::from_os_specific
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
Filename::to_os_specific
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
Filename::make_true_case
bool make_true_case()
On a case-insensitive operating system (e.g.
Definition: filename.cxx:1053
unref_delete
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
Definition: referenceCount.I:329
AudioManager::get_dls_pathname
get_dls_pathname
Returns the full pathname to the DLS file, as specified by the Config.prc file, or the default for th...
Definition: audioManager.h:176
load_dso.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
AudioManager::shutdown
virtual void shutdown()
Call this at exit time to shut down the audio system.
Definition: audioManager.cxx:146
nullAudioManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
NullAudioSound
Definition: nullAudioSound.h:23
AudioManager::update
virtual void update()
Must be called every frame.
Definition: audioManager.cxx:210
windowsRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
atomicAdjust.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ReferenceCount::ref
void ref() const
Explicitly increments the reference count.
Definition: referenceCount.I:151
AtomicAdjustDummyImpl::compare_and_exchange_ptr
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.
Definition: atomicAdjustDummyImpl.I:109
config_audio.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:742
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AudioSound
Definition: audioSound.h:25
PT
PT(AudioSound) AudioManager
Returns a special NullAudioSound object that has all the interface of a normal sound object,...
Definition: audioManager.cxx:154
FilterProperties
Stores a configuration for a set of audio DSP filters.
Definition: filterProperties.h:24
audioManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AudioManager::configure_filters
virtual bool configure_filters(FilterProperties *config)
Configures the global DSP filter chain.
Definition: audioManager.cxx:196
AudioManager
Definition: audioManager.h:28
VirtualFileSystem::resolve_filename
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
Definition: virtualFileSystem.cxx:641
FilterProperties::get_config
const ConfigVector & get_config()
Intended for use by AudioManager and AudioSound implementations: allows access to the config vector.
Definition: filterProperties.I:119
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39