diff options
| author | Alejandro Marzini | 2010-07-13 04:31:15 +0000 | 
|---|---|---|
| committer | Alejandro Marzini | 2010-07-13 04:31:15 +0000 | 
| commit | 609e08d5dbae3179eddf981abe73d69009432de4 (patch) | |
| tree | cddbd0a0e69eaa53b85f98f96dc410a307773f08 /sound | |
| parent | 8b6a670391f1b5103e3761d78eef8f41d64cf8cd (diff) | |
| parent | 03c0faa5d76f547603ee6389cdf958e2a6f0f43d (diff) | |
| download | scummvm-rg350-609e08d5dbae3179eddf981abe73d69009432de4.tar.gz scummvm-rg350-609e08d5dbae3179eddf981abe73d69009432de4.tar.bz2 scummvm-rg350-609e08d5dbae3179eddf981abe73d69009432de4.zip  | |
Merged from trunk, from Rev 49499 to HEAD
svn-id: r50840
Diffstat (limited to 'sound')
| -rw-r--r-- | sound/audiostream.cpp | 6 | ||||
| -rw-r--r-- | sound/audiostream.h | 48 | ||||
| -rw-r--r-- | sound/decoders/adpcm.h | 2 | ||||
| -rw-r--r-- | sound/decoders/aiff.cpp | 11 | ||||
| -rw-r--r-- | sound/decoders/aiff.h | 9 | ||||
| -rw-r--r-- | sound/decoders/flac.cpp | 6 | ||||
| -rw-r--r-- | sound/decoders/flac.h | 4 | ||||
| -rw-r--r-- | sound/decoders/mp3.h | 4 | ||||
| -rw-r--r-- | sound/decoders/vag.h | 2 | ||||
| -rw-r--r-- | sound/decoders/voc.h | 2 | ||||
| -rw-r--r-- | sound/decoders/vorbis.cpp | 2 | ||||
| -rw-r--r-- | sound/decoders/vorbis.h | 4 | ||||
| -rw-r--r-- | sound/decoders/wave.h | 4 | ||||
| -rw-r--r-- | sound/fmopl.cpp | 5 | ||||
| -rw-r--r-- | sound/mididrv.cpp | 402 | ||||
| -rw-r--r-- | sound/mididrv.h | 152 | ||||
| -rw-r--r-- | sound/midiparser.cpp | 22 | ||||
| -rw-r--r-- | sound/midiparser.h | 8 | ||||
| -rw-r--r-- | sound/mods/protracker.h | 2 | ||||
| -rw-r--r-- | sound/musicplugin.cpp | 20 | ||||
| -rw-r--r-- | sound/musicplugin.h | 32 | ||||
| -rw-r--r-- | sound/null.cpp | 54 | ||||
| -rw-r--r-- | sound/null.h | 56 | ||||
| -rw-r--r-- | sound/softsynth/adlib.cpp | 16 | ||||
| -rw-r--r-- | sound/softsynth/fluidsynth.cpp | 13 | ||||
| -rw-r--r-- | sound/softsynth/mt32.cpp | 23 | ||||
| -rw-r--r-- | sound/softsynth/pcspk.cpp | 57 | ||||
| -rw-r--r-- | sound/softsynth/sid.cpp | 2 | ||||
| -rw-r--r-- | sound/softsynth/ym2612.cpp | 16 | 
29 files changed, 526 insertions, 458 deletions
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index ce2c521e5e..a092e6c29d 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -95,6 +95,12 @@ SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &b  LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse)      : _parent(stream), _disposeAfterUse(disposeAfterUse), _loops(loops), _completeIterations(0) { +	assert(stream); + +	if (!stream->rewind()) { +		// TODO: Properly indicate error +		_loops = _completeIterations = 1; +	}  }  LoopingAudioStream::~LoopingAudioStream() { diff --git a/sound/audiostream.h b/sound/audiostream.h index 37a1953bb9..64ad128931 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -109,6 +109,9 @@ public:  	/**  	 * Creates a looping audio stream object.  	 * +	 * Note that on creation of the LoopingAudioStream object +	 * the underlying stream will be rewound. +	 *  	 * @see makeLoopingAudioStream  	 *  	 * @param stream Stream to loop @@ -126,6 +129,7 @@ public:  	/**  	 * Returns number of loops the stream has played. +	 *  	 * @param numLoops number of loops to play, 0 - infinite  	 */  	uint getCompleteIterations() const { return _completeIterations; } @@ -145,8 +149,8 @@ private:   * overhead down, when the code does not require any functionality only offered   * by LoopingAudioStream.   * - * @param stream Stream to loop (will be automatically destroyed, when the looping is done) - * @param loops How often to loop (0 = infinite) + * @param stream  Stream to loop (will be automatically destroyed, when the looping is done) + * @param loops   How often to loop (0 = infinite)   * @return A new AudioStream, which offers the desired functionality.   */  AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops); @@ -162,7 +166,8 @@ public:  	 * Tries to load a file by trying all available formats.  	 * In case of an error, the file handle will be closed, but deleting  	 * it is still the responsibility of the caller. -	 * @param basename  a filename without an extension +	 * +	 * @param basename a filename without an extension  	 * @return  an SeekableAudioStream ready to use in case of success;  	 *          NULL in case of an error (e.g. invalid/nonexisting file)  	 */ @@ -208,9 +213,9 @@ public:   * by LoopingAudioStream.   *   * @param stream Stream to loop (will be automatically destroyed, when the looping is done) - * @param start Starttime of the stream interval to be looped - * @param end End of the stream interval to be looped (a zero time, means till end) - * @param loops How often to loop (0 = infinite) + * @param start  Starttime of the stream interval to be looped + * @param end    End of the stream interval to be looped (a zero time, means till end) + * @param loops  How often to loop (0 = infinite)   * @return A new AudioStream, which offers the desired functionality.   */  AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops); @@ -232,10 +237,13 @@ public:  	/**  	 * Constructor for a SubLoopingAudioStream.  	 * -	 * @param stream Stream to loop -	 * @param loops How often the stream should be looped (0 means infinite) -	 * @param loopStart Start of the loop (this must be smaller than loopEnd) -	 * @param loopEnd End of the loop (thus must be greater than loopStart) +	 * Note that on creation of the SubLoopingAudioStream object +	 * the underlying stream will be rewound. +	 * +	 * @param stream          Stream to loop +	 * @param loops           How often the stream should be looped (0 means infinite) +	 * @param loopStart       Start of the loop (this must be smaller than loopEnd) +	 * @param loopEnd         End of the loop (thus must be greater than loopStart)  	 * @param disposeAfterUse Whether the stream should be disposed, when the  	 *                        SubLoopingAudioStream is destroyed.  	 */ @@ -279,9 +287,9 @@ public:  	/**  	 * Creates a new SubSeekableAudioStream.  	 * -	 * @param parent parent stream object. -	 * @param start Start time. -	 * @param end End time. +	 * @param parent          parent stream object. +	 * @param start           Start time. +	 * @param end             End time.  	 * @param disposeAfterUse Whether the parent stream object should be destroyed on destruction of the SubSeekableAudioStream.  	 */  	SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); @@ -317,7 +325,7 @@ public:  	 * contained in it has been played.  	 */  	virtual void queueAudioStream(Audio::AudioStream *audStream, -						DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0; +	                              DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0;  	/**  	 * Queue a block of raw audio data for playback. This stream plays all @@ -327,10 +335,10 @@ public:  	 *  	 * @note Make sure to allocate the data block with malloc(), not with new[].  	 * -	 * @param data	pointer to the audio data block -	 * @param size	length of the audio data block -	 * @param disposeAfterUse	if equal to DisposeAfterUse::YES, the block is released using free() after use. -	 * @param flags	a bit-ORed combination of RawFlags describing the audio data format +	 * @param data             pointer to the audio data block +	 * @param size             length of the audio data block +	 * @param disposeAfterUse  if equal to DisposeAfterUse::YES, the block is released using free() after use. +	 * @param flags            a bit-ORed combination of RawFlags describing the audio data format  	 */  	void queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags); @@ -357,8 +365,8 @@ QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo);   * Converts a point in time to a precise sample offset   * with the given parameters.   * - * @param where Point in time. - * @param rate Rate of the stream. + * @param where    Point in time. + * @param rate     Rate of the stream.   * @param isStereo Is the stream a stereo stream?   */  Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo); diff --git a/sound/decoders/adpcm.h b/sound/decoders/adpcm.h index 7452478f35..04dbb1a521 100644 --- a/sound/decoders/adpcm.h +++ b/sound/decoders/adpcm.h @@ -71,7 +71,7 @@ enum typesADPCM {   * @param rate              the sampling rate   * @param channels          the number of channels   * @param blockAlign        block alignment ??? - * @return   a new RewindableAudioStream, or NULL, if an error occured + * @return   a new RewindableAudioStream, or NULL, if an error occurred   */  RewindableAudioStream *makeADPCMStream(      Common::SeekableReadStream *stream, diff --git a/sound/decoders/aiff.cpp b/sound/decoders/aiff.cpp index 2f12669072..b76410f8d1 100644 --- a/sound/decoders/aiff.cpp +++ b/sound/decoders/aiff.cpp @@ -161,16 +161,21 @@ bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate  	return true;  } -SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream) { +SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, +	DisposeAfterUse::Flag disposeAfterUse) {  	int size, rate;  	byte *data, flags; -	if (!loadAIFFFromStream(stream, size, rate, flags)) +	if (!loadAIFFFromStream(*stream, size, rate, flags)) { +		if (disposeAfterUse == DisposeAfterUse::YES) +			delete stream;  		return 0; +	}  	data = (byte *)malloc(size);  	assert(data); -	stream.read(data, size); +	stream->read(data, size); +	delete stream;  	// Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES.  	return makeRawStream(data, size, rate, flags); diff --git a/sound/decoders/aiff.h b/sound/decoders/aiff.h index e8a3b6f0b0..53f86c95fd 100644 --- a/sound/decoders/aiff.h +++ b/sound/decoders/aiff.h @@ -34,6 +34,7 @@  #define SOUND_AIFF_H  #include "common/scummsys.h" +#include "common/types.h"  namespace Common { class SeekableReadStream; } @@ -55,8 +56,14 @@ extern bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, in   * from that data.   *   * This function uses loadAIFFFromStream() internally. + * + * @param stream			the SeekableReadStream from which to read the AIFF data + * @param disposeAfterUse	whether to delete the stream after use + * @return	a new SeekableAudioStream, or NULL, if an error occurred   */ -SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream); +SeekableAudioStream *makeAIFFStream( +	Common::SeekableReadStream *stream, +	DisposeAfterUse::Flag disposeAfterUse);  } // End of namespace Audio diff --git a/sound/decoders/flac.cpp b/sound/decoders/flac.cpp index fb9499e31f..2a92735616 100644 --- a/sound/decoders/flac.cpp +++ b/sound/decoders/flac.cpp @@ -229,7 +229,7 @@ FLACStream::FLACStream(Common::SeekableReadStream *inStream, bool dispose)  		if (processUntilEndOfMetadata() && _streaminfo.channels > 0) {  			_lastSample = _streaminfo.total_samples + 1;  			_length = Timestamp(0, _lastSample - 1, getRate()); -			return; // no error occured +			return; // no error occurred  		}  	} @@ -354,7 +354,7 @@ int FLACStream::readBuffer(int16 *buffer, const int numSamples) {  		break;  	default:  		decoderOk = false; -		warning("FLACStream: An error occured while decoding. DecoderState is: %s", +		warning("FLACStream: An error occurred while decoding. DecoderState is: %s",  			FLAC__StreamDecoderStateString[getStreamDecoderState()]);  	} @@ -667,7 +667,7 @@ inline void FLACStream::callbackMetadata(const ::FLAC__StreamMetadata *metadata)  }  inline void FLACStream::callbackError(::FLAC__StreamDecoderErrorStatus status) {  	// some of these are non-critical-Errors -	debug(1, "FLACStream: An error occured while decoding. DecoderState is: %s", +	debug(1, "FLACStream: An error occurred while decoding. DecoderState is: %s",  			FLAC__StreamDecoderErrorStatusString[status]);  } diff --git a/sound/decoders/flac.h b/sound/decoders/flac.h index 982450c045..3c00ec3d5d 100644 --- a/sound/decoders/flac.h +++ b/sound/decoders/flac.h @@ -41,8 +41,8 @@  #ifndef SOUND_FLAC_H  #define SOUND_FLAC_H -#include "common/types.h"  #include "common/scummsys.h" +#include "common/types.h"  #ifdef USE_FLAC @@ -61,7 +61,7 @@ class SeekableAudioStream;   *   * @param stream            the SeekableReadStream from which to read the FLAC data   * @param disposeAfterUse   whether to delete the stream after use - * @return   a new SeekableAudioStream, or NULL, if an error occured + * @return   a new SeekableAudioStream, or NULL, if an error occurred   */  SeekableAudioStream *makeFLACStream(  	Common::SeekableReadStream *stream, diff --git a/sound/decoders/mp3.h b/sound/decoders/mp3.h index 3175df5e92..ed54c8b013 100644 --- a/sound/decoders/mp3.h +++ b/sound/decoders/mp3.h @@ -41,8 +41,8 @@  #ifndef SOUND_MP3_H  #define SOUND_MP3_H -#include "common/types.h"  #include "common/scummsys.h" +#include "common/types.h"  #ifdef USE_MAD @@ -61,7 +61,7 @@ class SeekableAudioStream;   *   * @param stream			the SeekableReadStream from which to read the MP3 data   * @param disposeAfterUse	whether to delete the stream after use - * @return	a new SeekableAudioStream, or NULL, if an error occured + * @return	a new SeekableAudioStream, or NULL, if an error occurred   */  SeekableAudioStream *makeMP3Stream(  	Common::SeekableReadStream *stream, diff --git a/sound/decoders/vag.h b/sound/decoders/vag.h index 7e0ed255be..cdf91a8ea1 100644 --- a/sound/decoders/vag.h +++ b/sound/decoders/vag.h @@ -49,7 +49,7 @@ class RewindableAudioStream;   *   * @param stream            the SeekableReadStream from which to read the ADPCM data   * @param rate              the sampling rate - * @return   a new RewindableAudioStream, or NULL, if an error occured + * @return   a new RewindableAudioStream, or NULL, if an error occurred   */  RewindableAudioStream *makeVagStream(  	Common::SeekableReadStream *stream, diff --git a/sound/decoders/voc.h b/sound/decoders/voc.h index 79956ee62a..82cc261f2c 100644 --- a/sound/decoders/voc.h +++ b/sound/decoders/voc.h @@ -38,8 +38,8 @@  #ifndef SOUND_VOC_H  #define SOUND_VOC_H -#include "common/types.h"  #include "common/scummsys.h" +#include "common/types.h"  namespace Common { class ReadStream; }  namespace Common { class SeekableReadStream; } diff --git a/sound/decoders/vorbis.cpp b/sound/decoders/vorbis.cpp index a8ac7784f5..5aeb40c139 100644 --- a/sound/decoders/vorbis.cpp +++ b/sound/decoders/vorbis.cpp @@ -34,7 +34,7 @@  #include "sound/audiostream.h"  #ifdef USE_TREMOR -#if defined(ANDROID) || defined(__GP32__) // custom libtremor locations +#if defined(__GP32__) // custom libtremor locations  #include <ivorbisfile.h>  #else  #include <tremor/ivorbisfile.h> diff --git a/sound/decoders/vorbis.h b/sound/decoders/vorbis.h index dd0a89bfdd..0a0cf43bc9 100644 --- a/sound/decoders/vorbis.h +++ b/sound/decoders/vorbis.h @@ -41,8 +41,8 @@  #ifndef SOUND_VORBIS_H  #define SOUND_VORBIS_H -#include "common/types.h"  #include "common/scummsys.h" +#include "common/types.h"  #ifdef USE_VORBIS @@ -61,7 +61,7 @@ class SeekableAudioStream;   *   * @param stream			the SeekableReadStream from which to read the Ogg Vorbis data   * @param disposeAfterUse	whether to delete the stream after use - * @return	a new SeekableAudioStream, or NULL, if an error occured + * @return	a new SeekableAudioStream, or NULL, if an error occurred   */  SeekableAudioStream *makeVorbisStream(  	Common::SeekableReadStream *stream, diff --git a/sound/decoders/wave.h b/sound/decoders/wave.h index f0e3bb249b..edd37e7ac9 100644 --- a/sound/decoders/wave.h +++ b/sound/decoders/wave.h @@ -38,8 +38,8 @@  #ifndef SOUND_WAVE_H  #define SOUND_WAVE_H -#include "common/types.h"  #include "common/scummsys.h" +#include "common/types.h"  namespace Common { class SeekableReadStream; } @@ -71,7 +71,7 @@ extern bool loadWAVFromStream(   *   * @param stream			the SeekableReadStream from which to read the WAVE data   * @param disposeAfterUse	whether to delete the stream after use - * @return	a new RewindableAudioStream, or NULL, if an error occured + * @return	a new RewindableAudioStream, or NULL, if an error occurred   */  RewindableAudioStream *makeWAVStream(  	Common::SeekableReadStream *stream, diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp index 8fdddc20f8..16dc3986d6 100644 --- a/sound/fmopl.cpp +++ b/sound/fmopl.cpp @@ -28,6 +28,7 @@  #include "sound/softsynth/opl/mame.h"  #include "common/config-manager.h" +#include "common/translation.h"  namespace OPL { @@ -47,9 +48,9 @@ OPL::OPL() {  const Config::EmulatorDescription Config::_drivers[] = {  	{ "auto", "<default>", kAuto, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, -	{ "mame", "MAME OPL emulator", kMame, kFlagOpl2 }, +	{ "mame", _s("MAME OPL emulator"), kMame, kFlagOpl2 },  #ifndef DISABLE_DOSBOX_OPL -	{ "db", "DOSBox OPL emulator", kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, +	{ "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },  #endif  	{ 0, 0, 0, 0 }  }; diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index a9a782184e..aaff78bf92 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -29,72 +29,8 @@  #include "common/system.h"  #include "common/util.h"  #include "sound/mididrv.h" - -/** Internal list of all available 'midi' drivers. */ -static const MidiDriverDescription s_musicDrivers[] = { - -	// The flags for the "auto" & "null" drivers indicate that they are anything -	// you want it to be. -	{"auto", "<default>", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, -	{"null", "No music", MD_NULL, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, - -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -	{"windows", "Windows MIDI", MD_WINDOWS, MDT_MIDI}, -#endif - -#if defined(UNIX) && defined(USE_ALSA) -	{"alsa", "ALSA", MD_ALSA, MDT_MIDI}, -#endif - -#if defined(__MINT__) -	{"stmidi", "Atari ST MIDI", MD_STMIDI, MDT_MIDI}, -#endif - -#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__) -	{"seq", "SEQ", MD_SEQ, MDT_MIDI}, -#endif - -#if defined(IRIX) -	{"dmedia", "DMedia", MD_DMEDIA, MDT_MIDI}, -#endif - -#if defined(__amigaos4__) -	{"camd", "CAMD", MD_CAMD, MDT_MIDI}, -#endif - -#if defined(MACOSX) -	{"core", "CoreAudio", MD_COREAUDIO, MDT_MIDI}, -//	{"coreaudio", "CoreAudio", MD_COREAUDIO, MDT_MIDI}, -	{"coremidi", "CoreMIDI", MD_COREMIDI, MDT_MIDI}, -#endif - -#if defined(PALMOS_MODE) -#	if defined(COMPILE_CLIE) -	{"ypa1", "Yamaha Pa1", MD_YPA1, MDT_MIDI}, -#	elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM)) -	{"zodiac", "Tapwave Zodiac", MD_ZODIAC, MDT_MIDI}, -#	endif -#endif - -#ifdef USE_FLUIDSYNTH -	{"fluidsynth", "FluidSynth", MD_FLUIDSYNTH, MDT_MIDI}, -#endif -#ifdef USE_MT32EMU -	{"mt32", "MT-32 Emulation", MD_MT32, MDT_MIDI}, -#endif - -	// The flags for the "adlib" driver indicates that it can do AdLib and MIDI. -	{"adlib", "AdLib", MD_ADLIB, MDT_ADLIB}, -	{"pcspk", "PC Speaker", MD_PCSPK, MDT_PCSPK}, -	{"pcjr", "IBM PCjr", MD_PCJR, MDT_PCSPK}, -	{"cms", "Creative Music System", MD_CMS, MDT_CMS}, -	{"towns", "FM Towns", MD_TOWNS, MDT_TOWNS}, -#if defined(UNIX) -	{"timidity", "TiMidity", MD_TIMIDITY, MDT_MIDI}, -#endif - -	{0, 0, MD_NULL, MDT_NONE} -}; +#include "sound/musicplugin.h" +#include "common/translation.h"  const byte MidiDriver::_mt32ToGm[128] = {  //	  0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F @@ -120,169 +56,221 @@ const byte MidiDriver::_gmToMt32[128] = {  	101, 103, 100, 120, 117, 113,  99, 128, 128, 128, 128, 124, 123, 128, 128, 128, // 7x  }; -const MidiDriverDescription *MidiDriver::getAvailableMidiDrivers() { -	return s_musicDrivers; -} +static const uint32 GUIOMapping[] = { +	MT_PCSPK,		Common::GUIO_MIDIPCSPK, +	/*MDT_CMS,		Common::GUIO_MIDICMS,*/ +	MT_PCJR,		Common::GUIO_MIDIPCJR, +	MT_ADLIB,		Common::GUIO_MIDIADLIB, +	MT_TOWNS,		Common::GUIO_MIDITOWNS, +	MT_GM,			Common::GUIO_MIDIGM, +	MT_MT32,		Common::GUIO_MIDIMT32, +	0,		0 +}; -const MidiDriverDescription *MidiDriver::findMusicDriver(const Common::String &str) { -	if (str.empty()) -		return 0; +uint32 MidiDriver::musicType2GUIO(uint32 musicType) { +	uint32 res = 0; + +	for (int i = 0; GUIOMapping[i] || GUIOMapping[i + 1]; i += 2) { +		if (musicType == GUIOMapping[i] || musicType == (uint32)-1) +			res |= GUIOMapping[i + 1]; +	} + +	return res; +} -	const char *s = str.c_str(); -	int len = 0; -	const MidiDriverDescription *md = s_musicDrivers; +bool MidiDriver::_forceTypeMT32 = false; -	// Scan for string end or a colon -	while (s[len] != 0 && s[len] != ':') -		len++; +MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) { +	if (_forceTypeMT32) +		return MT_MT32; -	while (md->name) { -		// Compare the string passed to us with the current table entry. -		// We ignore any characters following an (optional) colon ':' -		// contained in str. -		if (!scumm_strnicmp(md->name, s, len)) { -			return md; +	if (handle) { +		const MusicPlugin::List p = MusicMan.getPlugins(); +		for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { +			MusicDevices i = (**m)->getDevices(); +			for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { +				if (handle == d->getHandle()) +					return d->getMusicType(); +			}  		} -		md++;  	} - -	return 0; +	 +	return MT_INVALID;  } -static MidiDriverType getDefaultMIDIDriver() { -#if defined(WIN32) && !defined(_WIN32_WCE) &&  !defined(__SYMBIAN32__) -	return MD_WINDOWS; -#elif defined(MACOSX) -	return MD_COREAUDIO; -#elif defined(PALMOS_MODE) -  #if defined(COMPILE_CLIE) -	return MD_YPA1; -  #elif defined(COMPILE_ZODIAC) -	return MD_ZODIAC; -  #else -	return MD_NULL; -  #endif -#else -	return MD_NULL; -#endif -} +Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType type) { +	if (handle) { +		const MusicPlugin::List p = MusicMan.getPlugins(); +		for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { +			MusicDevices i = (**m)->getDevices(); +			for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { +				if (handle == d->getHandle()) { +					if (type == kDriverName) +						return d->getMusicDriverName(); +					else if (type == kDriverId) +						return d->getMusicDriverId(); +					else if (type == kDeviceId) +						return d->getCompleteId(); +					else +						return Common::String("auto"); +				} +			} +		} +	} -MidiDriverType MidiDriver::parseMusicDriver(const Common::String &str) { -	const MidiDriverDescription *md = findMusicDriver(str); -	if (md) -		return md->id; -	return MD_AUTO; +	return Common::String("auto");  } -MidiDriverType MidiDriver::detectMusicDriver(int flags) { -	MidiDriverType musicDriver; +MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) { +	// Query the selected music device (defaults to MT_AUTO device). +	DeviceHandle hdl = getDeviceHandle(ConfMan.get("music_driver")); -	// Query the selected music driver (defaults to MD_AUTO). -	const MidiDriverDescription *md = findMusicDriver(ConfMan.get("music_driver")); +	_forceTypeMT32 = false;  	// Check whether the selected music driver is compatible with the  	// given flags. -	if (!md || !(md->flags & flags)) -		musicDriver = MD_AUTO; -	else -		musicDriver = md->id; - -	// If the selected driver is MD_AUTO, we try to determine -	// a suitable and "optimal" music driver. -	if (musicDriver == MD_AUTO) { - -		if (flags & MDT_PREFER_MIDI) { -			// A MIDI music driver is preferred. Of course this implies -			// that MIDI is actually listed in flags, so we verify that. -			assert(flags & MDT_MIDI); - -			// Query the default MIDI driver. It's possible that there -			// is none, in which case we revert to AUTO mode. -			musicDriver = getDefaultMIDIDriver(); -			if (musicDriver == MD_NULL) -				musicDriver = MD_AUTO; -		} +	switch (getMusicType(hdl)) { +	case MT_PCSPK: +		if (flags & MDT_PCSPK) +			return hdl; +		break; + +	case MT_PCJR: +		if (flags & MDT_PCJR) +			return hdl; +		break; +	 +	case MT_CMS: +		if (flags & MDT_CMS) +			return hdl; +		break; + +	case MT_ADLIB: +		if (flags & MDT_ADLIB) +			return hdl; +		break; +		 +	case MT_TOWNS: +		if (flags & MDT_TOWNS) +			return hdl; +		break; + +	case MT_PC98: +		if (flags & MDT_PC98) +			return hdl; +		break; + +	case MT_GM: +	case MT_GS: +	case MT_MT32: +		if (flags & MDT_MIDI) +			return hdl; +		break; + +	case MT_NULL: +		return hdl; -		if (musicDriver == MD_AUTO) { -			// MIDI is not preferred, or no default MIDI device is available. -			// In this case we first try the alternate drivers before checking -			// for a 'real' MIDI driver. - -			if (flags & MDT_TOWNS) -				musicDriver = MD_TOWNS; -			else if (flags & MDT_ADLIB) -				musicDriver = MD_ADLIB; -			else if (flags & MDT_PCSPK) -				musicDriver = MD_PCJR; -			else if (flags & MDT_MIDI) -				musicDriver = getDefaultMIDIDriver(); +	default: +		break; +	} + +	// If the selected driver did not match the flags setting, +	// we try to determine a suitable and "optimal" music driver. +	const MusicPlugin::List p = MusicMan.getPlugins(); +	// If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be +	// detected since they are hard coded and cannot be disabled. +	for (int l = (flags & (MDT_PREFER_GM | MDT_PREFER_MT32)) ? 1 : 0; l < 2; ++l) { +		if ((flags & MDT_MIDI) && (l == 1)) { +			// If a preferred MT32 or GM device has been selected that device gets returned +			if (flags & MDT_PREFER_MT32) +				hdl = getDeviceHandle(ConfMan.get("mt32_device")); +			else if (flags & MDT_PREFER_GM) +				hdl = getDeviceHandle(ConfMan.get("gm_device"));  			else -				musicDriver = MD_NULL; +				hdl = getDeviceHandle("auto"); + +			const MusicType type = getMusicType(hdl); +			if (type != MT_AUTO && type != MT_INVALID) { +				if (flags & MDT_PREFER_MT32) +					// If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h) +					_forceTypeMT32 = true; + +				return hdl; +			} + +			// If we have no specific device selected (neither in the scummvm nor in the game domain) +			// and no preferred MT32 or GM device selected we arrive here. +			// If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator) +			if (flags & MDT_PREFER_MT32) { +				for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { +					MusicDevices i = (**m)->getDevices(); +					for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { +						if (d->getMusicType() == MT_MT32) +							return d->getHandle(); +					} +				} +			} + +			// Now we default to the first available device with music type 'MT_GM' +			for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { +				MusicDevices i = (**m)->getDevices(); +				for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { +					if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) +						return d->getHandle(); +				} +			} +		} + +		MusicType tp = MT_AUTO; +		if (flags & MDT_TOWNS) +			tp = MT_TOWNS; +		else if (flags & MDT_ADLIB) +			tp = MT_ADLIB; +		else if (flags & MDT_PCSPK) +			tp = MT_PCSPK; +		else if (l == 0) +			// if we haven't tried to find a MIDI device yet we do this now. +			continue; +		else +			tp = MT_AUTO; + +		for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { +			MusicDevices i = (**m)->getDevices(); +			for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { +				if (d->getMusicType() == tp) +					return d->getHandle(); +			}  		}  	} -	return musicDriver; +	return 0;  } -MidiDriver *MidiDriver::createMidi(MidiDriverType midiDriver) { -	switch (midiDriver) { -	case MD_NULL:      return MidiDriver_NULL_create(); - -	case MD_ADLIB:     return MidiDriver_ADLIB_create(); - -	case MD_TOWNS:     return MidiDriver_YM2612_create(); - -	// Right now PC Speaker and PCjr are handled -	// outside the MidiDriver architecture, so -	// don't create anything for now. -	case MD_PCSPK: -	case MD_CMS: -	case MD_PCJR:      return NULL; - -#ifdef USE_FLUIDSYNTH -	case MD_FLUIDSYNTH:	return MidiDriver_FluidSynth_create(); -#endif - -#ifdef USE_MT32EMU -	case MD_MT32:      return MidiDriver_MT32_create(); -#endif - -#if defined(PALMOS_MODE) -#if defined(COMPILE_CLIE) -	case MD_YPA1:      return MidiDriver_YamahaPa1_create(); -#elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM)) -	case MD_ZODIAC:    return MidiDriver_Zodiac_create(); -#endif -#endif - -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -	case MD_WINDOWS:   return MidiDriver_WIN_create(); -#endif -#if defined(__MINT__) -	case MD_STMIDI:    return MidiDriver_STMIDI_create(); -#endif -#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__) -	case MD_SEQ:       return MidiDriver_SEQ_create(); -#endif -#if defined(UNIX) -	case MD_TIMIDITY:  return MidiDriver_TIMIDITY_create(); -#endif -#if defined(IRIX) -	case MD_DMEDIA:    return MidiDriver_DMEDIA_create(); -#endif -#if defined(MACOSX) -	case MD_COREAUDIO: return MidiDriver_CORE_create(); -	case MD_COREMIDI:  return MidiDriver_CoreMIDI_create(); -#endif -#if defined(UNIX) && defined(USE_ALSA) -	case MD_ALSA:      return MidiDriver_ALSA_create(); -#endif -#if defined(__amigaos4__) -	case MD_CAMD:      return MidiDriver_CAMD_create(); -#endif -	default: -		error("Invalid midi driver selected"); +MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) { +	MidiDriver *driver = 0; +	const MusicPlugin::List p = MusicMan.getPlugins(); +	for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { +		if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) +			(**m)->createInstance(&driver, handle); +	} + +	return driver; +} + +MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &identifier) { +	const MusicPlugin::List p = MusicMan.getPlugins(); + +	if (p.begin() == p.end()) +		error("Music plugins must be loaded prior to calling this method."); + +	for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { +		MusicDevices i = (**m)->getDevices(); +		for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { +			if (identifier.equals(d->getCompleteId()) || identifier.equals(d->getCompleteName())) { +				return d->getHandle(); +			} +		}  	} -	return NULL; +	return 0;  } diff --git a/sound/mididrv.h b/sound/mididrv.h index d7e89dd9ca..5fffd430fb 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -30,6 +30,8 @@  #include "common/timer.h"  class MidiChannel; +class MusicDevice; +  namespace Audio {  	class Mixer;  } @@ -43,56 +45,32 @@ namespace Common { class String; }   *   * @todo Rename MidiDriverType to MusicDriverType   */ -enum MidiDriverType { -	// Pseudo drivers -	MD_AUTO, -	MD_NULL, - -	// Windows -	MD_WINDOWS, - -	// Atari ST -	MD_STMIDI, - -	// Linux -	MD_ALSA, -	MD_SEQ, - -	// Mac OS X -	MD_QTMUSIC, -	MD_COREAUDIO, -	MD_COREMIDI, - -	// PalmOS -	MD_YPA1, -	MD_ZODIAC, - -	// IRIX -	MD_DMEDIA, - -	// AMIGAOS4 -	MD_CAMD, - -	// MIDI softsynths -	MD_FLUIDSYNTH, -	MD_MT32, - -	// "Fake" MIDI devices -	MD_ADLIB, -	MD_PCSPK, -	MD_CMS, -	MD_PCJR, -	MD_TOWNS, -	MD_TIMIDITY + +/** + * Music types that music drivers can implement and engines can rely on. + */ +enum MusicType { +	MT_INVALID = -1,    // Invalid output +	MT_AUTO = 0,        // Auto +	MT_NULL,            // Null +	MT_PCSPK,           // PC Speaker +	MT_PCJR,            // PCjr +	MT_CMS,             // CMS +	MT_ADLIB,           // AdLib +	MT_TOWNS,           // FM-TOWNS +	MT_PC98,            // PC98 +	MT_GM,              // General MIDI +	MT_MT32,            // MT-32 +	MT_GS               // Roland GS  };  /** - * A set of flags to be passed to detectMusicDriver() which can be used to + * A set of flags to be passed to detectDevice() which can be used to   * specify what kind of music driver is preferred / accepted.   * - * The flags (except for MDT_PREFER_MIDI) indicate whether a given driver + * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver   * type is acceptable. E.g. the TOWNS music driver could be returned by - * detectMusicDriver if and only if MDT_TOWNS is specified. + * detectDevice if and only if MDT_TOWNS is specified.   *   * @todo Rename MidiDriverFlags to MusicDriverFlags   */ @@ -100,10 +78,13 @@ enum MidiDriverFlags {  	MDT_NONE   = 0,  	MDT_PCSPK  = 1 << 0,      // PC Speaker: Maps to MD_PCSPK and MD_PCJR  	MDT_CMS    = 1 << 1,      // Creative Music System / Gameblaster: Maps to MD_CMS -	MDT_ADLIB  = 1 << 2,      // AdLib: Maps to MD_ADLIB -	MDT_TOWNS  = 1 << 3,      // FM-TOWNS: Maps to MD_TOWNS -	MDT_MIDI   = 1 << 4,      // Real MIDI -	MDT_PREFER_MIDI = 1 << 5  // Real MIDI output is preferred +	MDT_PCJR   = 1 << 2,      // Tandy/PC Junior driver +	MDT_ADLIB  = 1 << 3,      // AdLib: Maps to MT_ADLIB +	MDT_TOWNS  = 1 << 4,      // FM-TOWNS: Maps to MT_TOWNS +	MDT_PC98   = 1 << 5,      // FM-TOWNS: Maps to MT_PC98 +	MDT_MIDI   = 1 << 6,      // Real MIDI +	MDT_PREFER_MT32 = 1 << 7, // MT-32 output is preferred +	MDT_PREFER_GM = 1 << 8    // GM output is preferred  };  /** @@ -113,12 +94,6 @@ enum MidiDriverFlags {   *   * @todo Rename MidiDriverType to MusicDriverType   */ -struct MidiDriverDescription { -	const char *name; -	const char *description; -	MidiDriverType id;		// A unique ID for each driver -	int flags;				// Capabilities of this driver -};  /**   * Abstract MIDI Driver Class @@ -127,22 +102,45 @@ struct MidiDriverDescription {   */  class MidiDriver {  public: -	/** Find the music driver matching the given driver name/description. */ -	static const MidiDriverDescription *findMusicDriver(const Common::String &str); - -	/** Get the id of the music driver matching the given driver name, or MD_AUTO if there is no match. */ -	static MidiDriverType parseMusicDriver(const Common::String &str); -  	/** -	 * Get a list of all available MidiDriver types. -	 * @return list of all available midi drivers, terminated by  a zero entry +	 * The device handle. +	 * +	 * The value 0 is reserved for an invalid device for now. +	 * TODO: Maybe we should use -1 (i.e. 0xFFFFFFFF) as +	 * invalid device?  	 */ -	static const MidiDriverDescription *getAvailableMidiDrivers(); +	typedef uint32 DeviceHandle; -	static MidiDriver *createMidi(MidiDriverType midiDriver); +	enum DeviceStringType { +		kDriverName, +		kDriverId, +		kDeviceId +	}; -	static MidiDriverType detectMusicDriver(int flags); +	static uint32 musicType2GUIO(uint32 musicType); +	/** Create music driver matching the given device handle, or NULL if there is no match. */ +	static MidiDriver *createMidi(DeviceHandle handle); + +	/** Returns device handle based on the present devices and the flags parameter. */ +	static DeviceHandle detectDevice(int flags); +		 +	/** Find the music driver matching the given driver name/description. */ +	static DeviceHandle getDeviceHandle(const Common::String &identifier); + +	/** Get the music type matching the given device handle, or MT_AUTO if there is no match. */ +	static MusicType getMusicType(DeviceHandle handle); + +	/** Get the device description string matching the given device handle and the given type. */ +	static Common::String getDeviceString(DeviceHandle handle, DeviceStringType type); + +private: +	// If detectDevice() detects MT32 and we have a preferred MT32 device +	// we use this to force getMusicType() to return MT_MT32 so that we don't +	// have to rely on the 'True Roland MT-32' config manager setting (since nobody +	// would possibly think about activating 'True Roland MT-32' when he has set +	// 'Music Driver' to '<default>') +	static bool _forceTypeMT32;  public:  	virtual ~MidiDriver() { } @@ -271,28 +269,4 @@ public:  	virtual void sysEx_customInstrument(uint32 type, const byte *instr) = 0;  }; - -// Factory functions, for faster compile -extern MidiDriver *MidiDriver_NULL_create(); -extern MidiDriver *MidiDriver_ADLIB_create(); -extern MidiDriver *MidiDriver_WIN_create(); -extern MidiDriver *MidiDriver_STMIDI_create(); -extern MidiDriver *MidiDriver_SEQ_create(); -extern MidiDriver *MidiDriver_TIMIDITY_create(); -extern MidiDriver *MidiDriver_QT_create(); -extern MidiDriver *MidiDriver_CORE_create(); -extern MidiDriver *MidiDriver_CoreMIDI_create(); -extern MidiDriver *MidiDriver_ALSA_create(); -extern MidiDriver *MidiDriver_DMEDIA_create(); -extern MidiDriver *MidiDriver_CAMD_create(); -extern MidiDriver *MidiDriver_YM2612_create(); -#ifdef USE_FLUIDSYNTH -extern MidiDriver *MidiDriver_FluidSynth_create(); -#endif -#ifdef USE_MT32EMU -extern MidiDriver *MidiDriver_MT32_create(); -#endif -extern MidiDriver *MidiDriver_YamahaPa1_create(); -extern MidiDriver *MidiDriver_Zodiac_create(); -  #endif diff --git a/sound/midiparser.cpp b/sound/midiparser.cpp index 8ae2bad71a..d58471765e 100644 --- a/sound/midiparser.cpp +++ b/sound/midiparser.cpp @@ -67,6 +67,10 @@ void MidiParser::property(int prop, int value) {  	}  } +void MidiParser::sendToDriver(uint32 b) { +	_driver->send(b); +} +  void MidiParser::setTempo(uint32 tempo) {  	_tempo = tempo;  	if (_ppqn) @@ -127,7 +131,7 @@ void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool rec  			best = ptr;  			if (ptr->time_left) {  				if (recycle) -					_driver->send(0x80 | channel, note, 0); +					sendToDriver(0x80 | channel, note, 0);  				--_hanging_notes_count;  			}  			break; @@ -172,7 +176,7 @@ void MidiParser::onTimer() {  		for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {  			if (ptr->time_left) {  				if (ptr->time_left <= _timer_rate) { -					_driver->send(0x80 | ptr->channel, ptr->note, 0); +					sendToDriver(0x80 | ptr->channel, ptr->note, 0);  					ptr->time_left = 0;  					--_hanging_notes_count;  				} else { @@ -232,7 +236,7 @@ void MidiParser::onTimer() {  				else  					activeNote(info.channel(), info.basic.param1, true);  			} -			_driver->send(info.event, info.basic.param1, info.basic.param2); +			sendToDriver(info.event, info.basic.param1, info.basic.param2);  		} @@ -258,7 +262,7 @@ void MidiParser::allNotesOff() {  	for (i = 0; i < 128; ++i) {  		for (j = 0; j < 16; ++j) {  			if (_active_notes[i] & (1 << j)) { -				_driver->send(0x80 | j, i, 0); +				sendToDriver(0x80 | j, i, 0);  			}  		}  	} @@ -266,7 +270,7 @@ void MidiParser::allNotesOff() {  	// Turn off all hanging notes  	for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {  		if (_hanging_notes[i].time_left) { -			_driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); +			sendToDriver(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);  			_hanging_notes[i].time_left = 0;  		}  	} @@ -276,7 +280,7 @@ void MidiParser::allNotesOff() {  	// support this...).  	for (i = 0; i < 16; ++i) { -		_driver->send(0xB0 | i, 0x7b, 0); // All notes off +		sendToDriver(0xB0 | i, 0x7b, 0); // All notes off  	}  	memset(_active_notes, 0, sizeof(_active_notes)); @@ -348,7 +352,7 @@ void MidiParser::hangAllActiveNotes() {  				for (j = 0; j < 16; ++j) {  					if (temp_active[i] & (1 << j)) {  						activeNote(j, i, false); -						_driver->send(0x80 | j, i, 0); +						sendToDriver(0x80 | j, i, 0);  					}  				}  			} @@ -399,7 +403,7 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes) {  					else  						_driver->sysEx(info.ext.data, (uint16)info.length);  				} else -					_driver->send(info.event, info.basic.param1, info.basic.param2); +					sendToDriver(info.event, info.basic.param1, info.basic.param2);  			}  			parseNextEvent(_next_event); @@ -441,7 +445,7 @@ void MidiParser::unloadMusic() {  		if (_driver) {  			for (int i = 0; i < 16; ++i) { -				_driver->send(0xE0 | i, 0, 0x40); +				sendToDriver(0xE0 | i, 0, 0x40);  			}  		}  	} diff --git a/sound/midiparser.h b/sound/midiparser.h index 0ba12ce2b1..3ef99fcd6e 100644 --- a/sound/midiparser.h +++ b/sound/midiparser.h @@ -267,13 +267,12 @@ struct NoteTimer {   * memory block containing the music data.)   */  class MidiParser { -private: +protected:  	uint16    _active_notes[128];   ///< Each uint16 is a bit mask for channels that have that note on.  	NoteTimer _hanging_notes[32];   ///< Maintains expiration info for up to 32 notes.  	                                ///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.  	byte      _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration. -protected:  	MidiDriver *_driver;    ///< The device to which all events will be transmitted.  	uint32 _timer_rate;     ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.  	uint32 _ppqn;           ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".) @@ -303,6 +302,11 @@ protected:  	void hangingNote(byte channel, byte note, uint32 ticks_left, bool recycle = true);  	void hangAllActiveNotes(); +	virtual void sendToDriver(uint32 b); +	void sendToDriver(byte status, byte firstOp, byte secondOp) { +		sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); +	} +  	/**  	 * Platform independent BE uint32 read-and-advance.  	 * This helper function reads Big Endian 32-bit numbers diff --git a/sound/mods/protracker.h b/sound/mods/protracker.h index dfcb0e6c51..af722637c7 100644 --- a/sound/mods/protracker.h +++ b/sound/mods/protracker.h @@ -48,7 +48,7 @@ class AudioStream;   * @param stream	the ReadStream from which to read the ProTracker data   * @param rate		TODO   * @param stereo	TODO - * @return	a new AudioStream, or NULL, if an error occured + * @return	a new AudioStream, or NULL, if an error occurred   */  AudioStream *makeProtrackerStream(Common::SeekableReadStream *stream, int offs = 0, int rate = 44100, bool stereo = true); diff --git a/sound/musicplugin.cpp b/sound/musicplugin.cpp index b4754230da..8078094616 100644 --- a/sound/musicplugin.cpp +++ b/sound/musicplugin.cpp @@ -24,10 +24,12 @@   */  #include "sound/musicplugin.h" +#include "common/hash-str.h" +#include "common/translation.h"  MusicDevice::MusicDevice(MusicPluginObject const *musicPlugin, Common::String name, MusicType mt) : -	_musicDriverName(musicPlugin->getName()), _musicDriverId(musicPlugin->getId()), -	_name(name), _type(mt) { +	_musicDriverName(_(musicPlugin->getName())), _musicDriverId(musicPlugin->getId()), +	_name(_(name)), _type(mt) {  }  Common::String MusicDevice::getCompleteName() { @@ -46,3 +48,17 @@ Common::String MusicDevice::getCompleteName() {  	return name;  } + +Common::String MusicDevice::getCompleteId() { +	Common::String id = _musicDriverId; +	if (!_name.empty()) { +		id += "_"; +		id += _name; +	} + +	return id; +} + +MidiDriver::DeviceHandle MusicDevice::getHandle() { +	return (MidiDriver::DeviceHandle)Common::hashit(getCompleteId().c_str()); +} diff --git a/sound/musicplugin.h b/sound/musicplugin.h index df97494a90..3823f2fd3d 100644 --- a/sound/musicplugin.h +++ b/sound/musicplugin.h @@ -29,19 +29,6 @@  #include "sound/mididrv.h"  #include "common/list.h" -/** - * Music types that music drivers can implement and engines can rely on. - */ -enum MusicType { -	MT_PCSPK = 1,  // PC Speaker -	MT_PCJR  = 2,  // PCjr -	MT_ADLIB = 3,  // AdLib -	MT_TOWNS = 4,  // FM-TOWNS -	MT_GM    = 5,  // General MIDI -	MT_MT32  = 6,  // MT-32 -	MT_GS    = 7   // Roland GS -}; -  class MusicPluginObject;  /** @@ -63,6 +50,14 @@ public:  	 * device name (if it isn't the default one) and the name of the driver.  	 */  	Common::String getCompleteName(); +	 +	/** +	 * Returns a user readable string that contains the name of the current +	 * device name (if it isn't the default one) and the id of the driver. +	 */ +	Common::String getCompleteId(); + +	MidiDriver::DeviceHandle getHandle();  private:  	Common::String _name; @@ -94,15 +89,18 @@ public:  	virtual MusicDevices getDevices() const = 0;  	/** -	 * Tries to instantiate a MIDI Driver instance based on the settings of -	 * the currently active ConfMan target. That is, the MusicPluginObject -	 * should query the ConfMan singleton for the device name, port, etc. +	 * Tries to instantiate a MIDI Driver instance based on the device +	 * previously detected via MidiDriver::detectDevice()  	 *  	 * @param mididriver	Pointer to a pointer which the MusicPluginObject sets  	 *				to the newly create MidiDriver, or 0 in case of an error +	 * +	* @param dev	Pointer to a device to be used then creating the driver instance. +	 *				Default value of zero for driver types without devices. +	 *  	 * @return		a Common::Error describing the error which occurred, or kNoError  	 */ -	virtual Common::Error createInstance(MidiDriver **mididriver) const = 0; +	virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0;  }; diff --git a/sound/null.cpp b/sound/null.cpp index 00a5f5e488..556b96c14c 100644 --- a/sound/null.cpp +++ b/sound/null.cpp @@ -22,63 +22,41 @@   * $Id$   */ -#include "sound/musicplugin.h" -#include "sound/mpu401.h" +#include "sound/null.h" -/* NULL driver */ -class MidiDriver_NULL : public MidiDriver_MPU401 { -public: -	int open() { return 0; } -	void send(uint32 b) { } -}; +Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { +	*mididriver = new MidiDriver_NULL(); +	return Common::kNoError; +} -// Plugin interface +MusicDevices NullMusicPlugin::getDevices() const { +	MusicDevices devices; +	devices.push_back(MusicDevice(this, "", MT_NULL)); +	return devices; +} -class NullMusicPlugin : public MusicPluginObject { +class AutoMusicPlugin : public NullMusicPlugin {  public:  	const char *getName() const { -		return "No music"; +		return _s("<default>");  	}  	const char *getId() const { -		return "null"; +		return "auto";  	} -  	MusicDevices getDevices() const; -	Common::Error createInstance(MidiDriver **mididriver) const;  }; -Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver) const { -	*mididriver = new MidiDriver_NULL(); - -	return Common::kNoError; -} - -MusicDevices NullMusicPlugin::getDevices() const { +MusicDevices AutoMusicPlugin::getDevices() const {  	MusicDevices devices; -	// TODO: return a different music type? -	devices.push_back(MusicDevice(this, "", MT_GM)); +	devices.push_back(MusicDevice(this, "", MT_AUTO));  	return devices;  } -MidiDriver *MidiDriver_NULL_create() { -	MidiDriver *mididriver; - -	NullMusicPlugin p; -	p.createInstance(&mididriver); - -	return mididriver; -} - -#ifdef DISABLE_ADLIB -MidiDriver *MidiDriver_ADLIB_create() { -	return MidiDriver_NULL_create(); -} -#endif -  //#if PLUGIN_ENABLED_DYNAMIC(NULL)  	//REGISTER_PLUGIN_DYNAMIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);  //#else +	REGISTER_PLUGIN_STATIC(AUTO, PLUGIN_TYPE_MUSIC, AutoMusicPlugin);  	REGISTER_PLUGIN_STATIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);  //#endif diff --git a/sound/null.h b/sound/null.h new file mode 100644 index 0000000000..d9343701fa --- /dev/null +++ b/sound/null.h @@ -0,0 +1,56 @@ +/* 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. + * + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef SOUND_NULL_H +#define SOUND_NULL_H + +#include "sound/musicplugin.h" +#include "sound/mpu401.h" +#include "common/translation.h" + +/* NULL driver */ +class MidiDriver_NULL : public MidiDriver_MPU401 { +public: +	int open() { return 0; } +	void send(uint32 b) { } +}; + + +// Plugin interface + +class NullMusicPlugin : public MusicPluginObject { +public: +	virtual const char *getName() const { +		return _s("No music"); +	} + +	virtual const char *getId() const { +		return "null"; +	} + +	virtual MusicDevices getDevices() const; +	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; +}; + +#endif diff --git a/sound/softsynth/adlib.cpp b/sound/softsynth/adlib.cpp index 6697cef646..ffb359e816 100644 --- a/sound/softsynth/adlib.cpp +++ b/sound/softsynth/adlib.cpp @@ -27,6 +27,7 @@  #include "common/util.h"  #include "sound/fmopl.h"  #include "sound/musicplugin.h" +#include "common/translation.h"  #ifdef DEBUG_ADLIB  static int tick; @@ -1586,7 +1587,7 @@ void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {  class AdLibEmuMusicPlugin : public MusicPluginObject {  public:  	const char *getName() const { -		return "AdLib Emulator"; +		return _s("AdLib Emulator");  	}  	const char *getId() const { @@ -1594,7 +1595,7 @@ public:  	}  	MusicDevices getDevices() const; -	Common::Error createInstance(MidiDriver **mididriver) const; +	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;  };  MusicDevices AdLibEmuMusicPlugin::getDevices() const { @@ -1603,21 +1604,12 @@ MusicDevices AdLibEmuMusicPlugin::getDevices() const {  	return devices;  } -Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {  	*mididriver = new MidiDriver_ADLIB(g_system->getMixer());  	return Common::kNoError;  } -MidiDriver *MidiDriver_ADLIB_create() { -	MidiDriver *mididriver; - -	AdLibEmuMusicPlugin p; -	p.createInstance(&mididriver); - -	return mididriver; -} -  //#if PLUGIN_ENABLED_DYNAMIC(ADLIB)  	//REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);  //#else diff --git a/sound/softsynth/fluidsynth.cpp b/sound/softsynth/fluidsynth.cpp index c3bd782cc1..fcb4591a20 100644 --- a/sound/softsynth/fluidsynth.cpp +++ b/sound/softsynth/fluidsynth.cpp @@ -230,7 +230,7 @@ public:  	}  	MusicDevices getDevices() const; -	Common::Error createInstance(MidiDriver **mididriver) const; +	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;  };  MusicDevices FluidSynthMusicPlugin::getDevices() const { @@ -239,21 +239,12 @@ MusicDevices FluidSynthMusicPlugin::getDevices() const {  	return devices;  } -Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {  	*mididriver = new MidiDriver_FluidSynth(g_system->getMixer());  	return Common::kNoError;  } -MidiDriver *MidiDriver_FluidSynth_create() { -	MidiDriver *mididriver; - -	FluidSynthMusicPlugin p; -	p.createInstance(&mididriver); - -	return mididriver; -} -  //#if PLUGIN_ENABLED_DYNAMIC(FLUIDSYNTH)  	//REGISTER_PLUGIN_DYNAMIC(FLUIDSYNTH, PLUGIN_TYPE_MUSIC, FluidSynthMusicPlugin);  //#else diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp index 612dce06b0..95263a040d 100644 --- a/sound/softsynth/mt32.cpp +++ b/sound/softsynth/mt32.cpp @@ -39,6 +39,7 @@  #include "common/system.h"  #include "common/util.h"  #include "common/archive.h" +#include "common/translation.h"  #include "graphics/fontman.h"  #include "graphics/surface.h" @@ -323,7 +324,7 @@ int MidiDriver_MT32::open() {  	}  	_initialising = true; -	drawMessage(-1, "Initialising MT-32 Emulator"); +	drawMessage(-1, _s("Initialising MT-32 Emulator"));  	if (!_synth->open(prop))  		return MERR_DEVICE_NOT_AVAILABLE;  	_initialising = false; @@ -537,7 +538,7 @@ void MidiDriver_ThreadedMT32::onTimer() {  class MT32EmuMusicPlugin : public MusicPluginObject {  public:  	const char *getName() const { -		return "MT-32 Emulator"; +		return _s("MT-32 Emulator");  	}  	const char *getId() const { @@ -545,7 +546,7 @@ public:  	}  	MusicDevices getDevices() const; -	Common::Error createInstance(MidiDriver **mididriver) const; +	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;  };  MusicDevices MT32EmuMusicPlugin::getDevices() const { @@ -554,23 +555,13 @@ MusicDevices MT32EmuMusicPlugin::getDevices() const {  	return devices;  } -Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver) const { -	*mididriver = new MidiDriver_MT32(g_system->getMixer()); - -	return Common::kNoError; -} - -MidiDriver *MidiDriver_MT32_create() { -	// HACK: It will stay here until engine plugin loader overhaul +Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {  	if (ConfMan.hasKey("extrapath"))  		SearchMan.addDirectory("extrapath", ConfMan.get("extrapath")); -	MidiDriver *mididriver; - -	MT32EmuMusicPlugin p; -	p.createInstance(&mididriver); +	*mididriver = new MidiDriver_MT32(g_system->getMixer()); -	return mididriver; +	return Common::kNoError;  }  //#if PLUGIN_ENABLED_DYNAMIC(MT32) diff --git a/sound/softsynth/pcspk.cpp b/sound/softsynth/pcspk.cpp index 396d9328f1..bdf9f112e8 100644 --- a/sound/softsynth/pcspk.cpp +++ b/sound/softsynth/pcspk.cpp @@ -24,6 +24,7 @@  */  #include "sound/softsynth/pcspk.h" +#include "sound/null.h"  namespace Audio { @@ -128,3 +129,59 @@ int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) {  }  } // End of namespace Audio + + +//	Plugin interface +//	(This can only create a null driver since pc speaker support is not part of the +//	midi driver architecture. But we need the plugin for the options menu in the launcher +//	and for MidiDriver::detectDevice() which is more or less used by all engines.) + +class PCSpeakerMusicPlugin : public NullMusicPlugin { +public: +	const char *getName() const { +		return _s("PC Speaker Emulator"); +	} + +	const char *getId() const { +		return "pcspk"; +	} + +	MusicDevices getDevices() const; +}; + +MusicDevices PCSpeakerMusicPlugin::getDevices() const { +	MusicDevices devices; +	devices.push_back(MusicDevice(this, "", MT_PCSPK)); +	return devices; +} + +class PCjrMusicPlugin : public NullMusicPlugin { +public: +	const char *getName() const { +		return _s("IBM PCjr Emulator"); +	} + +	const char *getId() const { +		return "pcjr"; +	} + +	MusicDevices getDevices() const; +}; + +MusicDevices PCjrMusicPlugin::getDevices() const { +	MusicDevices devices; +	devices.push_back(MusicDevice(this, "", MT_PCJR)); +	return devices; +} + +//#if PLUGIN_ENABLED_DYNAMIC(PCSPK) +	//REGISTER_PLUGIN_DYNAMIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin); +//#else +	REGISTER_PLUGIN_STATIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin); +//#endif + +//#if PLUGIN_ENABLED_DYNAMIC(PCJR) +	//REGISTER_PLUGIN_DYNAMIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin); +//#else +	REGISTER_PLUGIN_STATIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin); +//#endif diff --git a/sound/softsynth/sid.cpp b/sound/softsynth/sid.cpp index e0dfd2efc0..d600ac28f5 100644 --- a/sound/softsynth/sid.cpp +++ b/sound/softsynth/sid.cpp @@ -506,7 +506,7 @@ Filter::Filter() {  		+ sizeof(f0_points_6581)/sizeof(*f0_points_6581) - 1,  		PointPlotter<sound_sample>(f0_6581), 1.0); -	mixer_DC = -0xfff*0xff/18 >> 7; +	mixer_DC = (-0xfff*0xff/18) >> 7;  	f0 = f0_6581;  	f0_points = f0_points_6581; diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp index e337bc4ab9..08331c6244 100644 --- a/sound/softsynth/ym2612.cpp +++ b/sound/softsynth/ym2612.cpp @@ -27,6 +27,7 @@  #include "sound/softsynth/ym2612.h"  #include "common/util.h"  #include "sound/musicplugin.h" +#include "common/translation.h"  ////////////////////////////////////////  // @@ -758,7 +759,7 @@ void MidiDriver_YM2612::removeLookupTables() {  class TownsEmuMusicPlugin : public MusicPluginObject {  public:  	const char *getName() const { -		return "FM Towns Emulator"; +		return _s("FM Towns Emulator");  	}  	const char *getId() const { @@ -766,7 +767,7 @@ public:  	}  	MusicDevices getDevices() const; -	Common::Error createInstance(MidiDriver **mididriver) const; +	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;  };  MusicDevices TownsEmuMusicPlugin::getDevices() const { @@ -775,21 +776,12 @@ MusicDevices TownsEmuMusicPlugin::getDevices() const {  	return devices;  } -Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {  	*mididriver = new MidiDriver_YM2612(g_system->getMixer());  	return Common::kNoError;  } -MidiDriver *MidiDriver_YM2612_create() { -	MidiDriver *mididriver; - -	TownsEmuMusicPlugin p; -	p.createInstance(&mididriver); - -	return mididriver; -} -  //#if PLUGIN_ENABLED_DYNAMIC(TOWNS)  	//REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);  //#else  | 
