00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "globalMilesManager.h"
00016
00017 #ifdef HAVE_RAD_MSS //[
00018
00019 #include "lightMutexHolder.h"
00020 #include "milesAudioManager.h"
00021 #include "milesAudioSample.h"
00022 #include "milesAudioSequence.h"
00023
00024 #ifdef WIN32
00025
00026 #include <windows.h>
00027 #include <mmsystem.h>
00028 #endif
00029
00030 GlobalMilesManager *GlobalMilesManager::_global_ptr;
00031
00032
00033
00034
00035
00036
00037 GlobalMilesManager::
00038 GlobalMilesManager() :
00039 _managers_lock("GlobalMilesManager::_managers_lock"),
00040 _samples_lock("GlobalMilesManager::_samples_lock"),
00041 _sequences_lock("GlobalMilesManager::_sequences_lock")
00042 {
00043 _digital_driver = 0;
00044 _midi_driver = 0;
00045 _dls_device = 0;
00046 _dls_file = 0;
00047 _is_open = false;
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 void GlobalMilesManager::
00058 add_manager(MilesAudioManager *manager) {
00059 LightMutexHolder holder(_managers_lock);
00060 _managers.insert(manager);
00061 if (!_is_open) {
00062 open_api();
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073 void GlobalMilesManager::
00074 remove_manager(MilesAudioManager *manager) {
00075 LightMutexHolder holder(_managers_lock);
00076 _managers.erase(manager);
00077 if (_managers.empty() && _is_open) {
00078 close_api();
00079 }
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 void GlobalMilesManager::
00089 cleanup() {
00090 LightMutexHolder holder(_managers_lock);
00091 Managers::iterator mi;
00092 for (mi = _managers.begin(); mi != _managers.end(); ++mi) {
00093 (*mi)->cleanup();
00094 }
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool GlobalMilesManager::
00113 get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound) {
00114 LightMutexHolder holder(_samples_lock);
00115
00116 for (size_t i = 0; i < _samples.size(); ++i) {
00117 SampleData &smp = _samples[i];
00118 if (AIL_sample_status(smp._sample) == SMP_DONE) {
00119 if (smp._sound != NULL) {
00120
00121
00122 smp._sound->internal_stop();
00123 }
00124 smp._sound = sound;
00125 sample = smp._sample;
00126 index = i;
00127 return true;
00128 }
00129 }
00130
00131
00132 sample = AIL_allocate_sample_handle(_digital_driver);
00133 if (sample == 0) {
00134 return false;
00135 }
00136
00137 AIL_init_sample(sample, DIG_F_STEREO_16, 0);
00138 index = _samples.size();
00139
00140 SampleData smp;
00141 smp._sound = sound;
00142 smp._sample = sample;
00143 _samples.push_back(smp);
00144 return true;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void GlobalMilesManager::
00154 release_sample(size_t index, MilesAudioSample *sound) {
00155 LightMutexHolder holder(_samples_lock);
00156 nassertv(index < _samples.size());
00157
00158 SampleData &smp = _samples[index];
00159 if (smp._sound == sound) {
00160 smp._sound = NULL;
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 bool GlobalMilesManager::
00180 get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound) {
00181 LightMutexHolder holder(_sequences_lock);
00182
00183 for (size_t i = 0; i < _sequences.size(); ++i) {
00184 SequenceData &seq = _sequences[i];
00185 if (AIL_sequence_status(seq._sequence) == SEQ_DONE) {
00186 if (seq._sound != NULL) {
00187
00188
00189 seq._sound->internal_stop();
00190 }
00191 seq._sound = sound;
00192 sequence = seq._sequence;
00193 index = i;
00194 return true;
00195 }
00196 }
00197
00198
00199 sequence = AIL_allocate_sequence_handle(_midi_driver);
00200 if (sequence == 0) {
00201 return false;
00202 }
00203
00204 index = _sequences.size();
00205
00206 SequenceData seq;
00207 seq._sound = sound;
00208 seq._sequence = sequence;
00209 _sequences.push_back(seq);
00210 return true;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 void GlobalMilesManager::
00220 release_sequence(size_t index, MilesAudioSequence *sound) {
00221 LightMutexHolder holder(_sequences_lock);
00222 nassertv(index < _sequences.size());
00223
00224 SequenceData &seq = _sequences[index];
00225 if (seq._sound == sound) {
00226 seq._sound = NULL;
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 void GlobalMilesManager::
00239 force_midi_reset() {
00240 if (!miles_audio_force_midi_reset) {
00241 audio_debug("MilesAudioManager::skipping force_midi_reset");
00242 return;
00243 }
00244 audio_debug("MilesAudioManager::force_midi_reset");
00245
00246 #ifdef WIN32
00247 if ((_midi_driver!=NULL) && (_midi_driver->deviceid != MIDI_NULL_DRIVER) && (_midi_driver->hMidiOut != NULL)) {
00248 audio_debug("MilesAudioManager::calling midiOutReset");
00249 midiOutReset(_midi_driver->hMidiOut);
00250 }
00251 #endif
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 GlobalMilesManager *GlobalMilesManager::
00261 get_global_ptr() {
00262 if (_global_ptr == NULL) {
00263 _global_ptr = new GlobalMilesManager;
00264 }
00265 return _global_ptr;
00266 }
00267
00268
00269
00270
00271
00272
00273 void GlobalMilesManager::
00274 open_api() {
00275 audio_debug("GlobalMilesManager::open_api()")
00276 nassertv(!_is_open);
00277
00278 bool use_digital = (audio_play_wave || audio_play_mp3);
00279 if (audio_play_midi && audio_software_midi) {
00280 use_digital = true;
00281 }
00282
00283 #ifdef IS_OSX
00284 audio_software_midi = true;
00285 #endif
00286
00287 audio_debug(" use_digital="<<use_digital);
00288 audio_debug(" audio_play_midi="<<audio_play_midi);
00289 audio_debug(" audio_software_midi="<<audio_software_midi);
00290 audio_debug(" audio_output_rate="<<audio_output_rate);
00291 audio_debug(" audio_output_bits="<<audio_output_bits);
00292 audio_debug(" audio_output_channels="<<audio_output_channels);
00293 audio_debug(" audio_software_midi="<<audio_software_midi);
00294
00295 #if !defined(NDEBUG) && defined(AIL_MSS_version) //[
00296 char version[8];
00297 AIL_MSS_version(version, 8);
00298 audio_debug(" Mss32.dll Version: "<<version);
00299 #endif //]
00300
00301 if (!AIL_startup()) {
00302 milesAudio_cat.warning()
00303 << "Miles Sound System already initialized!\n";
00304 }
00305
00306 AIL_set_file_callbacks(open_callback, close_callback,
00307 seek_callback, read_callback);
00308
00309 if (use_digital) {
00310 _digital_driver =
00311 AIL_open_digital_driver(audio_output_rate, audio_output_bits,
00312 audio_output_channels, 0);
00313 }
00314
00315 if (audio_play_midi) {
00316 if (audio_software_midi) {
00317 _midi_driver = AIL_open_XMIDI_driver(AIL_OPEN_XMIDI_NULL_DRIVER);
00318
00319
00320 _dls_device = AIL_DLS_open(_midi_driver, _digital_driver, NULL, 0,
00321 audio_output_rate, audio_output_bits,
00322 audio_output_channels);
00323
00324 Filename dls_pathname = AudioManager::get_dls_pathname();
00325
00326 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00327 vfs->resolve_filename(dls_pathname, get_model_path());
00328
00329 _dls_data.clear();
00330 PT(VirtualFile) file = vfs->get_file(dls_pathname);
00331 if (file == (VirtualFile *)NULL) {
00332 milesAudio_cat.warning()
00333 << "DLS file does not exist: " << dls_pathname << "\n";
00334
00335 } else if (!file->read_file(_dls_data, true)) {
00336 milesAudio_cat.warning()
00337 << "Could not read DLS file: " << dls_pathname << "\n";
00338
00339 } else if (_dls_data.empty()) {
00340 milesAudio_cat.warning()
00341 << "DLS file is empty: " << dls_pathname << "\n";
00342
00343 } else {
00344 _dls_file = AIL_DLS_load_memory(_dls_device, &_dls_data[0], 0);
00345 }
00346
00347 if (_dls_file == 0) {
00348 audio_error(" Could not get DLS file, switching to hardware MIDI.");
00349 AIL_DLS_close(_dls_device, 0);
00350 _dls_device = 0;
00351 AIL_close_XMIDI_driver(_midi_driver);
00352 _midi_driver = AIL_open_XMIDI_driver(0);
00353
00354 } else {
00355 audio_info(" using Miles software midi");
00356 }
00357 } else {
00358 _midi_driver = AIL_open_XMIDI_driver(0);
00359 audio_info(" using Miles hardware midi");
00360 }
00361 }
00362
00363 _is_open = true;
00364 }
00365
00366
00367
00368
00369
00370
00371 void GlobalMilesManager::
00372 close_api() {
00373 audio_debug("GlobalMilesManager::close_api()")
00374 nassertv(_is_open);
00375
00376 Samples::iterator si;
00377 for (si = _samples.begin(); si != _samples.end(); ++si) {
00378 SampleData &smp = (*si);
00379 AIL_release_sample_handle(smp._sample);
00380 }
00381 _samples.clear();
00382
00383 Sequences::iterator qi;
00384 for (qi = _sequences.begin(); qi != _sequences.end(); ++qi) {
00385 SequenceData &smp = (*qi);
00386 AIL_release_sequence_handle(smp._sequence);
00387 }
00388 _sequences.clear();
00389
00390 if (_dls_file != 0) {
00391 AIL_DLS_unload(_dls_device, _dls_file);
00392 _dls_file = 0;
00393 }
00394
00395 if (_dls_device != 0) {
00396 AIL_DLS_close(_dls_device, 0);
00397 _dls_device = 0;
00398 }
00399
00400 if (_midi_driver != 0) {
00401 AIL_close_XMIDI_driver(_midi_driver);
00402 _midi_driver = 0;
00403 }
00404
00405 if (_digital_driver != 0) {
00406 AIL_close_digital_driver(_digital_driver);
00407 _digital_driver = 0;
00408 }
00409
00410 AIL_shutdown();
00411
00412 _is_open = false;
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 U32 AILCALLBACK GlobalMilesManager::
00424 open_callback(char const *filename, UINTa *file_handle) {
00425 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00426 istream *strm = vfs->open_read_file(Filename::binary_filename(string(filename)), true);
00427 if (strm == NULL) {
00428
00429 return 0;
00430 }
00431
00432 (*file_handle) = (UINTa)strm;
00433 return 1;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 void AILCALLBACK GlobalMilesManager::
00443 close_callback(UINTa file_handle) {
00444 istream *strm = (istream *)file_handle;
00445 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00446 vfs->close_read_file(strm);
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 S32 AILCALLBACK GlobalMilesManager::
00456 seek_callback(UINTa file_handle, S32 offset, U32 type) {
00457 istream *strm = (istream *)file_handle;
00458 strm->clear();
00459 switch (type) {
00460 case AIL_FILE_SEEK_BEGIN:
00461 strm->seekg(offset, ios::beg);
00462 break;
00463
00464 case AIL_FILE_SEEK_CURRENT:
00465 strm->seekg(offset, ios::cur);
00466 break;
00467
00468 case AIL_FILE_SEEK_END:
00469 strm->seekg(offset, ios::end);
00470 break;
00471 }
00472
00473 return strm->tellg();
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 U32 AILCALLBACK GlobalMilesManager::
00483 read_callback(UINTa file_handle, void *buffer, U32 bytes) {
00484 istream *strm = (istream *)file_handle;
00485 strm->read((char *)buffer, bytes);
00486 return strm->gcount();
00487 }
00488
00489 #endif //]
00490