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 |