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