DOSBox-X
|
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 }