00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023
00024 #ifndef ALPHA_LINUX_CXX
00025 #ifndef UNDER_CE
00026 # include <csignal>
00027 #endif
00028 # include <iostream>
00029 #endif
00030 #include <unistd.h>
00031
00032 #include "fnames.h"
00033 #include "exult.h"
00034 #include "game.h"
00035 #include "Audio.h"
00036
00037 #include "../files/U7file.h"
00038 #include "../files/utils.h"
00039 #include "Midi.h"
00040 #include "xmidi.h"
00041 #include "conv.h"
00042 #include "convmusic.h"
00043
00044 #include "../conf/Configuration.h"
00045 extern Configuration *config;
00046
00047 #ifndef UNDER_CE
00048 using std::cerr;
00049 using std::cout;
00050 using std::endl;
00051 using std::string;
00052 using std::strcpy;
00053 #endif
00054
00055 static Mix_Music *oggmusic;
00056
00057
00058 void MyMidiPlayer::start_track(int num,bool repeat,int bank)
00059 {
00060 if (!midi_device && !init_device())
00061 return;
00062
00063
00064 #ifdef DEBUG
00065 cout << "Audio subsystem request: Music track # " << num << endl;
00066 #endif
00067
00068 if (num == -1 || num == 255)
00069 {
00070 stop_music();
00071 return;
00072 }
00073
00074 current_track = num;
00075 repeating = repeat;
00076
00077 if (output_driver_type == MIDI_DRIVER_OGG)
00078 {
00079 char filename[255] ;
00080 string s;
00081
00082
00083 if(oggmusic)
00084 {
00085 Mix_FreeMusic(oggmusic);
00086 oggmusic = NULL;
00087 }
00088
00089 if(Game::get_game_type()==SERPENT_ISLE)
00090 {
00091 if(bank == 2 && num == 28)
00092 num = 70;
00093
00094 s = midi_bank[bank];
00095 to_uppercase(s);
00096 if((num == 30 || num == 32) && s.find("MAINSHP") != std::string::npos)
00097 {
00098
00099 if(num == 30)
00100 s = "endcr01.ogg";
00101 else
00102 s = "endcr02.ogg";
00103 }
00104 else
00105 {
00106 s = bgconvmusic[num];
00107 s = s + ".ogg";
00108 }
00109
00110 s = get_system_path("<MUSIC>/" + s);
00111 strcpy(filename, s.c_str());
00112 }
00113 else
00114 {
00115 char outputstr[255];
00116
00117 s = midi_bank[bank];
00118 to_uppercase(s);
00119 if((num == 4 || num == 5) && s.find("INTRORDM") != std::string::npos)
00120 {
00121
00122 if(num == 4)
00123 s = "endcr01.ogg";
00124 else
00125 s = "endcr02.ogg";
00126 }
00127 else
00128 s = "%02dbg.ogg";
00129
00130 s = get_system_path("<MUSIC>/" + s);
00131 strcpy(outputstr, s.c_str());
00132 sprintf(filename, outputstr, num);
00133 }
00134
00135 if(num == 99)
00136 {
00137 s = get_system_path("<MUSIC>/exult.ogg");
00138 strcpy(filename, s.c_str());
00139 }
00140
00141 if(repeat)
00142 repeat = 2;
00143
00144 oggmusic = Mix_LoadMUS(filename);
00145 if (!oggmusic) {
00146 cout << "Error playing " << filename << ": " << Mix_GetError()
00147 << std::endl;
00148 }
00149
00150 Mix_PlayMusic(oggmusic, repeat);
00151 Mix_VolumeMusic(MIX_MAX_VOLUME);
00152
00153 #ifdef DEBUG
00154 cout << "OGG audio: Music track " << filename << endl;
00155 #endif
00156
00157 return;
00158 }
00159
00160
00161
00162 if (bank == 0 && midi_device->is_fm_synth()) bank = 3;
00163
00164 else if (bank == 1 && midi_device->is_fm_synth()) bank = 4;
00165
00166 else if (bank == 2 && midi_device->is_fm_synth()) num--;
00167
00168 U7object track(midi_bank[bank].c_str(),num);
00169
00170 char *buffer;
00171 size_t size;
00172 DataSource *mid_data;
00173
00174 try
00175 {
00176 buffer = track.retrieve(size);
00177 }
00178 catch( const std::exception & )
00179 {
00180 return;
00181 }
00182
00183
00184 mid_data = new BufferDataSource(buffer, size);
00185
00186
00187 int conv = music_conversion;
00188
00189 if (midi_device->use_gs127())
00190
00191 conv = XMIDI_CONVERT_MT32_TO_GS127;
00192
00193
00194
00195 XMIDI midfile(mid_data, conv);
00196
00197 delete mid_data;
00198 delete [] buffer;
00199
00200
00201
00202 XMIDIEventList *eventlist = midfile.GetEventList(0);
00203 if (eventlist) midi_device->start_track(eventlist, repeat);
00204
00205 }
00206
00207 void MyMidiPlayer::start_track(const char *fname,int num,bool repeat)
00208 {
00209 if (!fname || (!midi_device && !init_device()))
00210 return;
00211
00212 current_track = -1;
00213 repeating = repeat;
00214
00215 #ifdef DEBUG
00216 cout << "Audio subsystem request: Music track # " << num << " in file "<< fname << endl;
00217 #endif
00218
00219
00220 if (num == -1 || num == 255)
00221 {
00222 midi_device->stop_track();
00223 return;
00224 }
00225
00226
00227 if (output_driver_type == MIDI_DRIVER_OGG)
00228 {
00229 char filename[255] ;
00230
00231
00232 if(oggmusic)
00233 {
00234 Mix_FreeMusic(oggmusic);
00235 oggmusic = NULL;
00236 }
00237
00238 string s = fname;
00239 to_uppercase(s);
00240
00241 if(s.find("ENDSCORE") != std::string::npos && Game::get_game_type()!=SERPENT_ISLE)
00242 {
00243 sprintf(filename, "end%02dbg.ogg", num);
00244 }
00245 else if(s.find("R_SINTRO") != std::string::npos && Game::get_game_type()==SERPENT_ISLE)
00246 strcpy(filename, "si01.ogg");
00247 else if(s.find("R_SEND") != std::string::npos && Game::get_game_type()==SERPENT_ISLE)
00248 strcpy(filename, "si13.ogg");
00249 else
00250 return;
00251
00252 string s2 = filename;
00253 s2 = get_system_path("<MUSIC>/" + s2);
00254 strcpy(filename, s2.c_str());
00255
00256 oggmusic = Mix_LoadMUS(filename);
00257 Mix_PlayMusic(oggmusic, repeat);
00258 Mix_VolumeMusic(MIX_MAX_VOLUME);
00259
00260 return;
00261 }
00262
00263
00264 FILE *mid_file;
00265 DataSource *mid_data;
00266
00267
00268
00269
00270 mid_file = U7open(fname, "rb");
00271 mid_data = new FileDataSource(mid_file);
00272
00273
00274 int conv = music_conversion;
00275
00276 if (midi_device->use_gs127())
00277
00278 conv = XMIDI_CONVERT_MT32_TO_GS127;
00279
00280
00281
00282 XMIDI midfile(mid_data, conv);
00283
00284 delete mid_data;
00285 fclose(mid_file);
00286
00287
00288 XMIDIEventList *eventlist = midfile.GetEventList(num);
00289 if (eventlist) midi_device->start_track(eventlist, repeat);
00290 }
00291
00292 void MyMidiPlayer::start_track(XMIDIEventList *midfile, bool repeat)
00293 {
00294
00295 #ifdef DEBUG
00296 cout << "Audio subsystem request: Custom Music track" << endl;
00297 #endif
00298 if (!midi_device && !init_device())
00299 return;
00300
00301
00302 midi_device->start_track(midfile, repeat);
00303 }
00304
00305 void MyMidiPlayer::start_music(int num,bool repeat,int bank)
00306 {
00307 if(!midi_device && !init_device())
00308 return;
00309 if(current_track==num&&midi_device->is_playing())
00310 return;
00311
00312 if(num == 0 && bank == 0 && Game::get_game_type() == BLACK_GATE)
00313 return;
00314
00315 start_track(num,repeat,bank);
00316 }
00317
00318 void MyMidiPlayer::start_music(const char *fname,int num,bool repeat)
00319 {
00320 if(!fname || (!midi_device && !init_device()))
00321 return;
00322 start_track(fname,num,repeat);
00323 }
00324
00325 void MyMidiPlayer::stop_music()
00326 {
00327 if(!midi_device && !init_device())
00328 return;
00329
00330 current_track = -1;
00331 repeating = false;
00332
00333 midi_device->stop_track();
00334 }
00335
00336 bool MyMidiPlayer::add_midi_bank(const char *bankname)
00337 {
00338 string bank(bankname);
00339 midi_bank.push_back(bank);
00340 return true;
00341 }
00342
00343
00344 #if HAVE_TIMIDITY_BIN
00345 #include "midi_drivers/Timidity_binary.h"
00346 #endif
00347 #if HAVE_LIBKMIDI
00348 #include "midi_drivers/KMIDI.h"
00349 #endif
00350 #if !defined(MACOS) && !defined(WIN32)
00351 #include "midi_drivers/forked_player.h"
00352 #endif
00353 #ifdef USE_FMOPL_MIDI
00354 #include "midi_drivers/fmopl_midi.h"
00355 #endif
00356 #ifdef WIN32
00357 #include "midi_drivers/win_midiout.h"
00358 #endif
00359 #ifdef BEOS
00360 #include "midi_drivers/be_midi.h"
00361 #endif
00362 #if defined(MACOS) || defined(MACOSX)
00363 #include "midi_drivers/mac_midi.h"
00364 #endif
00365 #if defined( __MORPHOS__ ) || defined( AMIGA )
00366 #include "midi_drivers/amiga_midi.h"
00367 #endif
00368
00369 #define TRY_MIDI_DRIVER(CLASS_NAME) do { \
00370 if(no_device) { \
00371 try { \
00372 midi_device=new CLASS_NAME(); \
00373 no_device=false; \
00374 cout << "Music player: " << midi_device->copyright() << endl; \
00375 } catch(...) { \
00376 no_device=true; \
00377 } \
00378 } \
00379 } while(0)
00380
00381 void MyMidiPlayer::set_music_conversion(int conv)
00382 {
00383 music_conversion = conv;
00384
00385 switch(music_conversion) {
00386 case XMIDI_CONVERT_MT32_TO_GS:
00387 config->set("config/audio/midi/convert","gs",true);
00388 break;
00389 case XMIDI_CONVERT_NOCONVERSION:
00390 config->set("config/audio/midi/convert","none",true);
00391 break;
00392 case XMIDI_CONVERT_MT32_TO_GS127:
00393 config->set("config/audio/midi/convert","gs127",true);
00394 break;
00395 default:
00396 config->set("config/audio/midi/convert","gm",true);
00397 break;
00398 }
00399 }
00400
00401 void MyMidiPlayer::set_effects_conversion(int conv)
00402 {
00403 effects_conversion = conv;
00404
00405 switch(effects_conversion) {
00406 case XMIDI_CONVERT_NOCONVERSION:
00407 config->set("config/audio/effects/convert","none",true);
00408 break;
00409 default:
00410 config->set("config/audio/effects/convert","gs",true);
00411 break;
00412 }
00413 }
00414
00415 void MyMidiPlayer::set_output_driver_type(int type)
00416 {
00417
00418 if (type != output_driver_type) {
00419 stop_music();
00420 delete midi_device;
00421 midi_device = 0;
00422 initialized = false;
00423 }
00424
00425 output_driver_type = type;
00426
00427 switch(output_driver_type) {
00428 case MIDI_DRIVER_OGG:
00429 config->set("config/audio/midi/driver","digital",true);
00430 break;
00431 #ifdef USE_FMOPL_MIDI
00432 case MIDI_DRIVER_FMSYNTH:
00433 config->set("config/audio/midi/driver","fmsynth",true);
00434 break;
00435 #endif
00436 #ifdef USE_MT32EMU_MIDI
00437 case MIDI_DRIVER_MT32EMU:
00438 config->set("config/audio/midi/driver","mt32emu",true);
00439 break;
00440 #endif
00441 default:
00442 config->set("config/audio/midi/driver","normal",true);
00443 break;
00444 };
00445 }
00446
00447
00448 bool MyMidiPlayer::init_device(void)
00449 {
00450
00451 if (initialized) return (midi_device != 0);
00452
00453 bool no_device=true;
00454
00455
00456 string s;
00457
00458 bool sfx = Audio::get_ptr()->are_effects_enabled();
00459
00460 if (!sfx) s = "no";
00461 else s = "yes";
00462
00463 config->set("config/audio/effects/enabled",s,true);
00464
00465 bool music = Audio::get_ptr()->is_music_enabled();
00466
00467 if (!music) s = "no";
00468 else s = "yes";
00469
00470
00471 config->set("config/audio/midi/enabled",s,true);
00472
00473
00474 std::string driver_default = "normal";
00475
00476
00477 config->value("config/audio/midi/convert",s,"gm");
00478
00479 if (s == "gs")
00480 music_conversion = XMIDI_CONVERT_MT32_TO_GS;
00481 else if (s == "none")
00482 music_conversion = XMIDI_CONVERT_NOCONVERSION;
00483 else if (s == "gs127")
00484 music_conversion = XMIDI_CONVERT_MT32_TO_GS127;
00485 else if (s == "gs127drum")
00486 {
00487 music_conversion = XMIDI_CONVERT_MT32_TO_GS;
00488 config->set("config/audio/midi/convert","gs",true);
00489 }
00490 else
00491 {
00492 music_conversion = XMIDI_CONVERT_MT32_TO_GM;
00493 config->set("config/audio/midi/convert","gm",true);
00494 driver_default = s;
00495 }
00496
00497
00498 config->value("config/audio/effects/convert",s,"gs");
00499
00500 if (s == "none")
00501 effects_conversion = XMIDI_CONVERT_NOCONVERSION;
00502 else if (s == "gs127")
00503 effects_conversion = XMIDI_CONVERT_NOCONVERSION;
00504 else
00505 {
00506 effects_conversion = XMIDI_CONVERT_GS127_TO_GS;
00507 config->set("config/audio/effects/convert","gs",true);
00508 }
00509
00510
00511 config->value("config/audio/midi/driver",s,driver_default.c_str());
00512
00513 if (s == "digital")
00514 {
00515 output_driver_type = MIDI_DRIVER_OGG;
00516 config->set("config/audio/effects/driver","digital",true);
00517 }
00518 #ifdef USE_FMOPL_MIDI
00519 else if (s == "fmsynth")
00520 {
00521 output_driver_type = MIDI_DRIVER_FMSYNTH;
00522 config->set("config/audio/effects/driver","fmsynth",true);
00523 }
00524 #endif
00525 #ifdef USE_MT32EMU_MIDI
00526 else if (s == "mt32emu")
00527 {
00528 output_driver_type = MIDI_DRIVER_MT32EMU;
00529 }
00530 #endif
00531 else
00532 {
00533 output_driver_type = MIDI_DRIVER_NORMAL;
00534 config->set("config/audio/effects/driver","normal",true);
00535 }
00536
00537
00538 if (!sfx && !music)
00539 {
00540 midi_device = 0;
00541 return false;
00542 }
00543
00544
00545
00546
00547
00548 if (output_driver_type == MIDI_DRIVER_OGG)
00549 TRY_MIDI_DRIVER(OGG_MIDI);
00550 #ifdef USE_FMOPL_MIDI
00551 else if (output_driver_type == MIDI_DRIVER_FMSYNTH)
00552 TRY_MIDI_DRIVER(FMOpl_Midi);
00553 #endif
00554
00555 #if defined(WIN32) && !defined(UNDER_CE)
00556 TRY_MIDI_DRIVER(Windows_MidiOut);
00557 #endif
00558 #ifdef BEOS
00559 TRY_MIDI_DRIVER(Be_midi);
00560 #endif
00561 #if defined(HAVE_TIMIDITY_BIN) && (defined(XWIN) || defined(WIN32))
00562 TRY_MIDI_DRIVER(Timidity_binary);
00563 #endif
00564 #if HAVE_LIBKMIDI
00565 TRY_MIDI_DRIVER(KMIDI);
00566 #endif
00567 #if (defined(XWIN) && !defined(OPENBSD) && !defined(__zaurus__))
00568 TRY_MIDI_DRIVER(forked_player);
00569 #endif
00570 #if defined(MACOS) || defined(MACOSX)
00571 TRY_MIDI_DRIVER(Mac_QT_midi);
00572 #endif
00573 #if defined(__MORPHOS__) || defined(AMIGA)
00574 TRY_MIDI_DRIVER(AmigaMIDI);
00575 #endif
00576 #ifdef USE_FMOPL_MIDI
00577 TRY_MIDI_DRIVER(FMOpl_Midi);
00578 #endif
00579
00580 initialized = true;
00581
00582 if(no_device)
00583 {
00584 midi_device=0;
00585 cerr << "Unable to create a MIDI device. No music will be played." << endl;
00586 return false;
00587 }
00588
00589 load_patches(false);
00590
00591 return true;
00592 }
00593
00594
00595 MyMidiPlayer::MyMidiPlayer() : current_track(-1),repeating(false),
00596 midi_device(0), initialized(false),
00597 music_conversion(XMIDI_CONVERT_MT32_TO_GM),
00598 effects_conversion(XMIDI_CONVERT_GS127_TO_GS),
00599 output_driver_type(MIDI_DRIVER_NORMAL)
00600 {
00601 add_midi_bank(MAINMUS);
00602 add_midi_bank(INTROMUS);
00603 add_midi_bank("<STATIC>/mainshp.flx");
00604 add_midi_bank(MAINMUS_AD);
00605 add_midi_bank(INTROMUS_AD);
00606
00607 init_device();
00608 }
00609
00610 MyMidiPlayer::~MyMidiPlayer()
00611 {
00612 if(midi_device)
00613
00614 delete midi_device;
00615 }
00616
00617
00618 void MyMidiPlayer::start_sound_effect(int num)
00619 {
00620 #ifdef DEBUG
00621 cout << "Audio subsystem request: sound effect # " << num << endl;
00622 #endif
00623
00624 int real_num = num;
00625
00626 if (Game::get_game_type() == BLACK_GATE) real_num = bgconv[num];
00627
00628 cout << "Real num " << real_num << endl;
00629
00630 U7object track("<DATA>/midisfx.flx",real_num);
00631
00632 if (!midi_device && !init_device())
00633 return;
00634
00635 char *buffer;
00636 size_t size;
00637 DataSource *mid_data;
00638
00639 try
00640 {
00641 buffer = track.retrieve(size);
00642 }
00643 catch( const std::exception & )
00644 {
00645 return;
00646 }
00647
00648
00649 mid_data = new BufferDataSource(buffer, size);
00650
00651
00652 XMIDI midfile(mid_data, effects_conversion);
00653
00654 delete mid_data;
00655 delete [] buffer;
00656
00657
00658 XMIDIEventList *eventlist = midfile.GetEventList(0);
00659 if (eventlist) midi_device->start_sfx(eventlist);
00660
00661 }
00662
00663 void MyMidiPlayer::stop_sound_effects()
00664 {
00665 if (midi_device)
00666 midi_device->stop_sfx();
00667 }
00668
00669 OGG_MIDI::OGG_MIDI()
00670 {
00671 oggmusic = NULL;
00672 Mix_HookMusicFinished(music_complete_callback);
00673 Mix_VolumeMusic(MIX_MAX_VOLUME);
00674 }
00675
00676 OGG_MIDI::~OGG_MIDI()
00677 {
00678 Mix_HaltMusic();
00679 if(oggmusic)
00680 {
00681 Mix_FreeMusic(oggmusic);
00682 oggmusic = NULL;
00683 }
00684 }
00685
00686
00687 void OGG_MIDI::music_complete_callback(void)
00688 {
00689 if(oggmusic)
00690 {
00691 Mix_FreeMusic(oggmusic);
00692 oggmusic = NULL;
00693 }
00694 }
00695
00696 void OGG_MIDI::start_track(XMIDIEventList *, bool repeat)
00697 {
00698 }
00699
00700 void OGG_MIDI::stop_track(void)
00701 {
00702 Mix_HaltMusic();
00703 if(oggmusic)
00704 {
00705 Mix_FreeMusic(oggmusic);
00706 oggmusic = NULL;
00707 }
00708 }
00709
00710 bool OGG_MIDI::is_playing(void)
00711 {
00712 return Mix_PlayingMusic()!=0;
00713 }
00714
00715 const char * OGG_MIDI::copyright(void)
00716 {
00717 return "Internal OGG digital music player";
00718 }
00719
00720