aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorAlejandro Marzini2010-07-13 04:31:15 +0000
committerAlejandro Marzini2010-07-13 04:31:15 +0000
commit609e08d5dbae3179eddf981abe73d69009432de4 (patch)
treecddbd0a0e69eaa53b85f98f96dc410a307773f08 /sound
parent8b6a670391f1b5103e3761d78eef8f41d64cf8cd (diff)
parent03c0faa5d76f547603ee6389cdf958e2a6f0f43d (diff)
downloadscummvm-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.cpp6
-rw-r--r--sound/audiostream.h48
-rw-r--r--sound/decoders/adpcm.h2
-rw-r--r--sound/decoders/aiff.cpp11
-rw-r--r--sound/decoders/aiff.h9
-rw-r--r--sound/decoders/flac.cpp6
-rw-r--r--sound/decoders/flac.h4
-rw-r--r--sound/decoders/mp3.h4
-rw-r--r--sound/decoders/vag.h2
-rw-r--r--sound/decoders/voc.h2
-rw-r--r--sound/decoders/vorbis.cpp2
-rw-r--r--sound/decoders/vorbis.h4
-rw-r--r--sound/decoders/wave.h4
-rw-r--r--sound/fmopl.cpp5
-rw-r--r--sound/mididrv.cpp402
-rw-r--r--sound/mididrv.h152
-rw-r--r--sound/midiparser.cpp22
-rw-r--r--sound/midiparser.h8
-rw-r--r--sound/mods/protracker.h2
-rw-r--r--sound/musicplugin.cpp20
-rw-r--r--sound/musicplugin.h32
-rw-r--r--sound/null.cpp54
-rw-r--r--sound/null.h56
-rw-r--r--sound/softsynth/adlib.cpp16
-rw-r--r--sound/softsynth/fluidsynth.cpp13
-rw-r--r--sound/softsynth/mt32.cpp23
-rw-r--r--sound/softsynth/pcspk.cpp57
-rw-r--r--sound/softsynth/sid.cpp2
-rw-r--r--sound/softsynth/ym2612.cpp16
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