DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/gui/midi.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include <assert.h>
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include <string>
00023 #include <algorithm>
00024 
00025 #include "SDL.h"
00026 
00027 #include "dosbox.h"
00028 #include "control.h"
00029 #include "cross.h"
00030 #include "support.h"
00031 #include "setup.h"
00032 #include "mapper.h"
00033 #include "pic.h"
00034 #include "hardware.h"
00035 #include "timer.h"
00036 
00037 #define SYSEX_SIZE 1024
00038 #define RAWBUF  1024
00039 
00040 Bit8u MIDI_evt_len[256] = {
00041   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x00
00042   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x10
00043   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x20
00044   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x30
00045   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x40
00046   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x50
00047   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x60
00048   0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  // 0x70
00049 
00050   3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3,  // 0x80
00051   3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3,  // 0x90
00052   3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3,  // 0xa0
00053   3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3,  // 0xb0
00054 
00055   2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2,  // 0xc0
00056   2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2,  // 0xd0
00057 
00058   3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3,  // 0xe0
00059 
00060   0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0   // 0xf0
00061 };
00062 
00063 class MidiHandler;
00064 
00065 MidiHandler * handler_list=0;
00066 
00067 class MidiHandler {
00068 public:
00069         MidiHandler() {
00070                 next=handler_list;
00071                 handler_list=this;
00072         };
00073         virtual bool Open(const char * /*conf*/) { return true; };
00074         virtual void Close(void) {};
00075         virtual void PlayMsg(Bit8u * /*msg*/) {};
00076         virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {};
00077         virtual const char * GetName(void) { return "none"; };
00078         virtual void Reset() {};
00079         virtual ~MidiHandler() { };
00080         MidiHandler * next;
00081 };
00082 
00083 MidiHandler Midi_none;
00084 
00085 
00086 static struct midi_state_t {
00087         Bitu status;
00088         Bitu cmd_len;
00089         Bitu cmd_pos;
00090         Bit8u cmd_buf[8];
00091         Bit8u rt_buf[8];
00092         struct midi_state_sysex_t {
00093                 Bit8u buf[SYSEX_SIZE];
00094                 Bitu used;
00095                 Bitu delay;
00096                 Bit32u start;
00097 
00098                 midi_state_sysex_t() : used(0), delay(0), start(0) { }
00099         } sysex;
00100         bool available;
00101         MidiHandler * handler;
00102 
00103         midi_state_t() : status(0x00), cmd_len(0), cmd_pos(0), available(false), handler(NULL) { }
00104 } midi;
00105 
00106 
00107 static struct {
00108         bool init;
00109         bool ignore;
00110 
00111         // NOTE: 16-bit ($ffff = not used, $00-ff = data value)
00112         Bit16u code_80[0x80];                   // note off (w/ velocity)
00113         Bit16u code_90[0x80];                   // note on (w/ velocity)
00114         Bit16u code_a0[0x80];                   // aftertouch (polyphonic key pressure)
00115         Bit16u code_b0[0x80];                   // Continuous controller (GM 1.0 + GS)
00116         Bit16u code_c0[1];                              // patch change
00117         Bit16u code_d0[1];                              // channel pressure (after-touch)
00118         Bit16u code_e0[2];                              // pitch bend
00119         //Bit16u code_f0-ff                             // system messages
00120 
00121         Bit16u code_rpn_coarse[3];              // registered parameter numbers (GM 1.0)
00122         Bit16u code_rpn_fine[3];                        // registered parameter numbers (GM 1.0)
00123 } midi_state[16];
00124 
00125 
00126 
00127 /* Include different midi drivers, lowest ones get checked first for default */
00128 
00129 #if C_MT32
00130 #include "midi_mt32.h"
00131 #endif
00132 
00133 #if C_FLUIDSYNTH
00134 #include "midi_synth.h"
00135 #endif
00136 
00137 #if !defined(WIN32)
00138 # include "midi_timidity.h"
00139 #endif
00140 
00141 #if defined(MACOSX)
00142 
00143 #include "midi_coremidi.h"
00144 #include "midi_coreaudio.h"
00145 
00146 #elif defined (WIN32)
00147 
00148 #include "midi_win32.h"
00149 
00150 #else
00151 
00152 #include "midi_oss.h"
00153 
00154 #endif
00155 
00156 #if defined (HAVE_ALSA)
00157 
00158 #include "midi_alsa.h"
00159 
00160 #endif
00161 
00162 
00163 //#define WIN32_MIDI_STATE_DEBUG
00164 
00165 void MIDI_State_Reset()
00166 {
00167         memset( &midi_state, 0xff, sizeof(midi_state) );
00168 
00169         midi_state[0].init = true;
00170         midi_state[0].ignore = false;
00171 }
00172 
00173 
00174 void MIDI_State_SaveMessage()
00175 {
00176         Bit8u channel, command, arg1, arg2;
00177 
00178         if( midi_state[0].init == false ) {
00179                 MIDI_State_Reset();
00180         }
00181 
00182         if( midi_state[0].ignore == true ) return;
00183 
00184         // skip MUNT
00185         //if( strcmp( midi.handler->GetName(), "mt32" ) == 0 ) {
00186         //      return;
00187         //}
00188 
00189         channel = midi.cmd_buf[0] & 0xf;
00190         command = midi.cmd_buf[0] >> 4;
00191         arg1 = midi.cmd_buf[1];
00192         arg2 = midi.cmd_buf[2];
00193 
00194         switch( command ) {
00195                 case 0x8:               // Note off
00196                         // - arg1 = note, arg2 = velocity off
00197                         midi_state[channel].code_80[arg1] = arg2;
00198 
00199                         memset( &midi_state[channel].code_90[arg1], 0xff, sizeof(midi_state[channel].code_90[arg1]) );
00200                         memset( &midi_state[channel].code_a0[arg1], 0xff, sizeof(midi_state[channel].code_a0[arg1]) );
00201                         memset( midi_state[channel].code_d0, 0xff, sizeof(midi_state[channel].code_d0) );
00202                         break;
00203 
00204 
00205                 case 0x9:               // Note on
00206                         if( arg2 > 0 ) {
00207                                 // - arg1 = note, arg2 = velocity on
00208                                 midi_state[channel].code_90[arg1] = arg2;
00209 
00210                                 memset( &midi_state[channel].code_80[arg1], 0xff, sizeof(midi_state[channel].code_80[arg1]) );
00211                         }
00212                         else {
00213                                 // velocity = 0 (note off)
00214                                 midi_state[channel].code_80[arg1] = arg2;
00215 
00216                                 memset( &midi_state[channel].code_90[arg1], 0xff, sizeof(midi_state[channel].code_90[arg1]) );
00217                                 memset( &midi_state[channel].code_a0[arg1], 0xff, sizeof(midi_state[channel].code_a0[arg1]) );
00218                                 memset( midi_state[channel].code_d0, 0xff, sizeof(midi_state[channel].code_d0) );
00219                         }
00220                         break;
00221 
00222 
00223                 case 0xA:               // Aftertouch (polyphonic pressure)
00224                         midi_state[channel].code_a0[arg1] = arg2;
00225                         break;
00226 
00227 
00228                 case 0xB:               // Controller #s
00229                         midi_state[channel].code_b0[arg1] = arg2;
00230 
00231                         switch( arg1 ) {
00232                                 // General Midi 1.0
00233                                 case 0x01: break;               // Modulation
00234 
00235                                 case 0x07: break;               // Volume
00236                                 case 0x0A: break;               // Pan
00237                                 case 0x0B: break;               // Expression
00238 
00239                                 case 0x40: break;               // Sustain pedal
00240 
00241                                 case 0x64: break;               // Registered Parameter Number (RPN) LSB
00242                                 case 0x65: break;               // Registered Parameter Number (RPN) MSB
00243 
00244                                 case 0x79:                                      // All controllers off
00245                                         /*
00246                                         (likely GM1+GM2)
00247                                         Set Expression (#11) to 127
00248                                         Set Modulation (#1) to 0
00249                                         Set Pedals (#64, #65, #66, #67) to 0
00250                                         Set Registered and Non-registered parameter number LSB and MSB (#98-#101) to null value (127)
00251                                         Set pitch bender to center (64/0)
00252                                         Reset channel pressure to 0 
00253                                         Reset polyphonic pressure for all notes to 0.
00254                                         */
00255                                         memset( midi_state[channel].code_a0, 0xff, sizeof(midi_state[channel].code_a0) );
00256                                         memset( midi_state[channel].code_c0, 0xff, sizeof(midi_state[channel].code_c0) );
00257                                         memset( midi_state[channel].code_d0, 0xff, sizeof(midi_state[channel].code_d0) );
00258                                         memset( midi_state[channel].code_e0, 0xff, sizeof(midi_state[channel].code_e0) );
00259 
00260                                         memset( midi_state[channel].code_b0+0x01, 0xff, sizeof(midi_state[channel].code_b0[0x01]) );
00261                                         memset( midi_state[channel].code_b0+0x0b, 0xff, sizeof(midi_state[channel].code_b0[0x0b]) );
00262                                         memset( midi_state[channel].code_b0+0x40, 0xff, sizeof(midi_state[channel].code_b0[0x40]) );
00263 
00264                                         memset( midi_state[channel].code_rpn_coarse, 0xff, sizeof(midi_state[channel].code_rpn_coarse) );
00265                                         memset( midi_state[channel].code_rpn_fine, 0xff, sizeof(midi_state[channel].code_rpn_fine) );
00266 
00267                                         /*
00268                                         (likely GM1+GM2)
00269                                         Do NOT reset Bank Select (#0/#32)
00270                                         Do NOT reset Volume (#7)
00271                                         Do NOT reset Pan (#10)
00272                                         Do NOT reset Program Change
00273                                         Do NOT reset Effect Controllers (#91-#95) (5B-5F)
00274                                         Do NOT reset Sound Controllers (#70-#79) (46-4F)
00275                                         Do NOT reset other channel mode messages (#120-#127) (78-7F)
00276                                         Do NOT reset registered or non-registered parameters.
00277                                         */
00278                                         //Intentional fall-through
00279 
00280                                 case 0x7b:                                      // All notes off
00281                                         memset( midi_state[channel].code_80, 0xff, sizeof(midi_state[channel].code_80) );
00282                                         memset( midi_state[channel].code_90, 0xff, sizeof(midi_state[channel].code_90) );
00283                                         break;
00284 
00285                                 //******************************************
00286                                 //******************************************
00287                                 //******************************************
00288 
00289                                 // Roland GS
00290                                 case 0x00: break;               // Bank select MSB
00291                                 case 0x05: break;               // Portamento time
00292                                 case 0x20: break;               // Bank select LSB
00293                                 case 0x41: break;               // Portamento
00294                                 case 0x42: break;               // Sostenuto
00295                                 case 0x43: break;               // Soft pedal
00296                                 case 0x54: break;               // Portamento control
00297                                 case 0x5B: break;               // Effect 1 (Reverb) send level
00298                                 case 0x5D: break;               // Effect 3 (Chorus) send level
00299                                 case 0x5E: break;               // Effect 4 (Variation) send level
00300 
00301                                 // TODO: Add more as needed
00302                                 case 0x62: break;               // NRPN LSB
00303                                 case 0x63: break;               // NRPN MSB
00304                                 case 0x78:                                      // All sounds off
00305                                         memset( midi_state[channel].code_80, 0xff, sizeof(midi_state[channel].code_80) );
00306                                         memset( midi_state[channel].code_90, 0xff, sizeof(midi_state[channel].code_90) );
00307                                         break;
00308 
00309                                 /*
00310                                 // Roland MT-32
00311                                 case 0x64:
00312                                         parts[part]->setRPNLSB(velocity);
00313                                         break;
00314                                 case 0x65:
00315                                         parts[part]->setRPNMSB(velocity);
00316                                         break;
00317                                 case 0x7B: // All notes off
00318                                         //printDebug("All notes off");
00319                                         parts[part]->allNotesOff();
00320                                         break;
00321                                 case 0x7C:
00322                                 case 0x7D:
00323                                 case 0x7E:
00324                                 case 0x7F:
00325                                         // CONFIRMED:Mok: A real LAPC-I responds to these controllers as follows:
00326                                         parts[part]->setHoldPedal(false);
00327                                         parts[part]->allNotesOff();
00328                                         break;
00329                                 */
00330 
00331                                 //******************************************
00332                                 //******************************************
00333                                 //******************************************
00334 
00335                                 /*
00336                                 (LSB,MSB) RPN
00337 
00338                                 GM 1.0
00339                                 00,00 = Pitch bend range (fine + coarse)
00340                                 01,00 = Channel Fine tuning
00341                                 02,00 = Channel Coarse tuning
00342                                 7F,7F = None
00343                                 */
00344 
00345                                 case 0x06:                                      // Data entry (coarse)
00346                                         {
00347                                                 int rpn;
00348 
00349                                                 rpn = midi_state[channel].code_b0[0x64];
00350                                                 rpn |= (midi_state[channel].code_b0[0x65]) << 8;
00351 
00352 
00353                                                 // GM 1.0 = 0-2
00354                                                 if( rpn >= 3 ) break;
00355                                                 if( rpn == 0x7f7f ) break;
00356 
00357                                                 midi_state[channel].code_rpn_coarse[rpn] = arg2;
00358                                         }
00359                                         break;
00360 
00361 
00362                                 case 0x26:                                      // Data entry (fine)
00363                                         {
00364                                                 int rpn;
00365 
00366                                                 rpn = midi_state[channel].code_b0[0x64];
00367                                                 rpn |= (midi_state[channel].code_b0[0x65]) << 8;
00368 
00369 
00370                                                 // GM 1.0 = 0-2
00371                                                 if( rpn >= 3 ) break;
00372                                                 if( rpn == 0x7f7f ) break;
00373 
00374                                                 midi_state[channel].code_rpn_fine[rpn] = arg2;
00375                                         }
00376                                         break;
00377 
00378 
00379                                 default:                        // unsupported
00380                                         break;
00381                         }
00382                         break;
00383 
00384 
00385                 case 0xC:               // Patch change
00386                         midi_state[channel].code_c0[0] = arg1;
00387                         break;
00388 
00389                 case 0xD:               // Channel pressure (aftertouch)
00390                         midi_state[channel].code_d0[0] = arg1;
00391                         break;
00392 
00393                 case 0xE:               // Pitch bend
00394                         midi_state[channel].code_e0[0] = arg1;
00395                         midi_state[channel].code_e0[1] = arg2;
00396                         break;
00397 
00398                 case 0xF:               // System messages
00399                         // TODO: General Midi 1.0 says 'Master Volume' SysEx
00400                         break;
00401 
00402                 // unhandled case
00403                 default:
00404                         break;
00405         }
00406 }
00407 
00408 
00409 void MIDI_RawOutByte(Bit8u);
00410 void MIDI_State_LoadMessage()
00411 {
00412         if( midi_state[0].init == false ) {
00413                 MIDI_State_Reset();
00414         }
00415 
00416 
00417         midi_state[0].ignore = true;
00418 
00419         // flush data buffer - throw invalid midi message
00420         MIDI_RawOutByte(0xf7);
00421 
00422         // shutdown sound
00423         for( int lcv=0; lcv<16; lcv++ ) {
00424                 MIDI_RawOutByte( 0xb0+lcv );
00425                 MIDI_RawOutByte( 0x78 );
00426                 MIDI_RawOutByte( 0x00 );
00427                 MIDI_RawOutByte( 0x79 );
00428                 MIDI_RawOutByte( 0x00 );
00429 
00430                 MIDI_RawOutByte( 0x7b );
00431                 MIDI_RawOutByte( 0x00 );
00432         }
00433 
00434 
00435         for( int lcv=0; lcv<16; lcv++ ) {
00436                 // control states (bx - 00-5F)
00437                 MIDI_RawOutByte( 0xb0+lcv );
00438 
00439 
00440                 for( int lcv2=0; lcv2<0x80; lcv2++ ) {
00441                         if( lcv2 >= 0x60 ) break;
00442                         if( midi_state[lcv].code_b0[lcv2] == 0xffff ) continue;
00443 
00444                         // RPN data - coarse / fine
00445                         if( lcv2 == 0x06 ) continue;
00446                         if( lcv2 == 0x26 ) continue;
00447 
00448 
00449                         //MIDI_RawOutByte( 0xb0+lcv );
00450                         MIDI_RawOutByte( lcv2 );
00451                         MIDI_RawOutByte( midi_state[lcv].code_b0[lcv2] & 0xff );
00452                 }
00453 
00454 
00455                 // control states - RPN data (GM 1.0)
00456                 for( int lcv2=0; lcv2<3; lcv2++ ) {
00457                         if( midi_state[lcv].code_rpn_coarse[lcv2] == 0xffff &&
00458                                         midi_state[lcv].code_rpn_fine[lcv2] == 0xffff ) continue;
00459 
00460 
00461                         //MIDI_RawOutByte( 0xb0+lcv );
00462                         MIDI_RawOutByte( 0x64 );
00463                         MIDI_RawOutByte( lcv2 );
00464                         MIDI_RawOutByte( 0x65 );
00465                         MIDI_RawOutByte( 0x00 );
00466 
00467 
00468                         //MIDI_RawOutByte( 0xb0+lcv );
00469                         if( midi_state[lcv].code_rpn_coarse[lcv2] != 0xffff ) {
00470                                 MIDI_RawOutByte( 0x06 );
00471                                 MIDI_RawOutByte( midi_state[lcv].code_rpn_coarse[lcv2] & 0xff );
00472                         }
00473 
00474                         if( midi_state[lcv].code_rpn_fine[lcv2] != 0xffff ) {
00475                                 MIDI_RawOutByte( 0x26 );
00476                                 MIDI_RawOutByte( midi_state[lcv].code_rpn_fine[lcv2] & 0xff );
00477                         }
00478 
00479 
00480                         //MIDI_RawOutByte( 0xb0+lcv );
00481                         MIDI_RawOutByte( 0x64 );
00482                         MIDI_RawOutByte( 0x7f );
00483                         MIDI_RawOutByte( 0x65 );
00484                         MIDI_RawOutByte( 0x7f );
00485                 }
00486 
00487 
00488                 // program change
00489                 if( midi_state[lcv].code_c0[0] != 0xffff ) {
00490                         MIDI_RawOutByte( 0xc0+lcv );
00491                         MIDI_RawOutByte( midi_state[lcv].code_c0[0]&0xff );
00492                 }
00493 
00494 
00495                 // pitch wheel change
00496                 if( midi_state[lcv].code_e0[0] != 0xffff ) {
00497                         MIDI_RawOutByte( 0xe0+lcv );
00498                         MIDI_RawOutByte( midi_state[lcv].code_e0[0]&0xff );
00499                         MIDI_RawOutByte( midi_state[lcv].code_e0[1]&0xff );
00500                 }
00501 
00502                 //******************************************
00503                 //******************************************
00504                 //******************************************
00505 
00506                 // note on
00507                 MIDI_RawOutByte( 0x90+lcv );
00508 
00509                 for( int lcv2=0; lcv2<0x80; lcv2++ ) {
00510                         if( midi_state[lcv].code_90[lcv2] == 0xffff ) continue;
00511 
00512 
00513                         //MIDI_RawOutByte( 0x90+lcv );
00514                         MIDI_RawOutByte( lcv2 );
00515                         MIDI_RawOutByte( midi_state[lcv].code_90[lcv2]&0xff );
00516                 }
00517 
00518 
00519                 // polyphonic aftertouch
00520                 MIDI_RawOutByte( 0xa0+lcv );
00521 
00522                 for( int lcv2=0; lcv2<0x80; lcv2++ ) {
00523                         if( midi_state[lcv].code_a0[lcv2] == 0xffff ) continue;
00524 
00525 
00526                         //MIDI_RawOutByte( 0xa0+lcv );
00527                         MIDI_RawOutByte( lcv2 );
00528                         MIDI_RawOutByte( midi_state[lcv].code_a0[lcv2]&0xff );
00529                 }
00530 
00531 
00532                 // channel aftertouch
00533                 if( midi_state[lcv].code_d0[0] != 0xffff ) {
00534                         MIDI_RawOutByte( 0xd0+lcv );
00535                         MIDI_RawOutByte( midi_state[lcv].code_d0[0]&0xff );
00536                 }
00537         }
00538 
00539         midi_state[0].ignore = false;
00540 }
00541 
00542 
00543 void MIDI_RawOutByte(Bit8u data) {
00544         if (midi.sysex.start) {
00545                 Bit32u passed_ticks = GetTicks() - midi.sysex.start;
00546                 if (passed_ticks < midi.sysex.delay) SDL_Delay(midi.sysex.delay - passed_ticks);
00547         }
00548 
00549         /* Test for a realtime MIDI message */
00550         if (data>=0xf8) {
00551                 midi.rt_buf[0]=data;
00552                 midi.handler->PlayMsg(midi.rt_buf);
00553                 return;
00554         }        
00555         /* Test for a active sysex tranfer */
00556         if (midi.status==0xf0) {
00557                 if (!(data&0x80)) { 
00558                         if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++] = data;
00559                         return;
00560                 } else {
00561                         midi.sysex.buf[midi.sysex.used++] = 0xf7;
00562 
00563                         if ((midi.sysex.start) && (midi.sysex.used >= 4) && (midi.sysex.used <= 9) && (midi.sysex.buf[1] == 0x41) && (midi.sysex.buf[3] == 0x16)) {
00564                                 LOG(LOG_ALL,LOG_ERROR)("MIDI:Skipping invalid MT-32 SysEx midi message (too short to contain a checksum)");
00565                         } else {
00566 //                              LOG(LOG_ALL,LOG_NORMAL)("Play sysex; address:%02X %02X %02X, length:%4d, delay:%3d", midi.sysex.buf[5], midi.sysex.buf[6], midi.sysex.buf[7], midi.sysex.used, midi.sysex.delay);
00567                                 midi.handler->PlaySysex(midi.sysex.buf, midi.sysex.used);
00568                                 if (midi.sysex.start) {
00569                                         if (midi.sysex.buf[5] == 0x7F) {
00570                                                 midi.sysex.delay = 290; // All Parameters reset
00571                                         } else if (midi.sysex.buf[5] == 0x10 && midi.sysex.buf[6] == 0x00 && midi.sysex.buf[7] == 0x04) {
00572                                                 midi.sysex.delay = 145; // Viking Child
00573                                         } else if (midi.sysex.buf[5] == 0x10 && midi.sysex.buf[6] == 0x00 && midi.sysex.buf[7] == 0x01) {
00574                                                 midi.sysex.delay = 30; // Dark Sun 1
00575                                         } else midi.sysex.delay = (Bitu)(((float)(midi.sysex.used) * 1.25f) * 1000.0f / 3125.0f) + 2;
00576                                         midi.sysex.start = GetTicks();
00577                                 }
00578                         }
00579 
00580                         LOG(LOG_ALL,LOG_NORMAL)("Sysex message size %d",(int)midi.sysex.used);
00581                         if (CaptureState & CAPTURE_MIDI) {
00582                                 CAPTURE_AddMidi( true, midi.sysex.used-1, &midi.sysex.buf[1]);
00583                         }
00584                 }
00585         }
00586         if (data&0x80) {
00587                 midi.status=data;
00588                 midi.cmd_pos=0;
00589                 midi.cmd_len=MIDI_evt_len[data];
00590                 if (midi.status==0xf0) {
00591                         midi.sysex.buf[0]=0xf0;
00592                         midi.sysex.used=1;
00593                 }
00594         }
00595         if (midi.cmd_len) {
00596                 midi.cmd_buf[midi.cmd_pos++]=data;
00597                 if (midi.cmd_pos >= midi.cmd_len) {
00598                         if (CaptureState & CAPTURE_MIDI) {
00599                                 CAPTURE_AddMidi(false, midi.cmd_len, midi.cmd_buf);
00600                         }
00601 
00602                         midi.handler->PlayMsg(midi.cmd_buf);
00603                         midi.cmd_pos=1;         //Use Running status
00604 
00605                         MIDI_State_SaveMessage();
00606                 }
00607         }
00608 }
00609 
00610 bool MIDI_Available(void)  {
00611         return midi.available;
00612 }
00613 
00614 class MIDI:public Module_base{
00615 public:
00616         MIDI(Section* configuration):Module_base(configuration){
00617                 Section_prop * section = static_cast<Section_prop *>(configuration);
00618                 const char * dev=section->Get_string("mididevice");
00619                 std::string fullconf = section->Get_string("midiconfig");
00620 #if C_FLUIDSYNTH
00621                 synthsamplerate = section->Get_int("samplerate");
00622                 if (synthsamplerate == 0) synthsamplerate = 44100;
00623 #endif
00624 
00625                 /* If device = "default" go for first handler that works */
00626                 MidiHandler * handler;
00627                 bool opened = false;
00628 
00629 //              MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI");
00630                 midi.sysex.delay = 0;
00631                 midi.sysex.start = 0;
00632                 if (fullconf.find("delaysysex") != std::string::npos) {
00633                         midi.sysex.start = GetTicks();
00634                         fullconf.erase(fullconf.find("delaysysex"));
00635                         LOG(LOG_MISC,LOG_DEBUG)("MIDI:Using delayed SysEx processing");
00636                 }
00637                 std::remove(fullconf.begin(), fullconf.end(), ' ');
00638                 const char * conf = fullconf.c_str();
00639                 midi.status=0x00;
00640                 midi.cmd_pos=0;
00641                 midi.cmd_len=0;
00642 
00643                 if (strcasecmp(dev,"default")) {
00644                         for (handler = handler_list; handler; handler = handler->next) {
00645                                 if (!strcasecmp(dev,handler->GetName())) {
00646                                         opened = handler->Open(conf);
00647                                         break;
00648                                 }
00649                         }
00650                         if (handler == NULL)
00651                                 LOG(LOG_MISC,LOG_DEBUG)("MIDI:Can't find device:%s, finding default handler.",dev);
00652                         else if (!opened)
00653                                 LOG(LOG_MISC,LOG_WARN)("MIDI:Can't open device:%s with config:%s.",dev,conf);
00654                 }
00655 
00656                 if (!opened) {
00657                         for (handler = handler_list; handler; handler = handler->next) {
00658                                 opened = handler->Open(conf);
00659                                 if (opened) break;
00660                         }
00661                 }
00662 
00663                 if (!opened) {
00664                         // This shouldn't be possible
00665                         LOG(LOG_MISC,LOG_WARN)("MIDI:Couldn't open a handler");
00666                         return;
00667                 }
00668 
00669                 midi.available=true;
00670                 midi.handler=handler;
00671                 LOG(LOG_MISC,LOG_DEBUG)("MIDI:Opened device:%s",handler->GetName());
00672 
00673                 // force reset to prevent crashes (when not properly shutdown)
00674                 // ex. Roland VSC = unexpected hard system crash
00675                 midi_state[0].init = false;
00676                 MIDI_State_LoadMessage();
00677         }
00678         ~MIDI(){
00679                 if( midi.status < 0xf0 ) {
00680                         // throw invalid midi message - start new cmd
00681                         MIDI_RawOutByte(0x80);
00682                 }
00683                 else if( midi.status == 0xf0 ) {
00684                         // SysEx - throw invalid midi message
00685                         MIDI_RawOutByte(0xf7);
00686                 }
00687                 if(midi.available) midi.handler->Close();
00688                 midi.available = false;
00689                 midi.handler = 0;
00690         }
00691 };
00692 
00693 
00694 static MIDI* test = NULL;
00695 void MIDI_Destroy(Section* /*sec*/){
00696         if (test != NULL) {
00697                 delete test;
00698                 test = NULL;
00699         }
00700 }
00701 
00702 void MIDI_Init() {
00703         LOG(LOG_MISC,LOG_DEBUG)("Initializing MIDI emulation");
00704 
00705         test = new MIDI(control->GetSection("midi"));
00706         AddExitFunction(AddExitFunctionFuncPair(MIDI_Destroy),true);
00707 }
00708 
00709 void MIDI_GUI_OnSectionPropChange(Section *x) {
00710     (void)x;//UNUSED
00711 
00712         if (test != NULL) {
00713                 delete test;
00714                 test = NULL;
00715         }
00716 
00717         test = new MIDI(control->GetSection("midi"));
00718 }
00719