aboutsummaryrefslogtreecommitdiff
path: root/audio/mididrv.h
diff options
context:
space:
mode:
Diffstat (limited to 'audio/mididrv.h')
-rw-r--r--audio/mididrv.h288
1 files changed, 288 insertions, 0 deletions
diff --git a/audio/mididrv.h b/audio/mididrv.h
new file mode 100644
index 0000000000..9e649cba3d
--- /dev/null
+++ b/audio/mididrv.h
@@ -0,0 +1,288 @@
+/* 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_MIDIDRV_H
+#define SOUND_MIDIDRV_H
+
+#include "common/scummsys.h"
+#include "common/timer.h"
+
+class MidiChannel;
+class MusicDevice;
+
+namespace Audio {
+ class Mixer;
+}
+namespace Common { class String; }
+
+/**
+ * Music Driver Types, used to uniquely identify each music driver.
+ *
+ * The pseudo drivers are listed first, then all native drivers,
+ * then all other MIDI drivers, and finally the non-MIDI drivers.
+ *
+ * @todo Rename MidiDriverType to MusicDriverType
+ */
+
+/**
+ * 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_C64, // C64
+ MT_AMIGA, // Amiga
+ MT_APPLEIIGS, // Apple IIGS
+ 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 detectDevice() which can be used to
+ * specify what kind of music driver is preferred / accepted.
+ *
+ * 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
+ * detectDevice if and only if MDT_TOWNS is specified.
+ *
+ * @todo Rename MidiDriverFlags to MusicDriverFlags
+ */
+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_PCJR = 1 << 2, // Tandy/PC Junior driver
+ MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB
+ MDT_C64 = 1 << 4,
+ MDT_AMIGA = 1 << 5,
+ MDT_APPLEIIGS = 1 << 6,
+ MDT_TOWNS = 1 << 7, // FM-TOWNS: Maps to MT_TOWNS
+ MDT_PC98 = 1 << 8, // FM-TOWNS: Maps to MT_PC98
+ MDT_MIDI = 1 << 9, // Real MIDI
+ MDT_PREFER_MT32 = 1 << 10, // MT-32 output is preferred
+ MDT_PREFER_GM = 1 << 11 // GM output is preferred
+};
+
+/**
+ * Abstract description of a MIDI driver. Used by the config file and command
+ * line parsing code, and also to be able to give the user a list of available
+ * drivers.
+ *
+ * @todo Rename MidiDriverType to MusicDriverType
+ */
+
+/**
+ * Abstract MIDI Driver Class
+ *
+ * @todo Rename MidiDriver to MusicDriver
+ */
+class MidiDriver {
+public:
+ /**
+ * 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?
+ */
+ typedef uint32 DeviceHandle;
+
+ enum DeviceStringType {
+ kDriverName,
+ kDriverId,
+ kDeviceId
+ };
+
+ 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() { }
+
+ static const byte _mt32ToGm[128];
+ static const byte _gmToMt32[128];
+
+ /**
+ * Error codes returned by open.
+ * Can be converted to a string with getErrorName().
+ */
+ enum {
+ MERR_CANNOT_CONNECT = 1,
+// MERR_STREAMING_NOT_AVAILABLE = 2,
+ MERR_DEVICE_NOT_AVAILABLE = 3,
+ MERR_ALREADY_OPEN = 4
+ };
+
+ enum {
+// PROP_TIMEDIV = 1,
+ PROP_OLD_ADLIB = 2,
+ PROP_CHANNEL_MASK = 3
+ };
+
+ /**
+ * Open the midi driver.
+ * @return 0 if successful, otherwise an error code.
+ */
+ virtual int open() = 0;
+
+ /** Close the midi driver. */
+ virtual void close() = 0;
+
+ /**
+ * Output a packed midi command to the midi stream.
+ * The 'lowest' byte (i.e. b & 0xFF) is the status
+ * code, then come (if used) the first and second
+ * opcode.
+ */
+ virtual void send(uint32 b) = 0;
+
+ /**
+ * Output a midi command to the midi stream. Convenience wrapper
+ * around the usual 'packed' send method.
+ *
+ * Do NOT use this for sysEx transmission; instead, use the sysEx()
+ * method below.
+ */
+ void send(byte status, byte firstOp, byte secondOp) {
+ send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+ }
+
+ /** Get or set a property. */
+ virtual uint32 property(int prop, uint32 param) { return 0; }
+
+ /** Retrieve a string representation of an error code. */
+ static const char *getErrorName(int error_code);
+
+ // HIGH-LEVEL SEMANTIC METHODS
+ virtual void setPitchBendRange(byte channel, uint range) {
+ send(0xB0 | channel, 101, 0);
+ send(0xB0 | channel, 100, 0);
+ send(0xB0 | channel, 6, range);
+ send(0xB0 | channel, 38, 0);
+ send(0xB0 | channel, 101, 127);
+ send(0xB0 | channel, 100, 127);
+ }
+
+ /**
+ * Send a Roland MT-32 reset sysEx to the midi device.
+ */
+ void sendMT32Reset();
+
+ /**
+ * Send a General MIDI reset sysEx to the midi device.
+ */
+ void sendGMReset();
+
+ /**
+ * Transmit a sysEx to the midi device.
+ *
+ * The given msg MUST NOT contain the usual SysEx frame, i.e.
+ * do NOT include the leading 0xF0 and the trailing 0xF7.
+ *
+ * Furthermore, the maximal supported length of a SysEx
+ * is 264 bytes. Passing longer buffers can lead to
+ * undefined behavior (most likely, a crash).
+ */
+ virtual void sysEx(const byte *msg, uint16 length) { }
+
+ virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
+
+ virtual void metaEvent(byte type, byte *data, uint16 length) { }
+
+ // Timing functions - MidiDriver now operates timers
+ virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;
+
+ /** The time in microseconds between invocations of the timer callback. */
+ virtual uint32 getBaseTempo() = 0;
+
+ // Channel allocation functions
+ virtual MidiChannel *allocateChannel() = 0;
+ virtual MidiChannel *getPercussionChannel() = 0;
+};
+
+class MidiChannel {
+public:
+ virtual ~MidiChannel() {}
+
+ virtual MidiDriver *device() = 0;
+ virtual byte getNumber() = 0;
+ virtual void release() = 0;
+
+ virtual void send(uint32 b) = 0; // 4-bit channel portion is ignored
+
+ // Regular messages
+ virtual void noteOff(byte note) = 0;
+ virtual void noteOn(byte note, byte velocity) = 0;
+ virtual void programChange(byte program) = 0;
+ virtual void pitchBend(int16 bend) = 0; // -0x2000 to +0x1FFF
+
+ // Control Change messages
+ virtual void controlChange(byte control, byte value) = 0;
+ virtual void modulationWheel(byte value) { controlChange(1, value); }
+ virtual void volume(byte value) { controlChange(7, value); }
+ virtual void panPosition(byte value) { controlChange(10, value); }
+ virtual void pitchBendFactor(byte value) = 0;
+ virtual void detune(byte value) { controlChange(17, value); }
+ virtual void priority(byte value) { }
+ virtual void sustain(bool value) { controlChange(64, value ? 1 : 0); }
+ virtual void effectLevel(byte value) { controlChange(91, value); }
+ virtual void chorusLevel(byte value) { controlChange(93, value); }
+ virtual void allNotesOff() { controlChange(123, 0); }
+
+ // SysEx messages
+ virtual void sysEx_customInstrument(uint32 type, const byte *instr) = 0;
+};
+
+#endif