2007-05-30 21:56:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
2004-11-06 01:41:32 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2005-10-18 01:30:26 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2004-11-06 01:41:32 +00:00
*/
# include "common/scummsys.h"
2011-06-05 18:26:25 +02:00
# include "common/system.h"
2004-11-06 01:41:32 +00:00
# ifdef USE_MT32EMU
2011-02-09 01:09:01 +00:00
# include "audio/softsynth/mt32/mt32emu.h"
2004-11-06 01:41:32 +00:00
2011-02-09 01:09:01 +00:00
# include "audio/softsynth/emumidi.h"
# include "audio/musicplugin.h"
# include "audio/mpu401.h"
2004-11-06 01:41:32 +00:00
# include "common/config-manager.h"
2009-01-30 05:25:17 +00:00
# include "common/debug.h"
2011-04-24 11:34:27 +03:00
# include "common/error.h"
2007-03-17 00:53:21 +00:00
# include "common/events.h"
# include "common/file.h"
2005-01-10 22:06:49 +00:00
# include "common/system.h"
2007-03-17 00:53:21 +00:00
# include "common/util.h"
2009-09-23 00:15:00 +00:00
# include "common/archive.h"
2011-04-24 11:34:27 +03:00
# include "common/textconsole.h"
2010-06-21 21:36:36 +00:00
# include "common/translation.h"
2004-11-06 01:41:32 +00:00
2005-01-06 21:15:52 +00:00
# include "graphics/fontman.h"
2004-11-28 05:35:07 +00:00
# include "graphics/surface.h"
2011-04-24 11:34:27 +03:00
# include "graphics/pixelformat.h"
# include "graphics/palette.h"
# include "graphics/font.h"
2004-11-28 05:35:07 +00:00
2004-11-13 19:24:37 +00:00
class MidiChannel_MT32 : public MidiChannel_MPU401 {
void effectLevel ( byte value ) { }
void chorusLevel ( byte value ) { }
} ;
2004-11-06 01:41:32 +00:00
class MidiDriver_MT32 : public MidiDriver_Emulated {
private :
2004-11-13 19:24:37 +00:00
MidiChannel_MT32 _midiChannels [ 16 ] ;
2004-11-08 10:16:07 +00:00
uint16 _channelMask ;
2004-11-06 01:41:32 +00:00
MT32Emu : : Synth * _synth ;
int _outputRate ;
protected :
2004-11-08 10:16:07 +00:00
void generateSamples ( int16 * buf , int len ) ;
2004-11-06 01:41:32 +00:00
public :
2011-05-25 11:17:11 -04:00
bool _initializing ;
2004-11-28 05:35:07 +00:00
2005-05-10 23:48:48 +00:00
MidiDriver_MT32 ( Audio : : Mixer * mixer ) ;
2004-11-06 01:41:32 +00:00
virtual ~ MidiDriver_MT32 ( ) ;
int open ( ) ;
void close ( ) ;
void send ( uint32 b ) ;
2004-11-13 19:24:37 +00:00
void setPitchBendRange ( byte channel , uint range ) ;
2006-02-27 01:59:07 +00:00
void sysEx ( const byte * msg , uint16 length ) ;
2004-11-06 01:41:32 +00:00
uint32 property ( int prop , uint32 param ) ;
MidiChannel * allocateChannel ( ) ;
MidiChannel * getPercussionChannel ( ) ;
// AudioStream API
bool isStereo ( ) const { return true ; }
int getRate ( ) const { return _outputRate ; }
} ;
2006-10-21 12:44:10 +00:00
class MT32File : public MT32Emu : : File {
2008-07-29 16:09:10 +00:00
Common : : File _in ;
Common : : DumpFile _out ;
2004-11-06 01:41:32 +00:00
public :
bool open ( const char * filename , OpenMode mode ) {
2008-07-29 16:09:10 +00:00
if ( mode = = OpenMode_read )
return _in . open ( filename ) ;
else
return _out . open ( filename ) ;
2004-11-06 01:41:32 +00:00
}
void close ( ) {
2008-07-29 16:09:10 +00:00
_in . close ( ) ;
_out . close ( ) ;
2004-11-06 01:41:32 +00:00
}
2004-11-13 19:24:37 +00:00
size_t read ( void * in , size_t size ) {
2008-07-29 16:09:10 +00:00
return _in . read ( in , size ) ;
2004-11-06 01:41:32 +00:00
}
2004-11-13 19:24:37 +00:00
bool readBit8u ( MT32Emu : : Bit8u * in ) {
2008-07-29 16:09:10 +00:00
byte b = _in . readByte ( ) ;
2008-09-06 20:36:47 +00:00
if ( _in . eos ( ) )
2004-11-06 01:41:32 +00:00
return false ;
2004-11-13 19:24:37 +00:00
* in = b ;
2004-11-06 01:41:32 +00:00
return true ;
}
2004-11-13 19:24:37 +00:00
size_t write ( const void * in , size_t size ) {
2008-07-29 16:09:10 +00:00
return _out . write ( in , size ) ;
2004-11-13 19:24:37 +00:00
}
bool writeBit8u ( MT32Emu : : Bit8u out ) {
2008-07-29 16:09:10 +00:00
_out . writeByte ( out ) ;
2009-05-19 11:42:14 +00:00
return ! _out . err ( ) ;
2004-11-13 19:24:37 +00:00
}
2004-11-06 01:41:32 +00:00
bool isEOF ( ) {
2008-09-06 20:36:47 +00:00
return _in . isOpen ( ) & & _in . eos ( ) ;
2004-11-06 01:41:32 +00:00
}
} ;
2004-11-28 05:35:07 +00:00
static int eatSystemEvents ( ) {
2007-03-17 19:02:05 +00:00
Common : : Event event ;
2007-03-17 00:53:21 +00:00
Common : : EventManager * eventMan = g_system - > getEventManager ( ) ;
while ( eventMan - > pollEvent ( event ) ) {
2004-12-05 17:42:20 +00:00
switch ( event . type ) {
2007-03-17 19:02:05 +00:00
case Common : : EVENT_QUIT :
2004-11-28 05:35:07 +00:00
return 1 ;
2004-11-28 07:07:15 +00:00
default :
break ;
2004-11-28 05:35:07 +00:00
}
}
return 0 ;
}
static void drawProgress ( float progress ) {
2005-01-06 21:15:52 +00:00
const Graphics : : Font & font ( * FontMan . getFontByUsage ( Graphics : : FontManager : : kOSDFont ) ) ;
2010-04-20 18:29:53 +00:00
Graphics : : Surface * screen = g_system - > lockScreen ( ) ;
assert ( screen ) ;
assert ( screen - > pixels ) ;
Graphics : : PixelFormat screenFormat = g_system - > getScreenFormat ( ) ;
int16 w = g_system - > getWidth ( ) / 7 * 5 ;
int16 h = font . getFontHeight ( ) ;
int16 x = g_system - > getWidth ( ) / 7 ;
int16 y = g_system - > getHeight ( ) / 2 - h / 2 ;
Common : : Rect r ( x , y , x + w , y + h ) ;
uint32 col ;
2010-07-21 18:17:51 +00:00
2010-04-20 18:29:53 +00:00
if ( screenFormat . bytesPerPixel > 1 )
col = screenFormat . RGBToColor ( 0 , 171 , 0 ) ;
else
col = 1 ;
screen - > frameRect ( r , col ) ;
2004-11-28 05:35:07 +00:00
r . grow ( - 1 ) ;
2010-04-20 18:29:53 +00:00
r . setWidth ( uint16 ( progress * w ) ) ;
if ( screenFormat . bytesPerPixel > 1 )
col = screenFormat . RGBToColor ( 171 , 0 , 0 ) ;
else
col = 2 ;
screen - > fillRect ( r , col ) ;
g_system - > unlockScreen ( ) ;
2004-11-28 05:35:07 +00:00
g_system - > updateScreen ( ) ;
}
static void drawMessage ( int offset , const Common : : String & text ) {
2005-01-06 21:15:52 +00:00
const Graphics : : Font & font ( * FontMan . getFontByUsage ( Graphics : : FontManager : : kOSDFont ) ) ;
2010-04-20 18:29:53 +00:00
Graphics : : Surface * screen = g_system - > lockScreen ( ) ;
assert ( screen ) ;
assert ( screen - > pixels ) ;
Graphics : : PixelFormat screenFormat = g_system - > getScreenFormat ( ) ;
uint16 h = font . getFontHeight ( ) ;
uint16 y = g_system - > getHeight ( ) / 2 - h / 2 + offset * ( h + 1 ) ;
uint32 col ;
2010-07-21 18:17:51 +00:00
2010-04-20 18:29:53 +00:00
if ( screenFormat . bytesPerPixel > 1 )
col = screenFormat . RGBToColor ( 0 , 0 , 0 ) ;
else
col = 0 ;
Common : : Rect r ( 0 , y , screen - > w , y + h ) ;
screen - > fillRect ( r , col ) ;
if ( screenFormat . bytesPerPixel > 1 )
col = screenFormat . RGBToColor ( 0 , 171 , 0 ) ;
else
col = 1 ;
font . drawString ( screen , text , 0 , y , screen - > w , col , Graphics : : kTextAlignCenter ) ;
g_system - > unlockScreen ( ) ;
2004-11-28 05:35:07 +00:00
g_system - > updateScreen ( ) ;
}
2004-11-13 19:24:37 +00:00
static MT32Emu : : File * MT32_OpenFile ( void * userData , const char * filename , MT32Emu : : File : : OpenMode mode ) {
2004-11-06 01:41:32 +00:00
MT32File * file = new MT32File ( ) ;
if ( ! file - > open ( filename , mode ) ) {
delete file ;
return NULL ;
}
return file ;
}
2004-11-13 19:24:37 +00:00
static void MT32_PrintDebug ( void * userData , const char * fmt , va_list list ) {
2011-05-25 11:17:11 -04:00
if ( ( ( MidiDriver_MT32 * ) userData ) - > _initializing ) {
2010-04-20 18:29:53 +00:00
char buf [ 512 ] ;
2005-04-09 01:52:44 +00:00
vsnprintf ( buf , 512 , fmt , list ) ;
2004-11-28 05:35:07 +00:00
buf [ 70 ] = 0 ; // Truncate to a reasonable length
2010-04-20 18:29:53 +00:00
2004-11-28 05:35:07 +00:00
drawMessage ( 1 , buf ) ;
}
2010-04-20 18:29:53 +00:00
2004-11-13 19:24:37 +00:00
//vdebug(0, fmt, list); // FIXME: Use a higher debug level
}
2004-11-06 01:41:32 +00:00
2004-11-28 05:35:07 +00:00
static int MT32_Report ( void * userData , MT32Emu : : ReportType type , const void * reportData ) {
2009-09-30 16:16:53 +00:00
switch ( type ) {
2004-11-06 02:20:43 +00:00
case MT32Emu : : ReportType_lcdMessage :
2004-11-15 23:33:06 +00:00
g_system - > displayMessageOnOSD ( ( const char * ) reportData ) ;
2004-11-06 02:20:43 +00:00
break ;
2004-11-28 05:35:07 +00:00
case MT32Emu : : ReportType_errorControlROM :
error ( " Failed to load MT32_CONTROL.ROM " ) ;
2004-11-06 02:20:43 +00:00
break ;
2004-11-28 05:35:07 +00:00
case MT32Emu : : ReportType_errorPCMROM :
error ( " Failed to load MT32_PCM.ROM " ) ;
2004-11-06 02:20:43 +00:00
break ;
2004-11-28 05:35:07 +00:00
case MT32Emu : : ReportType_progressInit :
2011-05-25 11:17:11 -04:00
if ( ( ( MidiDriver_MT32 * ) userData ) - > _initializing ) {
2004-11-28 13:08:23 +00:00
drawProgress ( * ( ( const float * ) reportData ) ) ;
2004-11-28 05:35:07 +00:00
return eatSystemEvents ( ) ;
}
2004-11-06 02:20:43 +00:00
break ;
2005-10-18 04:26:51 +00:00
case MT32Emu : : ReportType_availableSSE :
2006-07-21 10:59:55 +00:00
debug ( 1 , " MT32emu: SSE is available " ) ;
2005-10-18 04:26:51 +00:00
break ;
case MT32Emu : : ReportType_usingSSE :
debug ( 1 , " MT32emu: using SSE " ) ;
break ;
case MT32Emu : : ReportType_available3DNow :
2006-07-21 10:59:55 +00:00
debug ( 1 , " MT32emu: 3DNow! is available " ) ;
2005-10-18 04:26:51 +00:00
break ;
case MT32Emu : : ReportType_using3DNow :
2006-07-21 10:59:55 +00:00
debug ( 1 , " MT32emu: using 3DNow! " ) ;
2005-10-18 04:26:51 +00:00
break ;
2004-11-06 02:20:43 +00:00
default :
break ;
}
2004-11-28 05:35:07 +00:00
return 0 ;
2004-11-06 02:20:43 +00:00
}
2004-11-06 01:41:32 +00:00
2004-11-13 19:24:37 +00:00
////////////////////////////////////////
//
// MidiDriver_MT32
//
////////////////////////////////////////
2005-05-10 23:48:48 +00:00
MidiDriver_MT32 : : MidiDriver_MT32 ( Audio : : Mixer * mixer ) : MidiDriver_Emulated ( mixer ) {
2004-11-08 10:16:07 +00:00
_channelMask = 0xFFFF ; // Permit all 16 channels by default
2004-11-06 01:41:32 +00:00
uint i ;
2004-11-08 10:16:07 +00:00
for ( i = 0 ; i < ARRAYSIZE ( _midiChannels ) ; + + i ) {
_midiChannels [ i ] . init ( this , i ) ;
2004-11-06 01:41:32 +00:00
}
_synth = NULL ;
2004-11-28 05:35:07 +00:00
// A higher baseFreq reduces the length used in generateSamples(),
// and means that the timer callback will be called more often.
// That results in more accurate timing.
_baseFreq = 10000 ;
// Unfortunately bugs in the emulator cause inaccurate tuning
// at rates other than 32KHz, thus we produce data at 32KHz and
2005-05-10 23:48:48 +00:00
// rely on Mixer to convert.
2004-11-13 19:24:37 +00:00
_outputRate = 32000 ; //_mixer->getOutputRate();
2011-05-25 11:17:11 -04:00
_initializing = false ;
2004-11-06 01:41:32 +00:00
}
MidiDriver_MT32 : : ~ MidiDriver_MT32 ( ) {
2010-01-03 19:37:43 +00:00
delete _synth ;
2004-11-06 01:41:32 +00:00
}
int MidiDriver_MT32 : : open ( ) {
MT32Emu : : SynthProperties prop ;
if ( _isOpen )
return MERR_ALREADY_OPEN ;
MidiDriver_Emulated : : open ( ) ;
2005-07-30 21:11:48 +00:00
2004-11-06 01:41:32 +00:00
memset ( & prop , 0 , sizeof ( prop ) ) ;
2004-11-14 04:13:15 +00:00
prop . sampleRate = getRate ( ) ;
prop . useReverb = true ;
prop . useDefaultReverb = false ;
prop . reverbType = 0 ;
prop . reverbTime = 5 ;
prop . reverbLevel = 3 ;
2004-11-28 05:35:07 +00:00
prop . userData = this ;
2004-11-13 19:24:37 +00:00
prop . printDebug = MT32_PrintDebug ;
prop . report = MT32_Report ;
2004-11-06 01:41:32 +00:00
prop . openFile = MT32_OpenFile ;
2010-04-20 18:29:53 +00:00
2004-11-06 01:41:32 +00:00
_synth = new MT32Emu : : Synth ( ) ;
2010-04-20 18:29:53 +00:00
Graphics : : PixelFormat screenFormat = g_system - > getScreenFormat ( ) ;
if ( screenFormat . bytesPerPixel = = 1 ) {
const byte dummy_palette [ ] = {
2011-02-13 20:26:02 +01:00
0 , 0 , 0 , // background
0 , 171 , 0 , // border, font
171 , 0 , 0 // fill
2010-04-20 18:29:53 +00:00
} ;
2011-02-07 17:52:38 +00:00
g_system - > getPaletteManager ( ) - > setPalette ( dummy_palette , 0 , 3 ) ;
2010-04-20 18:29:53 +00:00
}
2011-05-25 11:17:11 -04:00
_initializing = true ;
drawMessage ( - 1 , _s ( " Initializing MT-32 Emulator " ) ) ;
2004-11-06 01:41:32 +00:00
if ( ! _synth - > open ( prop ) )
return MERR_DEVICE_NOT_AVAILABLE ;
2011-05-25 11:17:11 -04:00
_initializing = false ;
2010-04-20 18:29:53 +00:00
if ( screenFormat . bytesPerPixel > 1 )
g_system - > fillScreen ( screenFormat . RGBToColor ( 0 , 0 , 0 ) ) ;
else
g_system - > fillScreen ( 0 ) ;
2004-11-28 05:35:07 +00:00
g_system - > updateScreen ( ) ;
2010-04-20 18:29:53 +00:00
2011-03-21 22:50:21 +01:00
_mixer - > playStream ( Audio : : Mixer : : kSFXSoundType , & _mixerSoundHandle , this , - 1 , Audio : : Mixer : : kMaxChannelVolume , 0 , DisposeAfterUse : : NO , true ) ;
2010-04-20 18:29:53 +00:00
2004-11-06 01:41:32 +00:00
return 0 ;
}
void MidiDriver_MT32 : : send ( uint32 b ) {
_synth - > playMsg ( b ) ;
}
2004-11-13 19:24:37 +00:00
void MidiDriver_MT32 : : setPitchBendRange ( byte channel , uint range ) {
if ( range > 24 ) {
2011-05-02 14:42:08 +02:00
warning ( " setPitchBendRange() called with range > 24: %d " , range ) ;
2004-11-13 19:24:37 +00:00
}
byte benderRangeSysex [ 9 ] ;
benderRangeSysex [ 0 ] = 0x41 ; // Roland
benderRangeSysex [ 1 ] = channel ;
benderRangeSysex [ 2 ] = 0x16 ; // MT-32
benderRangeSysex [ 3 ] = 0x12 ; // Write
benderRangeSysex [ 4 ] = 0x00 ;
benderRangeSysex [ 5 ] = 0x00 ;
benderRangeSysex [ 6 ] = 0x04 ;
benderRangeSysex [ 7 ] = ( byte ) range ;
benderRangeSysex [ 8 ] = MT32Emu : : Synth : : calcSysexChecksum ( & benderRangeSysex [ 4 ] , 4 , 0 ) ;
sysEx ( benderRangeSysex , 9 ) ;
}
2006-02-27 01:59:07 +00:00
void MidiDriver_MT32 : : sysEx ( const byte * msg , uint16 length ) {
2004-11-06 01:41:32 +00:00
if ( msg [ 0 ] = = 0xf0 ) {
_synth - > playSysex ( msg , length ) ;
} else {
_synth - > playSysexWithoutFraming ( msg , length ) ;
}
}
void MidiDriver_MT32 : : close ( ) {
if ( ! _isOpen )
return ;
_isOpen = false ;
2004-11-28 05:35:07 +00:00
// Detach the player callback handler
setTimerCallback ( NULL , NULL ) ;
// Detach the mixer callback handler
2011-03-21 22:50:21 +01:00
_mixer - > stopHandle ( _mixerSoundHandle ) ;
2004-11-06 01:41:32 +00:00
_synth - > close ( ) ;
delete _synth ;
_synth = NULL ;
}
2004-11-08 10:16:07 +00:00
void MidiDriver_MT32 : : generateSamples ( int16 * data , int len ) {
2004-11-06 01:41:32 +00:00
_synth - > render ( data , len ) ;
}
2004-11-08 10:16:07 +00:00
uint32 MidiDriver_MT32 : : property ( int prop , uint32 param ) {
2004-11-06 01:41:32 +00:00
switch ( prop ) {
2004-11-08 10:16:07 +00:00
case PROP_CHANNEL_MASK :
_channelMask = param & 0xFFFF ;
return 1 ;
2004-11-06 01:41:32 +00:00
}
return 0 ;
}
MidiChannel * MidiDriver_MT32 : : allocateChannel ( ) {
2004-11-13 19:24:37 +00:00
MidiChannel_MT32 * chan ;
2004-11-06 01:41:32 +00:00
uint i ;
2004-11-08 10:16:07 +00:00
for ( i = 0 ; i < ARRAYSIZE ( _midiChannels ) ; + + i ) {
if ( i = = 9 | | ! ( _channelMask & ( 1 < < i ) ) )
2004-11-06 01:41:32 +00:00
continue ;
2004-11-08 10:16:07 +00:00
chan = & _midiChannels [ i ] ;
2004-11-06 01:41:32 +00:00
if ( chan - > allocate ( ) ) {
return chan ;
}
}
return NULL ;
}
MidiChannel * MidiDriver_MT32 : : getPercussionChannel ( ) {
2004-11-08 10:16:07 +00:00
return & _midiChannels [ 9 ] ;
2004-11-06 01:41:32 +00:00
}
2004-11-28 05:35:07 +00:00
// This code should be used when calling the timer callback from the mixer thread is undesirable.
// Note that it results in less accurate timing.
#if 0
class MidiEvent_MT32 {
public :
MidiEvent_MT32 * _next ;
uint32 _msg ; // 0xFFFFFFFF indicates a sysex message
byte * _data ;
uint32 _len ;
MidiEvent_MT32 ( uint32 msg , byte * data , uint32 len ) {
_msg = msg ;
if ( len > 0 ) {
_data = new byte [ len ] ;
memcpy ( _data , data , len ) ;
}
_len = len ;
_next = NULL ;
}
MidiEvent_MT32 ( ) {
if ( _len > 0 )
delete _data ;
}
} ;
class MidiDriver_ThreadedMT32 : public MidiDriver_MT32 {
private :
2005-01-28 22:05:51 +00:00
OSystem : : Mutex _eventMutex ;
2004-11-28 05:35:07 +00:00
MidiEvent_MT32 * _events ;
2006-06-24 09:34:49 +00:00
TimerManager : : TimerProc _timer_proc ;
2004-11-28 05:35:07 +00:00
void pushMidiEvent ( MidiEvent_MT32 * event ) ;
MidiEvent_MT32 * popMidiEvent ( ) ;
protected :
void send ( uint32 b ) ;
2006-02-27 01:59:07 +00:00
void sysEx ( const byte * msg , uint16 length ) ;
2004-11-28 05:35:07 +00:00
public :
2005-05-10 23:48:48 +00:00
MidiDriver_ThreadedMT32 ( Audio : : Mixer * mixer ) ;
2004-11-28 05:35:07 +00:00
void onTimer ( ) ;
void close ( ) ;
2006-06-24 09:34:49 +00:00
void setTimerCallback ( void * timer_param , TimerManager : : TimerProc timer_proc ) ;
2004-11-28 05:35:07 +00:00
} ;
2005-05-10 23:48:48 +00:00
MidiDriver_ThreadedMT32 : : MidiDriver_ThreadedMT32 ( Audio : : Mixer * mixer ) : MidiDriver_MT32 ( mixer ) {
2004-11-28 05:35:07 +00:00
_events = NULL ;
_timer_proc = NULL ;
}
void MidiDriver_ThreadedMT32 : : close ( ) {
MidiDriver_MT32 : : close ( ) ;
while ( ( popMidiEvent ( ) ! = NULL ) ) {
// Just eat any leftover events
}
}
2006-06-24 09:34:49 +00:00
void MidiDriver_ThreadedMT32 : : setTimerCallback ( void * timer_param , TimerManager : : TimerProc timer_proc ) {
2004-11-28 05:35:07 +00:00
if ( ! _timer_proc | | ! timer_proc ) {
if ( _timer_proc )
2006-10-22 15:42:29 +00:00
_vm - > _timer - > removeTimerProc ( _timer_proc ) ;
2004-11-28 05:35:07 +00:00
_timer_proc = timer_proc ;
if ( timer_proc )
2006-10-22 15:42:29 +00:00
_vm - > _timer - > installTimerProc ( timer_proc , getBaseTempo ( ) , timer_param ) ;
2004-11-28 05:35:07 +00:00
}
}
void MidiDriver_ThreadedMT32 : : pushMidiEvent ( MidiEvent_MT32 * event ) {
2005-01-28 22:05:51 +00:00
Common : : StackLock lock ( _eventMutex ) ;
2004-11-28 05:35:07 +00:00
if ( _events = = NULL ) {
_events = event ;
} else {
MidiEvent_MT32 * last = _events ;
while ( last - > _next ! = NULL )
last = last - > _next ;
last - > _next = event ;
}
}
MidiEvent_MT32 * MidiDriver_ThreadedMT32 : : popMidiEvent ( ) {
2005-01-28 22:05:51 +00:00
Common : : StackLock lock ( _eventMutex ) ;
2004-11-28 05:35:07 +00:00
MidiEvent_MT32 * event ;
event = _events ;
if ( event ! = NULL )
_events = event - > _next ;
return event ;
}
void MidiDriver_ThreadedMT32 : : send ( uint32 b ) {
MidiEvent_MT32 * event = new MidiEvent_MT32 ( b , NULL , 0 ) ;
pushMidiEvent ( event ) ;
}
2006-02-27 01:59:07 +00:00
void MidiDriver_ThreadedMT32 : : sysEx ( const byte * msg , uint16 length ) {
2004-11-28 05:35:07 +00:00
MidiEvent_MT32 * event = new MidiEvent_MT32 ( 0xFFFFFFFF , msg , length ) ;
pushMidiEvent ( event ) ;
}
void MidiDriver_ThreadedMT32 : : onTimer ( ) {
MidiEvent_MT32 * event ;
while ( ( event = popMidiEvent ( ) ) ! = NULL ) {
if ( event - > _msg = = 0xFFFFFFFF ) {
MidiDriver_MT32 : : sysEx ( event - > _data , event - > _len ) ;
} else {
MidiDriver_MT32 : : send ( event - > _msg ) ;
}
delete event ;
}
}
# endif
2008-05-14 14:56:29 +00:00
// Plugin interface
2008-06-13 16:04:43 +00:00
class MT32EmuMusicPlugin : public MusicPluginObject {
2008-05-14 14:56:29 +00:00
public :
2008-06-13 16:04:43 +00:00
const char * getName ( ) const {
2010-06-21 21:36:36 +00:00
return _s ( " MT-32 Emulator " ) ;
2008-05-14 14:56:29 +00:00
}
2008-06-13 16:04:43 +00:00
const char * getId ( ) const {
2008-05-14 14:56:29 +00:00
return " mt32 " ;
}
2008-06-13 16:04:43 +00:00
MusicDevices getDevices ( ) const ;
2011-06-05 18:26:25 +02:00
bool checkDevice ( MidiDriver : : DeviceHandle ) const ;
2010-06-21 21:36:36 +00:00
Common : : Error createInstance ( MidiDriver * * mididriver , MidiDriver : : DeviceHandle = 0 ) const ;
2008-05-14 14:56:29 +00:00
} ;
2008-06-13 16:04:43 +00:00
MusicDevices MT32EmuMusicPlugin : : getDevices ( ) const {
MusicDevices devices ;
devices . push_back ( MusicDevice ( this , " " , MT_MT32 ) ) ;
return devices ;
}
2011-06-05 18:26:25 +02:00
bool MT32EmuMusicPlugin : : checkDevice ( MidiDriver : : DeviceHandle ) const {
if ( ! ( ( Common : : File : : exists ( " MT32_CONTROL.ROM " ) & & Common : : File : : exists ( " MT32_PCM.ROM " ) ) | |
( Common : : File : : exists ( " CM32L_CONTROL.ROM " ) & & Common : : File : : exists ( " CM32L_PCM.ROM " ) ) ) ) {
warning ( " The MT-32 emulator requires the following 2 files (not bundled with ScummVM: \n either 'MT32_CONTROL.ROM' and 'MT32_PCM.ROM' or 'CM32L_CONTROL.ROM' and 'CM32L_PCM.ROM' " ) ;
return false ;
}
return true ;
}
2010-06-21 21:36:36 +00:00
Common : : Error MT32EmuMusicPlugin : : createInstance ( MidiDriver * * mididriver , MidiDriver : : DeviceHandle ) const {
2005-07-30 21:11:48 +00:00
if ( ConfMan . hasKey ( " extrapath " ) )
2009-09-23 00:15:00 +00:00
SearchMan . addDirectory ( " extrapath " , ConfMan . get ( " extrapath " ) ) ;
2008-05-14 14:56:29 +00:00
2010-06-21 21:36:36 +00:00
* mididriver = new MidiDriver_MT32 ( g_system - > getMixer ( ) ) ;
2008-05-14 14:56:29 +00:00
2010-06-21 21:36:36 +00:00
return Common : : kNoError ;
2004-11-06 01:41:32 +00:00
}
2008-05-14 14:56:29 +00:00
//#if PLUGIN_ENABLED_DYNAMIC(MT32)
2008-06-13 16:04:43 +00:00
//REGISTER_PLUGIN_DYNAMIC(MT32, PLUGIN_TYPE_MUSIC, MT32EmuMusicPlugin);
2008-05-14 14:56:29 +00:00
//#else
2008-06-13 16:04:43 +00:00
REGISTER_PLUGIN_STATIC ( MT32 , PLUGIN_TYPE_MUSIC , MT32EmuMusicPlugin ) ;
2008-05-14 14:56:29 +00:00
//#endif
2004-11-06 01:41:32 +00:00
# endif