Panda3D
Loading...
Searching...
No Matches
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
28using std::string;
29
30
31TypeHandle AudioManager::_type_handle;
32
33
34namespace {
35 AudioManager *create_NullAudioManager() {
36 audio_debug("create_NullAudioManager()");
37 return new NullAudioManager();
38 }
39}
40
41Create_AudioManager_proc *AudioManager::_create_AudioManager = nullptr;
42
43void AudioManager::
44register_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:
50PT(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 */
124AudioManager::
125~AudioManager() {
126 if (_null_sound != nullptr) {
127 unref_delete((AudioSound *)_null_sound);
128 }
129}
130
131/**
132 *
133 */
134AudioManager::
135AudioManager() {
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 */
146shutdown() {
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 */
154PT(AudioSound) AudioManager::
155get_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 */
174int AudioManager::
175get_speaker_setup() {
176 // intentionally blank
177 return 0;
178}
179
180/**
181 *
182 */
183void AudioManager::
184set_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 */
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 */
210update() {
211 // Intentionally blank.
212}
213
214/**
215 *
216 */
217void 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 */
224void 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 */
231void AudioManager::audio_3d_set_distance_factor(PN_stdfloat factor) {
232 // intentionally blank.
233}
234
235/**
236 *
237 */
238PN_stdfloat AudioManager::audio_3d_get_distance_factor() const {
239 // intentionally blank.
240 return 0.0f;
241}
242
243/**
244 *
245 */
246void AudioManager::audio_3d_set_doppler_factor(PN_stdfloat factor) {
247 // intentionally blank.
248}
249
250/**
251 *
252 */
253PN_stdfloat AudioManager::audio_3d_get_doppler_factor() const {
254 // intentionally blank.
255 return 0.0f;
256}
257
258/**
259 *
260 */
261void AudioManager::audio_3d_set_drop_off_factor(PN_stdfloat factor) {
262 // intentionally blank.
263}
264
265/**
266 *
267 */
268PN_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 */
316void AudioManager::
317output(std::ostream &out) const {
318 out << get_type();
319}
320
321/**
322 *
323 */
324void AudioManager::
325write(std::ostream &out) const {
326 out << (*this) << "\n";
327}
328
329/**
330 * For use only with Miles.
331 */
333set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2, LVecBase3 *speaker3, LVecBase3 *speaker4, LVecBase3 *speaker5, LVecBase3 *speaker6, LVecBase3 *speaker7, LVecBase3 *speaker8, LVecBase3 *speaker9) {
334 // intentionally blank
335}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
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.
get_dls_pathname
Returns the full pathname to the DLS file, as specified by the Config.prc file, or the default for th...
virtual void shutdown()
Call this at exit time to shut down the audio system.
virtual bool configure_filters(FilterProperties *config)
Configures the global DSP filter chain.
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:44
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
bool make_true_case()
On a case-insensitive operating system (e.g.
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
Stores a configuration for a set of audio DSP filters.
const ConfigVector & get_config()
Intended for use by AudioManager and AudioSound implementations: allows access to the config vector.
void ref() const
Explicitly increments the reference count.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A hierarchy of directories and files that appears to be one continuous file system,...
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.