00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include <cstring>
00021
00022 #ifndef PENTAGRAM_IN_EXULT
00023 #include "IDataSource.h"
00024 #endif
00025
00026 #include "LowLevelMidiDriver.h"
00027 #include "XMidiSequence.h"
00028 #include "XMidiFile.h"
00029 #include "XMidiEvent.h"
00030 #include "XMidiEventList.h"
00031
00032 #define LLMD_MSG_PLAY 1
00033 #define LLMD_MSG_FINISH 2
00034 #define LLMD_MSG_PAUSE 3
00035 #define LLMD_MSG_SET_VOLUME 4
00036 #define LLMD_MSG_SET_SPEED 5
00037 #define LLMD_MSG_PRECACHE_TIMBRES 6
00038
00039
00040 #define LLMD_MSG_THREAD_INIT -1
00041 #define LLMD_MSG_THREAD_INIT_FAILED -2
00042 #define LLMD_MSG_THREAD_EXIT -3
00043
00044
00045
00046 #define LLMD_MINIMUM_YIELD_THRESHOLD 6
00047
00048
00049
00050 #ifdef DO_SMP_TEST
00051 #define giveinfo() perr << __FILE__ << ":" << __LINE__ << std::endl; perr.flush();
00052 #else
00053 #define giveinfo()
00054 #endif
00055
00056
00057
00058
00059 static const uint32 sysex_data_start = 7;
00060 static const uint32 sysex_max_data_size = 256;
00061
00062
00063
00064
00065
00066
00067 static const uint32 rhythm_base = 0x030110;
00068 static const uint32 rhythm_mem_size = 4;
00069
00070 static const uint32 rhythm_first_note = 24;
00071 static const uint32 rhythm_num_notes = 64;
00072
00073
00074 static inline uint32 rhythm_mem_offset(uint32 index_num) {
00075 return index_num * 4;
00076 }
00077
00078
00079 static inline uint32 rhythm_mem_offset_note(uint32 rhythm_note_num) {
00080 return (rhythm_note_num-rhythm_first_note) * 4;
00081 }
00082
00083
00084
00085
00086
00087
00088 static const uint32 timbre_temp_base = 0x040000;
00089 static const uint32 timbre_unk_base = 0x060000;
00090 static const uint32 timbre_base = 0x080000;
00091 static const uint32 timbre_mem_size = 246;
00092 static inline uint32 timbre_mem_offset(uint32 timbre_num) { return timbre_num * 256; }
00093
00094
00095
00096
00097 static const uint32 patch_temp_base = 0x030000;
00098 static const uint32 patch_temp_size = 16;
00099 static inline uint32 patch_temp_offset(uint32 patch_num) { return patch_num * 16; }
00100
00101
00102
00103
00104
00105 static const uint32 patch_base = 0x050000;
00106 static const uint32 patch_mem_size = 8;
00107 static inline uint32 patch_mem_offset(uint32 patch_num) { return patch_num * 8; }
00108
00109 const LowLevelMidiDriver::MT32Patch LowLevelMidiDriver::mt32_patch_template = {
00110 0,
00111 0,
00112 24,
00113 50,
00114 24,
00115 0,
00116 1,
00117 0
00118 };
00119
00120
00121
00122
00123 static const uint32 all_dev_reset_base = 0x7f0000;
00124
00125
00126
00127 static const uint32 display_base = 0x200000;
00128 static const uint32 display_mem_size = 0x14;
00129
00130
00131 static inline int ConvBaseToActual(uint32 address_base)
00132 {
00133 return ((address_base>>2) & (0x7f<<14)) |
00134 ((address_base>>1) & (0x7f<<7)) |
00135 ((address_base>>0) & (0x7f<<0));
00136 }
00137
00138 using std::string;
00139 using std::endl;
00140
00141 LowLevelMidiDriver::LowLevelMidiDriver() :
00142 MidiDriver(), mutex(0), cbmutex(0),cond(0),
00143 global_volume(255), thread(0)
00144 {
00145 }
00146
00147 LowLevelMidiDriver::~LowLevelMidiDriver()
00148 {
00149
00150 if (initialized)
00151 {
00152 perr << "Warning: Destructing LowLevelMidiDriver and destroyMidiDriver() wasn't called!" << std::endl;
00153
00154 if (thread) SDL_KillThread(thread);
00155 }
00156 thread = 0;
00157 }
00158
00159
00160
00161
00162
00163 int LowLevelMidiDriver::initMidiDriver(uint32 samp_rate, bool is_stereo)
00164 {
00165
00166 if (initialized) destroyMidiDriver();
00167
00168 string s;
00169
00170
00171 std::memset(sequences, 0, sizeof (XMidiSequence*) * LLMD_NUM_SEQ);
00172 std::memset(chan_locks, -1, sizeof (sint32) * 16);
00173 std::memset(chan_map, -1, sizeof (sint32) * LLMD_NUM_SEQ * 16);
00174 for (int i = 0; i < LLMD_NUM_SEQ; i++) {
00175 playing[i] = false;
00176 callback_data[i] = -1;
00177 }
00178
00179 mutex = SDL_CreateMutex();
00180 cbmutex = SDL_CreateMutex();
00181 cond = SDL_CreateCond();
00182 thread = 0;
00183 sample_rate = samp_rate;
00184 stereo = is_stereo;
00185 uploading_timbres = false;
00186 next_sysex = 0;
00187
00188
00189 std::memset(mt32_patch_banks,0,sizeof(mt32_patch_banks[0])*128);
00190 std::memset(mt32_timbre_banks,0,sizeof(mt32_timbre_banks[0])*128);
00191 std::memset(mt32_timbre_used,-1,sizeof(mt32_timbre_used[0])*64);
00192 std::memset(mt32_bank_sel,0,sizeof(mt32_bank_sel[0])*LLMD_NUM_SEQ);
00193 std::memset(mt32_patch_bank_sel,0,sizeof(mt32_patch_bank_sel[0])*128);
00194 std::memset(mt32_rhythm_bank,0,sizeof(mt32_rhythm_bank[0])*128);
00195
00196 int code = 0;
00197
00198 if (isSampleProducer()) code = initSoftwareSynth();
00199 else code = initThreadedSynth();
00200
00201 if (code)
00202 {
00203 perr << "Failed to initialize midi player (code: " << code << ")" << endl;
00204 SDL_DestroyMutex(mutex);
00205 SDL_DestroyMutex(cbmutex);
00206 SDL_DestroyCond(cond);
00207 thread = 0;
00208 mutex = 0;
00209 cbmutex = 0;
00210 cond = 0;
00211 }
00212 else
00213 initialized = true;
00214
00215 return code;
00216 }
00217
00218 void LowLevelMidiDriver::destroyMidiDriver()
00219 {
00220 if (!initialized) return;
00221
00222 waitTillNoComMessages();
00223
00224 if (isSampleProducer()) destroySoftwareSynth();
00225 else destroyThreadedSynth();
00226
00227 initialized = false;
00228
00229 SDL_DestroyMutex(mutex);
00230 SDL_DestroyMutex(cbmutex);
00231 SDL_DestroyCond(cond);
00232 cbmutex = 0;
00233 mutex = 0;
00234 thread = 0;
00235 cond = 0;
00236
00237 giveinfo();
00238 }
00239
00240 int LowLevelMidiDriver::maxSequences()
00241 {
00242 return LLMD_NUM_SEQ;
00243 }
00244
00245 void LowLevelMidiDriver::startSequence(int seq_num, XMidiEventList *eventlist, bool repeat, int vol, int branch)
00246 {
00247 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00248
00249 if (!initialized)
00250 return;
00251
00252
00253
00254 while (uploading_timbres) {
00255 waitTillNoComMessages();
00256
00257 lockComMessage();
00258 bool isplaying = playing[3];
00259 unlockComMessage();
00260
00261
00262
00263 if (isplaying) yield();
00264 else uploading_timbres = false;
00265 }
00266
00267 eventlist->incerementCounter();
00268
00269 ComMessage message(LLMD_MSG_PLAY);
00270 message.sequence = seq_num;
00271 message.data.play.list = eventlist;
00272 message.data.play.repeat = repeat;
00273 message.data.play.volume = vol;
00274 message.data.play.branch = branch;
00275
00276 sendComMessage(message);
00277 }
00278
00279 void LowLevelMidiDriver::finishSequence(int seq_num)
00280 {
00281 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00282 if (!initialized) return;
00283 if (uploading_timbres) return;
00284
00285 ComMessage message(LLMD_MSG_FINISH);
00286 message.sequence = seq_num;
00287
00288 sendComMessage(message);
00289 }
00290
00291 void LowLevelMidiDriver::setSequenceVolume(int seq_num, int vol)
00292 {
00293 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00294 if (vol < 0 || vol > 255) return;
00295 if (!initialized) return;
00296 if (uploading_timbres) return;
00297
00298 ComMessage message(LLMD_MSG_SET_VOLUME);
00299 message.sequence = seq_num;
00300 message.data.volume.level = vol;
00301
00302 sendComMessage(message);
00303 }
00304
00305 void LowLevelMidiDriver::setGlobalVolume(int vol)
00306 {
00307 if (vol < 0 || vol > 255) return;
00308 if (!initialized) return;
00309
00310 ComMessage message(LLMD_MSG_SET_VOLUME);
00311 message.sequence = -1;
00312 message.data.volume.level = vol;
00313
00314 sendComMessage(message);
00315 }
00316
00317 void LowLevelMidiDriver::setSequenceSpeed(int seq_num, int speed)
00318 {
00319 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00320 if (speed < 0) return;
00321 if (!initialized) return;
00322 if (uploading_timbres) return;
00323
00324 ComMessage message(LLMD_MSG_SET_SPEED);
00325 message.sequence = seq_num;
00326 message.data.speed.percentage = speed;
00327
00328 sendComMessage(message);
00329 }
00330
00331 bool LowLevelMidiDriver::isSequencePlaying(int seq_num)
00332 {
00333 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return false;
00334 if (uploading_timbres) return false;
00335
00336 waitTillNoComMessages();
00337
00338 lockComMessage();
00339 bool ret = playing[seq_num];
00340 unlockComMessage();
00341
00342 return ret;
00343 }
00344
00345 void LowLevelMidiDriver::pauseSequence(int seq_num)
00346 {
00347 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00348 if (!initialized) return;
00349 if (uploading_timbres) return;
00350
00351 ComMessage message(LLMD_MSG_PAUSE);
00352 message.sequence = seq_num;
00353 message.data.pause.paused = true;
00354
00355 sendComMessage(message);
00356 }
00357
00358 void LowLevelMidiDriver::unpauseSequence(int seq_num)
00359 {
00360 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00361 if (!initialized) return;
00362 if (uploading_timbres) return;
00363
00364 ComMessage message(LLMD_MSG_PAUSE);
00365 message.sequence = seq_num;
00366 message.data.pause.paused = false;
00367
00368 sendComMessage(message);
00369 }
00370
00371 uint32 LowLevelMidiDriver::getSequenceCallbackData(int seq_num)
00372 {
00373 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return 0;
00374
00375 SDL_mutexP(cbmutex);
00376 uint32 ret = callback_data[seq_num];
00377 SDL_mutexV(cbmutex);
00378
00379 return ret;
00380 }
00381
00382
00383
00384
00385
00386 sint32 LowLevelMidiDriver::peekComMessageType()
00387 {
00388 lockComMessage();
00389 sint32 ret = 0;
00390 if (messages.size()) ret = messages.front().type;
00391 unlockComMessage();
00392 return ret;
00393 }
00394
00395 void LowLevelMidiDriver::sendComMessage(ComMessage& message)
00396 {
00397 lockComMessage();
00398 messages.push(message);
00399 SDL_CondSignal(cond);
00400 unlockComMessage();
00401 }
00402
00403 void LowLevelMidiDriver::waitTillNoComMessages()
00404 {
00405 while (peekComMessageType()) yield ();
00406 }
00407
00408 void LowLevelMidiDriver::lockComMessage()
00409 {
00410 SDL_mutexP(mutex);
00411 }
00412
00413 void LowLevelMidiDriver::unlockComMessage()
00414 {
00415 SDL_mutexV(mutex);
00416 }
00417
00418
00419
00420
00421
00422 int LowLevelMidiDriver::initThreadedSynth()
00423 {
00424
00425 giveinfo();
00426
00427 ComMessage message(LLMD_MSG_THREAD_INIT);
00428 sendComMessage(message);
00429
00430 thread = SDL_CreateThread (threadMain_Static, static_cast<void*>(this));
00431
00432 while (peekComMessageType() == LLMD_MSG_THREAD_INIT)
00433 yield ();
00434
00435 int code = 0;
00436
00437 lockComMessage();
00438 {
00439 while (!messages.empty())
00440 {
00441 if (messages.front().type == LLMD_MSG_THREAD_INIT_FAILED)
00442 code = messages.front().data.init_failed.code;
00443 messages.pop();
00444 }
00445 }
00446 unlockComMessage();
00447
00448 return code;
00449 }
00450
00451 void LowLevelMidiDriver::destroyThreadedSynth()
00452 {
00453 ComMessage message(LLMD_MSG_THREAD_EXIT);
00454 sendComMessage(message);
00455
00456 int count = 0;
00457
00458 while (count < 400)
00459 {
00460 giveinfo();
00461
00462 if (peekComMessageType() != 0)
00463 {
00464 yield ();
00465 SDL_Delay(1);
00466 }
00467 else break;
00468
00469 count++;
00470 }
00471
00472
00473 if (count == 400 && peekComMessageType() != 0) {
00474 perr << "MidiPlayer Thread failed to stop in time. Killing it." << std::endl;
00475 SDL_KillThread (thread);
00476 }
00477
00478 lockComMessage();
00479 {
00480
00481 while (!messages.empty()) messages.pop();
00482 }
00483 unlockComMessage();
00484
00485 }
00486
00487 int LowLevelMidiDriver::threadMain_Static(void *data)
00488 {
00489 giveinfo();
00490 LowLevelMidiDriver *ptr=static_cast<LowLevelMidiDriver *>(data);
00491 giveinfo();
00492 return ptr->threadMain();
00493 }
00494
00495 int LowLevelMidiDriver::threadMain()
00496 {
00497 giveinfo();
00498
00499
00500 int code = open();
00501
00502 lockComMessage();
00503 {
00504
00505 while(!messages.empty()) messages.pop();
00506
00507
00508
00509 if (code)
00510 {
00511 ComMessage message(LLMD_MSG_THREAD_INIT_FAILED);
00512 message.data.init_failed.code = code;
00513 messages.push(message);
00514 }
00515 }
00516 unlockComMessage();
00517
00518 if (code) return code;
00519
00520
00521 increaseThreadPriority();
00522
00523
00524 for (;;)
00525 {
00526 xmidi_clock = SDL_GetTicks()*6;
00527 if (playSequences()) break;
00528
00529 sint32 time_till_next = 0x7FFFFFFF;
00530
00531 for (int i = 0; i < LLMD_NUM_SEQ; i++)
00532 {
00533 int seq = i;
00534
00535 if (sequences[seq])
00536 {
00537 sint32 ms = sequences[seq]->timeTillNext();
00538 if (ms < time_till_next) time_till_next = ms;
00539 }
00540 }
00541
00542 if (time_till_next <= LLMD_MINIMUM_YIELD_THRESHOLD)
00543 {
00544 bool wait = false;
00545 lockComMessage();
00546 if (messages.empty()) wait = true;
00547 unlockComMessage();
00548 if (wait)
00549 {
00550
00551 yield();
00552
00553 }
00554 else
00555 {
00556
00557 }
00558 }
00559 else
00560 {
00561 lockComMessage();
00562 if (messages.empty())
00563 {
00564
00565 SDL_CondWaitTimeout(cond, mutex,time_till_next-2);
00566
00567 }
00568 else
00569 {
00570
00571 }
00572 unlockComMessage();
00573 }
00574 }
00575
00576
00577 const char exit_display[] = "Poor Poor Avatar... ";
00578 sendMT32SystemMessage(display_base,0,display_mem_size,exit_display);
00579 sendMT32SystemMessage(all_dev_reset_base,0,1,exit_display);
00580 SDL_Delay(40);
00581
00582
00583 close();
00584
00585 lockComMessage();
00586 {
00587
00588 while(!messages.empty()) messages.pop();
00589 initialized = false;
00590 }
00591 unlockComMessage();
00592
00593 return 0;
00594 }
00595
00596
00597
00598
00599
00600 int LowLevelMidiDriver::initSoftwareSynth()
00601 {
00602
00603 int ret = open();
00604
00605
00606 if (ret) return 1;
00607
00608
00609 total_seconds = 0;
00610 samples_this_second = 0;
00611
00612
00613
00614
00615 if (sample_rate == 11025)
00616 samples_per_iteration = 49;
00617 if (sample_rate == 22050)
00618 samples_per_iteration = 98;
00619 else if (sample_rate == 44100)
00620 samples_per_iteration = 147;
00621 else
00622 {
00623 samples_per_iteration = sample_rate/480;
00624
00625
00626 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00627
00628 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00629 }
00630
00631 return 0;
00632 }
00633
00634 void LowLevelMidiDriver::destroySoftwareSynth()
00635 {
00636
00637 ComMessage message(LLMD_MSG_THREAD_EXIT);
00638 sendComMessage(message);
00639
00640
00641 waitTillNoComMessages();
00642
00643 close();
00644 }
00645
00646 void LowLevelMidiDriver::produceSamples(sint16 *samples, uint32 bytes)
00647 {
00648
00649 if (!initialized) return;
00650
00651 int stereo_mult = 1;
00652 if (stereo) stereo_mult = 2;
00653
00654 uint32 num_samples = bytes/(2*stereo_mult);
00655
00656
00657 while (num_samples > 0)
00658 {
00659 uint32 samples_to_produce = samples_per_iteration;
00660 if (samples_to_produce > num_samples) samples_to_produce = num_samples;
00661
00662
00663 samples_this_second += samples_to_produce;
00664 while (samples_this_second > sample_rate)
00665 {
00666 total_seconds++;
00667 samples_this_second -= sample_rate;
00668 }
00669
00670
00671 xmidi_clock = (total_seconds*6000) + (samples_this_second*6000)/sample_rate;
00672
00673
00674 if (playSequences()) {
00675
00676 lockComMessage();
00677 {
00678
00679 while(!messages.empty()) messages.pop();
00680 initialized = false;
00681 }
00682 unlockComMessage();
00683
00684 break;
00685 }
00686
00687
00688 lowLevelProduceSamples(samples, samples_to_produce);
00689
00690
00691 samples += samples_to_produce*stereo_mult;
00692 num_samples -= samples_to_produce;
00693 }
00694 }
00695
00696
00697
00698
00699
00700 bool LowLevelMidiDriver::playSequences ()
00701 {
00702 int i;
00703
00704
00705 for (i = 0; i < LLMD_NUM_SEQ; i++)
00706 {
00707 int seq = i;
00708
00709 while (sequences[seq] && !peekComMessageType())
00710 {
00711 sint32 pending_events = sequences[seq]->playEvent();
00712
00713 if (pending_events > 0) break;
00714 else if (pending_events == -1)
00715 {
00716 delete sequences[seq];
00717 sequences[seq] = 0;
00718 lockComMessage();
00719 playing[seq] = false;
00720 unlockComMessage();
00721 }
00722 }
00723 }
00724
00725
00726 lockComMessage();
00727 {
00728 while (!messages.empty())
00729 {
00730 ComMessage message = messages.front();
00731
00732
00733 if (messages.back().type == LLMD_MSG_THREAD_EXIT)
00734 message = messages.back();
00735
00736 switch (message.type)
00737 {
00738 case LLMD_MSG_FINISH:
00739 {
00740 delete sequences[message.sequence];
00741 sequences[message.sequence] = 0;
00742 playing[message.sequence] = false;
00743 callback_data[message.sequence] = -1;
00744 unlockAndUnprotectChannel(message.sequence);
00745 }
00746 break;
00747
00748 case LLMD_MSG_THREAD_EXIT:
00749 {
00750 for (i = 0; i < LLMD_NUM_SEQ; i++)
00751 {
00752 delete sequences[i];
00753 sequences[i] = 0;
00754 playing[i] = false;
00755 callback_data[i] = -1;
00756 unlockAndUnprotectChannel(i);
00757 }
00758 }
00759 unlockComMessage();
00760 return true;
00761
00762 case LLMD_MSG_SET_VOLUME:
00763 {
00764 if (message.sequence == -1)
00765 {
00766 global_volume = message.data.volume.level;
00767 for (i = 0; i < LLMD_NUM_SEQ; i++)
00768 if (sequences[i])
00769 sequences[i]->setVolume(sequences[i]->getVolume());
00770 }
00771 else if (sequences[message.sequence])
00772 sequences[message.sequence]->setVolume(message.data.volume.level);
00773 }
00774 break;
00775
00776 case LLMD_MSG_SET_SPEED:
00777 {
00778 if (sequences[message.sequence])
00779 sequences[message.sequence]->setSpeed(message.data.speed.percentage);
00780 }
00781 break;
00782
00783 case LLMD_MSG_PAUSE:
00784 {
00785 if (sequences[message.sequence])
00786 {
00787 if (!message.data.pause.paused) sequences[message.sequence]->unpause();
00788 else sequences[message.sequence]->pause();
00789 }
00790 }
00791 break;
00792
00793 case LLMD_MSG_PLAY:
00794 {
00795
00796 delete sequences[message.sequence];
00797 sequences[message.sequence] = 0;
00798 playing[message.sequence] = false;
00799 callback_data[message.sequence] = -1;
00800 unlockAndUnprotectChannel(message.sequence);
00801
00802 giveinfo();
00803
00804 if (message.data.play.list)
00805 {
00806 sequences[message.sequence] = new XMidiSequence(
00807 this,
00808 message.sequence,
00809 message.data.play.list,
00810 message.data.play.repeat,
00811 message.data.play.volume,
00812 message.data.play.branch);
00813
00814 playing[message.sequence] = true;
00815
00816 uint16 mask = sequences[message.sequence]->getChanMask();
00817
00818
00819
00820
00821
00822
00823 }
00824
00825 }
00826 break;
00827
00828
00829 case LLMD_MSG_PRECACHE_TIMBRES:
00830 {
00831 int count = 0;
00832
00833 for (int bank = 0; bank < 128; bank++)
00834 {
00835 if (mt32_timbre_banks[bank]) for (int timbre = 0; timbre < 128; timbre++)
00836 {
00837 if (mt32_timbre_banks[bank][timbre])
00838 {
00839 uploadTimbre(bank,timbre);
00840 count++;
00841
00842 if (count == 64) break;
00843 }
00844 }
00845 if (count == 64) break;
00846 }
00847
00848 if (mt32_patch_banks[0]) for (int patch = 0; patch < 128; patch++)
00849 {
00850 if (mt32_patch_banks[0][patch] && mt32_patch_banks[0][patch]->timbre_bank >= 2)
00851 setPatchBank(0,patch);
00852 }
00853 }
00854 break;
00855
00856
00857 default:
00858 break;
00859 }
00860
00861
00862 messages.pop();
00863 }
00864 }
00865 unlockComMessage();
00866
00867 return false;
00868 }
00869
00870 void LowLevelMidiDriver::sequenceSendEvent(uint16 sequence_id, uint32 message)
00871 {
00872 int log_chan = message & 0xF;
00873 message &= 0xFFFFFFF0;
00874
00875
00876 if ((message & 0x00F0) == (MIDI_STATUS_CONTROLLER << 4))
00877 {
00878
00879 if ((message & 0xFF00) == (7 << 8))
00880 {
00881 int vol = (message >> 16) & 0xFF;
00882 message &= 0x00FFFF;
00883
00884 vol = (vol * global_volume) / 0xFF;
00885 message |= vol << 16;
00886 }
00887 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_CHAN_LOCK << 8))
00888 {
00889 lockChannel(sequence_id, log_chan, ((message>>16)&0xFF)>=64);
00890 return;
00891 }
00892 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_CHAN_LOCK_PROT << 8))
00893 {
00894 protectChannel(sequence_id, log_chan, ((message>>16)&0xFF)>=64);
00895 return;
00896 }
00897 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_BANK_CHANGE << 8))
00898 {
00899
00900 mt32_bank_sel[sequence_id][log_chan] = (message>>16)&0xFF;
00901
00902 }
00903 }
00904 else if ((message & 0x00F0) == (MIDI_STATUS_PROG_CHANGE << 4))
00905 {
00906 if (mt32_patch_banks[0])
00907 {
00908 int bank = mt32_bank_sel[sequence_id][log_chan];
00909 int patch = (message & 0xFF00)>>8;
00910
00911 if (bank != mt32_patch_bank_sel[patch]) setPatchBank(bank,patch);
00912 }
00913 }
00914 else if ((message & 0x00F0) == (MIDI_STATUS_NOTE_ON << 4) && log_chan == 0x9)
00915 {
00916 int temp = (message>>8)&0xFF;
00917 if (mt32_rhythm_bank[temp]) loadRhythmTemp(temp);
00918 }
00919
00920
00921 int phys_chan = chan_map[sequence_id][log_chan];
00922
00923 if (phys_chan == -2) return;
00924 else if (phys_chan < 0) phys_chan = log_chan;
00925
00926 send(message|phys_chan);
00927 }
00928
00929 void LowLevelMidiDriver::sequenceSendSysEx(uint16 sequence_id, uint8 status, const uint8 *msg, uint16 length)
00930 {
00931
00932 if (status == 0xFF) return;
00933
00934
00935 if (!msg || !length) return;
00936
00937
00938 if (uploading_timbres && length > 7)
00939 {
00940
00941
00942 if (msg[0] == 0x41 && msg[1] == 0x10 && msg[2] == 0x16 && msg[3] == 0x12)
00943 {
00944 uint32 actual_address = (msg[4]<<14) | (msg[5]<<7) | msg[6];
00945
00946 uint32 timbre_add_start = ConvBaseToActual(timbre_base);
00947 uint32 timbre_add_end = timbre_add_start + timbre_mem_offset(64);
00948 uint32 patch_add_start = ConvBaseToActual(patch_base);
00949 uint32 patch_add_end = patch_add_start + patch_mem_offset(128);
00950 uint32 rhythm_add_start = ConvBaseToActual(rhythm_base);
00951 uint32 rhythm_add_end = rhythm_add_start + rhythm_mem_offset(85);
00952 uint32 timbre_temp_add_start = ConvBaseToActual(timbre_temp_base);
00953 uint32 timbre_temp_add_end = timbre_temp_add_start + timbre_mem_offset(8);
00954 uint32 patch_temp_add_start = ConvBaseToActual(patch_temp_base);
00955 uint32 patch_temp_add_end = patch_temp_add_start + patch_temp_offset(8);
00956 uint32 timbre_unk_add_start = ConvBaseToActual(timbre_unk_base);
00957 uint32 timbre_unk_add_end = timbre_unk_add_start + timbre_mem_offset(128);
00958
00959 uint32 sysex_size = length-(4+3+1+1);
00960
00961 if (actual_address >= timbre_add_start && actual_address < timbre_add_end)
00962 {
00963 return;
00964 }
00965 if (actual_address >= timbre_temp_add_start && actual_address < timbre_temp_add_end)
00966 {
00967 return;
00968 }
00969 if (actual_address >= timbre_unk_add_start && actual_address < timbre_unk_add_end)
00970 {
00971 return;
00972 }
00973 if (actual_address >= patch_add_start && actual_address < patch_add_end)
00974 {
00975 return;
00976 }
00977 if (actual_address >= patch_temp_add_start && actual_address < patch_temp_add_end)
00978 {
00979 return;
00980 }
00981 if (actual_address >= rhythm_add_start && actual_address < rhythm_add_end)
00982 {
00983 return;
00984 }
00985 }
00986 }
00987
00988
00989
00990 int ticks = SDL_GetTicks();
00991 if (next_sysex > ticks) SDL_Delay(next_sysex-ticks);
00992 send_sysex(status,msg,length);
00993 next_sysex = SDL_GetTicks() + 40;
00994 }
00995
00996 uint32 LowLevelMidiDriver::getTickCount(uint16 sequence_id)
00997 {
00998 return xmidi_clock;
00999 }
01000
01001 void LowLevelMidiDriver::handleCallbackTrigger(uint16 sequence_id, uint8 data)
01002 {
01003 SDL_mutexP(cbmutex);
01004 callback_data[sequence_id] = data;
01005 SDL_mutexV(cbmutex);
01006 }
01007
01008 int LowLevelMidiDriver::protectChannel(uint16 sequence_id, int chan, bool protect)
01009 {
01010
01011 if (!protect)
01012 {
01013 chan_locks[chan] = -1;
01014 chan_map[sequence_id][chan] = -1;
01015 }
01016
01017 else if (chan_locks[chan] != -2)
01018 {
01019
01020 int relock_sid = -1;
01021 int relock_log = -1;
01022 if (chan_locks[chan] != -1)
01023 {
01024 relock_sid = chan_locks[chan];
01025
01026
01027 for (int c = 0; c < 16; c++)
01028 {
01029 if (chan_map[relock_sid][c] == chan)
01030 {
01031 relock_log = c;
01032 break;
01033 }
01034 }
01035
01036
01037 lockChannel(relock_sid, relock_log, false);
01038 }
01039
01040
01041 chan_locks[chan] = -2;
01042