diff options
-rw-r--r-- | scumm/imuse.cpp | 214 | ||||
-rw-r--r-- | scumm/imuse.h | 2 |
2 files changed, 95 insertions, 121 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp index a087c0e8f7..00fb6fe35d 100644 --- a/scumm/imuse.cpp +++ b/scumm/imuse.cpp @@ -52,7 +52,6 @@ // they will only be used from this file, so it will reduce // compile time. -class IMuseDriver; struct Part; struct HookDatas { @@ -70,6 +69,7 @@ struct HookDatas { struct Player { IMuseInternal *_se; + MidiDriver *_midi; Part *_parts; bool _active; @@ -111,7 +111,7 @@ struct Player { // Player part void hook_clear(); void clear(); - bool startSound(int sound); + bool startSound (int sound, MidiDriver *midi); void uninit_parts(); byte *parse_midi(byte *s); void key_off(uint8 chan, byte data); @@ -209,7 +209,6 @@ struct IsNoteCmdData { struct Part { int _slot; - IMuseDriver *_drv; Part *_next, *_prev; MidiChannel *_mc; Player *_player; @@ -240,7 +239,7 @@ struct Part { void key_on(byte note, byte velocity); void key_off(byte note); void set_param(byte param, int value) { } - void init(IMuseDriver * _driver); + void init(); void setup(Player *player); void uninit(); void off(); @@ -282,30 +281,6 @@ struct ImTrigger { byte command [4]; }; -// IMuseDriver class - -class IMuseDriver { -private: - IMuseInternal *_se; - OSystem *_system; - MidiDriver *_md; - Instrument _glob_instr[32]; // Adlib custom instruments - - static void timer_callback (void *); - -public: - IMuseDriver(MidiDriver *midi); - void uninit(); - void init(IMuseInternal *eng, OSystem *os); - - void set_instrument(uint slot, byte *instr); - void part_load_global_instrument (Part *part, byte slot); - - MidiChannel *allocateChannel() { return _md->allocateChannel(); } - MidiChannel *getPercussionChannel() { return _md->getPercussionChannel(); } - uint32 getBaseTempo() { return _md->getBaseTempo(); } -}; - // WARNING: This is the internal variant of the IMUSE class. // imuse.h contains a public version of the same class. // the public version, only contains a set of methods. @@ -313,7 +288,8 @@ class IMuseInternal { friend struct Player; private: - IMuseDriver * _driver; + MidiDriver *_midi_adlib; + MidiDriver *_midi_native; byte **_base_sounds; @@ -351,6 +327,7 @@ private: Part _parts[32]; uint16 _active_notes[128]; + Instrument _global_adlib_instruments[32]; CommandQueue _cmd_queue[64]; byte *findTag(int sound, char *tag, int index); @@ -360,17 +337,18 @@ private: Player *allocate_player(byte priority); void handle_marker(uint id, byte data); int get_channel_volume(uint a); + void initMidiDriver (MidiDriver *midi); void init_players(); void init_parts(); void init_volume_fader(); void init_sustaining_notes(); void init_queue(); - void sequencer_timers(); - void expire_sustain_notes(); - void expire_volume_faders(); + void sequencer_timers (MidiDriver *midi); + void expire_sustain_notes (MidiDriver *midi); + void expire_volume_faders (MidiDriver *midi); - Part *allocate_part(byte pri); + Part *allocate_part(byte pri, MidiDriver *midi); int32 ImSetTrigger (int sound, int id, int a, int b, int c, int d); int32 ImClearTrigger (int sound, int id); @@ -396,22 +374,22 @@ private: static int saveReference(void *me_ref, byte type, void *ref); static void *loadReference(void *me_ref, byte type, int ref); + static void midiTimerCallback (void *data); + public: IMuseInternal() { memset(this,0,sizeof(IMuseInternal)); // palmos } ~IMuseInternal(); - IMuseDriver *driver() { - return _driver; - } - int initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer); - void reallocateMidiChannels(); + void reallocateMidiChannels (MidiDriver *midi); + void setGlobalAdlibInstrument (byte slot, byte *data); + void copyGlobalAdlibInstrument (byte slot, Instrument *dest); // IMuse interface - void on_timer(); + void on_timer (MidiDriver *midi); void pause(bool paused); int terminate(); int save_or_load(Serializer *ser, Scumm *scumm); @@ -676,7 +654,7 @@ bool IMuseInternal::startSound(int sound) { return false; player->clear(); - return player->startSound(sound); + return player->startSound (sound, _midi_native); } @@ -740,7 +718,7 @@ void IMuseInternal::init_parts() { int i; for (i = 0, part = _parts; i != ARRAYSIZE(_parts); i++, part++) { - part->init(_driver); + part->init(); part->_slot = i; } } @@ -770,21 +748,21 @@ int IMuseInternal::stop_all_sounds() { return 0; } -void IMuseInternal::on_timer() { +void IMuseInternal::on_timer (MidiDriver *midi) { if (_paused) return; - sequencer_timers(); - expire_sustain_notes(); - expire_volume_faders(); + sequencer_timers (midi); + expire_sustain_notes (midi); + expire_volume_faders (midi); } -void IMuseInternal::sequencer_timers() { +void IMuseInternal::sequencer_timers (MidiDriver *midi) { Player *player = _players; int i; for (i = ARRAYSIZE(_players); i != 0; i--, player++) { - if (player->_active) { + if (player->_active && player->_midi == midi) { player->sequencer_timer(); } } @@ -844,7 +822,7 @@ int IMuseInternal::get_channel_volume(uint a) { return (_master_volume * _music_volume / 255) >> 1; } -Part *IMuseInternal::allocate_part(byte pri) { +Part *IMuseInternal::allocate_part (byte pri, MidiDriver *midi) { Part *part, *best = NULL; int i; @@ -859,14 +837,14 @@ Part *IMuseInternal::allocate_part(byte pri) { if (best) { best->uninit(); - reallocateMidiChannels(); + reallocateMidiChannels (midi); } else { debug(1, "Denying part request"); } return best; } -void IMuseInternal::expire_sustain_notes() { +void IMuseInternal::expire_sustain_notes (MidiDriver *midi) { SustainingNotes *sn, *next; Player *player; uint32 counter; @@ -874,6 +852,7 @@ void IMuseInternal::expire_sustain_notes() { for (sn = _sustain_notes_head; sn; sn = next) { next = sn->next; player = sn->player; + if (player->_midi != midi) continue; counter = sn->counter + player->_timer_speed; sn->pos += counter >> 16; @@ -897,7 +876,7 @@ void IMuseInternal::expire_sustain_notes() { } } -void IMuseInternal::expire_volume_faders() { +void IMuseInternal::expire_volume_faders (MidiDriver *midi) { VolumeFader *vf; int i; @@ -910,7 +889,7 @@ void IMuseInternal::expire_volume_faders() { _active_volume_faders = false; vf = _volume_fader; for (i = ARRAYSIZE(_volume_fader); i != 0; i--, vf++) { - if (vf->active) { + if (vf->active && vf->player->_midi == midi) { _active_volume_faders = true; vf->on_timer(false); } @@ -1172,13 +1151,19 @@ int IMuseInternal::get_master_volume() { } int IMuseInternal::terminate() { - if (_driver) { - _driver->uninit(); - delete _driver; - _driver = NULL; + if (_midi_adlib) { + _midi_adlib->close(); + delete _midi_adlib; + _midi_adlib = 0; + } + + if (_midi_native) { + _midi_native->close(); + delete _midi_native; + _midi_native = 0; } + return 0; - // Not implemented } int IMuseInternal::enqueue_trigger(int sound, int marker) { @@ -1638,17 +1623,13 @@ IMuseInternal *IMuseInternal::create(OSystem *syst, MidiDriver *midi, SoundMixer int IMuseInternal::initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer) { int i; - IMuseDriver *driv; if (midi == NULL) - driv = NULL; - else - driv = new IMuseDriver (midi); + error ("IMuse was initialized without a MIDI driver (even the NULL driver)"); - _driver = driv; - _game_tempo = driv->getBaseTempo(); - - driv->init(this, syst); + _midi_native = midi; + _game_tempo = _midi_native->getBaseTempo(); + initMidiDriver (_midi_native); _master_volume = 255; if (_music_volume < 1) @@ -1668,6 +1649,16 @@ int IMuseInternal::initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer return 0; } +void IMuseInternal::initMidiDriver (MidiDriver *midi) { + // Open MIDI driver + int result = midi->open(); + if (result) + error("IMuse initialization - ", MidiDriver::getErrorName(result)); + + // Connect to the driver's timer + midi->setTimerCallback (midi, &IMuseInternal::midiTimerCallback); +} + void IMuseInternal::init_queue() { _queue_adding = false; _queue_pos = 0; @@ -1739,9 +1730,10 @@ void Player::clear() { _se->ImFireAllTriggers (_id); _active = false; _ticks_per_beat = TICKS_PER_BEAT; + _midi = NULL; } -bool Player::startSound(int sound) { +bool Player::startSound (int sound, MidiDriver *midi) { void *mdhd; mdhd = _se->findTag(sound, MDHD_TAG, 0); @@ -1774,6 +1766,7 @@ bool Player::startSound(int sound) { _active = false; return false; } + _midi = midi; return true; } @@ -1846,7 +1839,7 @@ void Player::uninit_parts() { error("asd"); while (_parts) _parts->uninit(); - _se->reallocateMidiChannels(); // In case another player couldn't allocate all its parts + _se->reallocateMidiChannels (_midi); // In case another player couldn't allocate all its parts } void Player::uninit_seq() { @@ -1923,7 +1916,7 @@ byte *Player::parse_midi(byte *s) { break; case 18: // GP Slider 3 part->set_pri(value - 0x40); - _se->reallocateMidiChannels(); + _se->reallocateMidiChannels (_midi); break; case 64: // Sustain Pedal part->set_pedal(value != 0); @@ -2056,7 +2049,7 @@ void Player::parse_sysex(byte *p, uint len) { if (part->_percussion) { if (part->_mc) { part->off(); - _se->reallocateMidiChannels(); + _se->reallocateMidiChannels (_midi); } } else { part->sendAll(); @@ -2112,7 +2105,7 @@ void Player::parse_sysex(byte *p, uint len) { p++; a = *p++; decode_sysex_bytes(p, buf, len - 4); - _se->_driver->set_instrument(a, buf); + _se->setGlobalAdlibInstrument (a, buf); break; case 33: // Parameter adjust @@ -2586,7 +2579,7 @@ Part *Player::get_part(uint8 chan) { part = part->_next; } - part = _se->allocate_part(_priority); + part = _se->allocate_part (_priority, _midi); if (!part) { warning("no parts available"); return NULL; @@ -2619,7 +2612,7 @@ void Player::set_priority(int pri) { for (part = _parts; part; part = part->_next) { part->set_pri(part->_pri); } - _se->reallocateMidiChannels(); + _se->reallocateMidiChannels (_midi); } void Player::set_pan(int pan) { @@ -2676,7 +2669,7 @@ int Player::scan(uint totrack, uint tobeat, uint totick) { pos = scanptr - mtrk; _scanning = false; - _se->reallocateMidiChannels(); + _se->reallocateMidiChannels (_midi); play_active_notes(); _beat_index = tobeat; _tick_index = totick; @@ -2696,7 +2689,7 @@ void Player::turn_off_parts() { for (part = _parts; part; part = part->_next) part->off(); - _se->reallocateMidiChannels(); + _se->reallocateMidiChannels (_midi); } void Player::play_active_notes() { @@ -2996,7 +2989,7 @@ int IMuseInternal::save_or_load(Serializer *ser, Scumm *scumm) { init_sustaining_notes(); _active_volume_faders = true; fix_parts_after_load(); - reallocateMidiChannels(); + reallocateMidiChannels (_midi_native); set_master_volume (_master_volume); } @@ -3118,7 +3111,7 @@ void Part::set_onoff(bool on) { if (!on) off(); if (!_percussion) - _player->_se->reallocateMidiChannels(); + _player->_se->reallocateMidiChannels (_player->_midi); } } @@ -3128,7 +3121,8 @@ void Part::set_instrument(byte * data) { } void Part::load_global_instrument (byte slot) { - _drv->part_load_global_instrument (this, slot); + _player->_se->copyGlobalAdlibInstrument (slot, &_instrument); + if (clearToTransmit()) _instrument.send (_mc); } void Part::key_on(byte note, byte velocity) { @@ -3147,7 +3141,7 @@ void Part::key_on(byte note, byte velocity) { if (mc && _instrument.isValid()) { mc->noteOn (note, velocity); } else if (_percussion) { - mc = _drv->getPercussionChannel(); + mc = _player->_midi->getPercussionChannel(); if (!mc) return; mc->volume (_vol_eff); @@ -3162,14 +3156,13 @@ void Part::key_off(byte note) { if (mc) { mc->noteOff (note); } else if (_percussion) { - mc = _drv->getPercussionChannel(); + mc = _player->_midi->getPercussionChannel(); if (mc) mc->noteOff (note); } } -void Part::init(IMuseDriver * driver) { - _drv = driver; +void Part::init() { _player = NULL; _next = NULL; _prev = NULL; @@ -3235,13 +3228,14 @@ void Part::off() { _mc->allNotesOff(); _mc->release(); _mc = NULL; - memset (_actives, 0, sizeof(_actives)); } + memset (_actives, 0, sizeof(_actives)); } bool Part::clearToTransmit() { if (_mc) return true; - _player->_se->reallocateMidiChannels(); + _player->_se->reallocateMidiChannels (_player->_midi); + if (_mc) sendAll(); return false; } @@ -3301,38 +3295,17 @@ void Part::set_instrument(uint b) { //////////////////////////////////////// // -// General MIDI implementation of iMuse +// Some more IMuseInternal stuff // //////////////////////////////////////// -IMuseDriver::IMuseDriver (MidiDriver *midi) { - memset(this,0,sizeof(IMuseDriver)); //palmos - _md = midi; -} - -void IMuseDriver::init(IMuseInternal *eng, OSystem *syst) { - _system = syst; - - // Open MIDI driver - int result = _md->open(); - if (result) - error("IMuseDriver::error = %s", MidiDriver::getErrorName(result)); - - // Connect to the driver's timer - _se = eng; - _md->setTimerCallback (NULL, &IMuseDriver::timer_callback); -} - -void IMuseDriver::timer_callback (void *) { +void IMuseInternal::midiTimerCallback (void *data) { + MidiDriver *driver = (MidiDriver *) data; if (g_scumm->_imuse) - g_scumm->_imuse->on_timer(); -} - -void IMuseDriver::uninit() { - _md->close(); + g_scumm->_imuse->on_timer (driver); } -void IMuseInternal::reallocateMidiChannels() { +void IMuseInternal::reallocateMidiChannels (MidiDriver *midi) { Part *part, *hipart; int i; byte hipri, lopri; @@ -3342,7 +3315,10 @@ void IMuseInternal::reallocateMidiChannels() { hipri = 0; hipart = NULL; for (i = 32, part = _parts; i; i--, part++) { - if (part->_player && !part->_percussion && part->_on && !part->_mc && part->_pri_eff >= hipri) { + if (part->_player && part->_player->_midi == midi && + !part->_percussion && part->_on && + !part->_mc && part->_pri_eff >= hipri) + { hipri = part->_pri_eff; hipart = part; } @@ -3351,11 +3327,11 @@ void IMuseInternal::reallocateMidiChannels() { if (!hipart) return; - if ((hipart->_mc = _driver->allocateChannel()) == NULL) { + if ((hipart->_mc = midi->allocateChannel()) == NULL) { lopri = 255; lopart = NULL; for (i = 32, part = _parts; i; i--, part++) { - if (part->_mc && part->_pri_eff <= lopri) { + if (part->_mc && part->_mc->device() == midi && part->_pri_eff <= lopri) { lopri = part->_pri_eff; lopart = part; } @@ -3365,25 +3341,23 @@ void IMuseInternal::reallocateMidiChannels() { return; lopart->off(); - if ((hipart->_mc = _driver->allocateChannel()) == NULL) + if ((hipart->_mc = midi->allocateChannel()) == NULL) return; } hipart->sendAll(); } } -void IMuseDriver::set_instrument(uint slot, byte *data) { +void IMuseInternal::setGlobalAdlibInstrument (byte slot, byte *data) { if (slot < 32) { - // memcpy(&_glob_instr[slot], data, sizeof(Instrument)); - _glob_instr[slot].adlib (data); + _global_adlib_instruments[slot].adlib (data); } } -void IMuseDriver::part_load_global_instrument (Part *part, byte slot) { +void IMuseInternal::copyGlobalAdlibInstrument (byte slot, Instrument *dest) { if (slot >= 32) return; - _glob_instr [slot].copy_to (&part->_instrument); - if (part->clearToTransmit()) part->_instrument.send (part->_mc); + _global_adlib_instruments[slot].copy_to (dest); } //////////////////////////////////////////////////////////// @@ -3403,7 +3377,7 @@ IMuse::~IMuse() { if (_mutex) _system->delete_mutex (_mutex); if (_target) delet inline void IMuse::in() { _system->lock_mutex (_mutex); } inline void IMuse::out() { _system->unlock_mutex (_mutex); } -void IMuse::on_timer() { in(); _target->on_timer(); out(); } +void IMuse::on_timer (MidiDriver *midi) { in(); _target->on_timer (midi); out(); } void IMuse::pause(bool paused) { in(); _target->pause (paused); out(); } int IMuse::save_or_load(Serializer *ser, Scumm *scumm) { in(); int ret = _target->save_or_load (ser, scumm); out(); return ret; } int IMuse::set_music_volume(uint vol) { in(); int ret = _target->set_music_volume (vol); out(); return ret; } diff --git a/scumm/imuse.h b/scumm/imuse.h index adc47399d8..5ad6e3a608 100644 --- a/scumm/imuse.h +++ b/scumm/imuse.h @@ -47,7 +47,7 @@ public: PROP_TEMPO_BASE = 1 }; - void on_timer(); + void on_timer (MidiDriver *midi); void pause(bool paused); int save_or_load(Serializer *ser, Scumm *scumm); int set_music_volume(uint vol); |