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::
146 shutdown() {
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::
196 configure_filters(FilterProperties *config) {
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::
210 update() {
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()) {
282 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
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 }
atomicAdjust.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT
PT(AudioSound) AudioManager
Returns a special NullAudioSound object that has all the interface of a normal sound object,...
Definition: audioManager.cxx:154
audioManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
AudioManager
Definition: audioManager.h:28
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
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:174
AudioManager::shutdown
virtual void shutdown()
Call this at exit time to shut down the audio system.
Definition: audioManager.cxx:146
AudioManager::configure_filters
virtual bool configure_filters(FilterProperties *config)
Configures the global DSP filter chain.
Definition: audioManager.cxx:196
AudioManager::update
virtual void update()
Must be called every frame.
Definition: audioManager.cxx:210
AudioSound
Definition: audioSound.h:25
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
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
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
FilterProperties
Stores a configuration for a set of audio DSP filters.
Definition: filterProperties.h:24
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
NullAudioManager
Definition: nullAudioManager.h:21
NullAudioSound
Definition: nullAudioSound.h:23
ReferenceCount::ref
void ref() const
Explicitly increments the reference count.
Definition: referenceCount.I:151
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
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:640
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:741
pvector< FilterConfig >
config_audio.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
load_dso.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
nullAudioManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:344
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
windowsRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.