aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorJamieson Christian2002-11-21 19:06:42 +0000
committerJamieson Christian2002-11-21 19:06:42 +0000
commitc9ed09e7df28be6517f3cce26298124a0102a10c (patch)
tree2bfd354f2cbb1fa07cec34101d61cf3693edd9d1 /sound
parentd7e443cd7c8c91b0e19f85abb94a63301bc17a2b (diff)
downloadscummvm-rg350-c9ed09e7df28be6517f3cce26298124a0102a10c.tar.gz
scummvm-rg350-c9ed09e7df28be6517f3cce26298124a0102a10c.tar.bz2
scummvm-rg350-c9ed09e7df28be6517f3cce26298124a0102a10c.zip
Revamped Adlib functionality.
IMuseAdlib is defunct. New MidiDriver_ADLIB device. Simon 1/2 now supports Adlib. svn-id: r5677
Diffstat (limited to 'sound')
-rw-r--r--sound/mididrv.cpp75
-rw-r--r--sound/mididrv.h8
-rw-r--r--sound/midistreamer.cpp34
3 files changed, 101 insertions, 16 deletions
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index 9b9b8fe416..baf3427cfb 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -35,6 +35,67 @@
#include "common/engine.h" // for warning/error/debug
#include "common/util.h"
+
+
+////////////////////////////////////////
+//
+// Common MPU401 implementation methods
+//
+////////////////////////////////////////
+
+typedef void TimerCallback (void *);
+
+class MidiDriver_MPU401 : public MidiDriver {
+private:
+ bool _started_thread;
+ TimerCallback *_timer_proc;
+ void *_timer_param;
+
+ static int midi_driver_thread (void *param);
+
+public:
+ virtual void setTimerCallback (void *timer_param, void (*timer_proc) (void *));
+ virtual uint32 getBaseTempo (void) { return 0x4A0000; }
+};
+
+void MidiDriver_MPU401::setTimerCallback (void *timer_param, void (*timer_proc) (void *))
+{
+ if (!_timer_proc || !timer_proc) {
+ _timer_proc = (TimerCallback *) timer_proc;
+ _timer_param = timer_param;
+ if (!_started_thread && timer_proc)
+ g_system->create_thread (midi_driver_thread, this);
+ _started_thread = true;
+ }
+}
+
+int MidiDriver_MPU401::midi_driver_thread(void *param)
+{
+ MidiDriver_MPU401 *mid = (MidiDriver_MPU401 *)param;
+ int old_time, cur_time;
+
+ old_time = g_system->get_msecs();
+
+ for (;;) {
+ g_system->delay_msecs(10);
+
+ cur_time = g_system->get_msecs();
+ while (old_time < cur_time) {
+ old_time += 10;
+ // Don't use mid->_se_on_timer()
+ // We must come in through IMuseMonitor to protect
+ // against conflicts with script access to IMuse.
+ if (mid->_timer_proc)
+ (*(mid->_timer_proc)) (mid->_timer_param);
+ }
+ }
+
+ return 0;
+}
+
+
+
+
// FIXME - the following disables reverb support in the QuickTime / CoreAudio
// midi backends. For some reasons, reverb will suck away a *lot* of CPU time.
// Until we know for sure what is causing this and if there is a better way to
@@ -44,7 +105,7 @@
#if defined(WIN32) && !defined(_WIN32_WCE)
/* Windows MIDI driver */
-class MidiDriver_WIN : public MidiDriver {
+class MidiDriver_WIN : public MidiDriver_MPU401 {
public:
int open(int mode);
void close();
@@ -304,7 +365,7 @@ MidiDriver *MidiDriver_WIN_create()
#include "morphos_sound.h"
/* MorphOS MIDI driver */
-class MidiDriver_ETUDE:public MidiDriver {
+class MidiDriver_ETUDE:public MidiDriver_MPU401 {
public:
int open(int mode);
void close();
@@ -515,7 +576,7 @@ MidiDriver *MidiDriver_ETUDE_create()
#define SEQ_MIDIPUTC 5
#define SPECIAL_CHANNEL 9
-class MidiDriver_SEQ:public MidiDriver {
+class MidiDriver_SEQ:public MidiDriver_MPU401 {
public:
MidiDriver_SEQ();
int open(int mode);
@@ -655,7 +716,7 @@ MidiDriver *MidiDriver_SEQ_create()
/* QuickTime MIDI driver */
-class MidiDriver_QT:public MidiDriver {
+class MidiDriver_QT:public MidiDriver_MPU401 {
public:
int open(int mode);
void close();
@@ -872,7 +933,7 @@ MidiDriver *MidiDriver_QT_create()
/* CoreAudio MIDI driver */
/* Based on code by Benjamin W. Zale */
-class MidiDriver_CORE:public MidiDriver {
+class MidiDriver_CORE:public MidiDriver_MPU401 {
public:
MidiDriver_CORE():au_MusicDevice(NULL), au_output(NULL) {
} int open(int mode);
@@ -979,7 +1040,7 @@ MidiDriver *MidiDriver_CORE_create()
#endif // __APPLE__
/* NULL driver */
-class MidiDriver_NULL:public MidiDriver {
+class MidiDriver_NULL:public MidiDriver_MPU401 {
public:
int open(int mode);
void close() { }
@@ -1051,7 +1112,7 @@ const char *MidiDriver::get_error_name(int error_code)
#define ADDR_DELIM ".:"
-class MidiDriver_ALSA:public MidiDriver {
+class MidiDriver_ALSA:public MidiDriver_MPU401 {
public:
MidiDriver_ALSA();
int open(int mode);
diff --git a/sound/mididrv.h b/sound/mididrv.h
index 6544f7f885..49fff19fd5 100644
--- a/sound/mididrv.h
+++ b/sound/mididrv.h
@@ -106,6 +106,12 @@ public:
send((range << 16) | ( 6 << 8) | (0xB0 | channel));
send(( 0 << 16) | ( 38 << 8) | (0xB0 | channel));
}
+
+ virtual void sysEx_customInstrument (byte channel, uint32 type, byte *instr) { }
+
+ // Timing functions - MidiDriver now operates timers
+ virtual void setTimerCallback (void *timer_param, void (*timer_proc) (void *)) = 0;
+ virtual uint32 getBaseTempo (void) = 0;
};
@@ -122,12 +128,14 @@ enum {
MD_COREAUDIO = 7,
MD_MIDIEMU = 8,
MD_ALSA = 9,
+ MD_ADLIB = 10
};
/* Factory functions => no need to include the specific classes
* in this header => faster compile */
extern MidiDriver *MidiDriver_NULL_create();
+extern MidiDriver *MidiDriver_ADLIB_create();
extern MidiDriver *MidiDriver_WIN_create();
extern MidiDriver *MidiDriver_TIMIDITY_create();
extern MidiDriver *MidiDriver_SEQ_create();
diff --git a/sound/midistreamer.cpp b/sound/midistreamer.cpp
index fcd4109c81..724b0852c5 100644
--- a/sound/midistreamer.cpp
+++ b/sound/midistreamer.cpp
@@ -37,6 +37,7 @@ private:
int _event_count;
int _event_index;
+ long _driver_tempo;
long _tempo;
uint16 _ticks_per_beat;
long _delay;
@@ -44,8 +45,8 @@ private:
volatile bool _active;
uint32 property(int prop, uint32 param);
- static int timer_thread (void *param);
- void on_timer (void);
+ static void timer_thread (void *param);
+ void on_timer();
public:
MidiStreamer (MidiDriver *target);
@@ -56,6 +57,9 @@ public:
void pause(bool p) { _paused = p; }
void set_stream_callback(void *param, StreamCallback *sc);
void setPitchBendRange (byte channel, uint range) { _target->setPitchBendRange (channel, range); }
+
+ void setTimerCallback (void *timer_param, void (*timer_proc) (void *)) { }
+ uint32 getBaseTempo (void) { return _target->getBaseTempo(); }
};
MidiStreamer::MidiStreamer (MidiDriver *target) :
@@ -82,7 +86,7 @@ void MidiStreamer::set_stream_callback (void *param, StreamCallback *sc)
_event_index = 0;
}
}
-
+/*
int MidiStreamer::timer_thread (void *param) {
MidiStreamer *mid = (MidiStreamer *) param;
int old_time, cur_time;
@@ -109,10 +113,14 @@ int MidiStreamer::timer_thread (void *param) {
mid->_active = false;
return 0;
}
+*/
+void MidiStreamer::timer_thread (void *param) {
+ ((MidiStreamer *) param)->on_timer();
+}
void MidiStreamer::on_timer()
{
- _delay += 10000;
+ _delay += _driver_tempo; // 10000;
while (true) {
if (_event_index >= _event_count) {
_event_count = _stream_proc (_stream_param, _events, ARRAYSIZE (_events));
@@ -145,18 +153,17 @@ int MidiStreamer::open (int mode)
if (res && res != MERR_ALREADY_OPEN)
return res;
- // Wait for existing timer thread to shut down.
- while (_active);
-
_event_index = _event_count = _delay = 0;
_mode = mode;
_paused = false;
- _active = true;
if (mode == MO_SIMPLE)
return 0;
- g_system->create_thread (timer_thread, this);
+// g_system->create_thread (timer_thread, this);
+ _driver_tempo = _target->getBaseTempo() / 500;
+
+ _target->setTimerCallback (this, &timer_thread);
return 0;
}
@@ -164,6 +171,15 @@ void MidiStreamer::close()
{
if (!_mode)
return;
+
+ _target->setTimerCallback (NULL, NULL);
+
+ // Turn off all notes on all channels,
+ // just to catch anything still playing.
+ int i;
+ for (i = 0; i < 16; ++i)
+ _target->send ((0x7B << 8) | 0xB0 | i);
+
_mode = 0;
_paused = true;
}