mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-27 21:54:15 +00:00
MTROPOLIS: Preliminary MIDI stuff
This commit is contained in:
parent
f5887475a9
commit
17458248c2
@ -24,11 +24,77 @@
|
||||
|
||||
#include "mtropolis/miniscript.h"
|
||||
|
||||
#include "audio/mididrv.h"
|
||||
#include "audio/midiplayer.h"
|
||||
#include "audio/midiparser.h"
|
||||
|
||||
|
||||
namespace MTropolis {
|
||||
|
||||
namespace Standard {
|
||||
|
||||
class MidiPlayer : public Audio::MidiPlayer {
|
||||
public:
|
||||
explicit MidiPlayer(int8 source);
|
||||
~MidiPlayer();
|
||||
|
||||
void playFile(const void *data, size_t size);
|
||||
int8 getSource() const;
|
||||
|
||||
private:
|
||||
int8 _source;
|
||||
bool _isInitialized;
|
||||
};
|
||||
|
||||
MidiPlayer::MidiPlayer(int8 source) : _isInitialized(false), _source(source) {
|
||||
MidiDriver::DeviceHandle deviceHdl = MidiDriver::detectDevice(MDT_MIDI);
|
||||
if (!deviceHdl)
|
||||
return;
|
||||
|
||||
_driver = MidiDriver::createMidi(deviceHdl);
|
||||
if (!_driver)
|
||||
return;
|
||||
|
||||
if (_driver->open() != 0) {
|
||||
_driver->close();
|
||||
delete _driver;
|
||||
_driver = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
_driver->setTimerCallback(static_cast<Audio::MidiPlayer *>(this), &timerCallback);
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
MidiPlayer::~MidiPlayer() {
|
||||
stop();
|
||||
|
||||
if (_parser)
|
||||
delete _parser;
|
||||
}
|
||||
|
||||
void MidiPlayer::playFile(const void *data, size_t size) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
stop();
|
||||
|
||||
_parser = MidiParser::createParser_SMF();
|
||||
_parser->setMidiDriver(this);
|
||||
_parser->setTimerRate(_driver->getBaseTempo());
|
||||
|
||||
// FIXME: MIDI API shouldn't need mutable void input...
|
||||
_parser->loadMusic(static_cast<byte *>(const_cast<void *>(data)), size);
|
||||
_parser->setTrack(0);
|
||||
_parser->startPlaying();
|
||||
|
||||
resume();
|
||||
}
|
||||
|
||||
int8 MidiPlayer::getSource() const {
|
||||
return _source;
|
||||
}
|
||||
|
||||
bool CursorModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::CursorModifier &data) {
|
||||
if (!_applyWhen.load(data.applyWhen) || !_removeWhen.load(data.removeWhen))
|
||||
return false;
|
||||
@ -134,7 +200,15 @@ Common::SharedPtr<Modifier> ObjectReferenceVariableModifier::shallowClone() cons
|
||||
return Common::SharedPtr<Modifier>(new ObjectReferenceVariableModifier(*this));
|
||||
}
|
||||
|
||||
MidiModifier::MidiModifier() : _plugIn(nullptr) {
|
||||
}
|
||||
|
||||
MidiModifier::~MidiModifier() {
|
||||
}
|
||||
|
||||
bool MidiModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::MidiModifier &data) {
|
||||
_plugIn = static_cast<StandardPlugIn *>(context.plugIn);
|
||||
|
||||
if (data.executeWhen.type != Data::PlugInTypeTaggedValue::kEvent)
|
||||
return false;
|
||||
|
||||
@ -176,8 +250,29 @@ bool MidiModifier::load(const PlugInModifierLoaderContext &context, const Data::
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MidiModifier::respondsToEvent(const Event &evt) const {
|
||||
return _executeWhen.respondsTo(evt) || _terminateWhen.respondsTo(evt);
|
||||
}
|
||||
|
||||
VThreadState MidiModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
|
||||
if (_executeWhen.respondsTo(msg->getEvent())) {
|
||||
if (_mode == kModeFile) {
|
||||
if (_embeddedFile) {
|
||||
_plugIn->getMidi()->playFile(&_embeddedFile->contents[0], _embeddedFile->contents.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return kVThreadReturn;
|
||||
}
|
||||
|
||||
Common::SharedPtr<Modifier> MidiModifier::shallowClone() const {
|
||||
return Common::SharedPtr<Modifier>(new MidiModifier(*this));
|
||||
Common::SharedPtr<MidiModifier> clone(new MidiModifier(*this));
|
||||
|
||||
clone->_isActive = false;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
ListVariableModifier::ListVariableModifier() : _list(new DynamicList()) {
|
||||
@ -322,7 +417,12 @@ StandardPlugIn::StandardPlugIn()
|
||||
, _objRefVarModifierFactory(this)
|
||||
, _midiModifierFactory(this)
|
||||
, _listVarModifierFactory(this)
|
||||
, _sysInfoModifierFactory(this) {
|
||||
, _sysInfoModifierFactory(this)
|
||||
, _lastAllocatedSourceID(0) {
|
||||
_midi.reset(new MidiPlayer(0));
|
||||
}
|
||||
|
||||
StandardPlugIn::~StandardPlugIn() {
|
||||
}
|
||||
|
||||
void StandardPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
|
||||
@ -343,6 +443,28 @@ StandardPlugInHacks& StandardPlugIn::getHacks() {
|
||||
return _hacks;
|
||||
}
|
||||
|
||||
MidiPlayer *StandardPlugIn::getMidi() const {
|
||||
return _midi.get();
|
||||
}
|
||||
|
||||
int8 StandardPlugIn::allocateMidiSource() {
|
||||
if (_deallocatedSources.size() > 0) {
|
||||
int8 src = _deallocatedSources.back();
|
||||
_deallocatedSources.pop_back();
|
||||
return src;
|
||||
}
|
||||
|
||||
if (_lastAllocatedSourceID == INT8_MAX)
|
||||
error("Ran out of MIDI sources");
|
||||
|
||||
_lastAllocatedSourceID++;
|
||||
return _lastAllocatedSourceID;
|
||||
}
|
||||
|
||||
void StandardPlugIn::deallocateMidiSource(int8 source) {
|
||||
_deallocatedSources.push_back(source);
|
||||
}
|
||||
|
||||
} // End of namespace Standard
|
||||
|
||||
namespace PlugIns {
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "mtropolis/runtime.h"
|
||||
#include "mtropolis/plugin/standard_data.h"
|
||||
|
||||
class MidiDriver;
|
||||
|
||||
namespace MTropolis {
|
||||
|
||||
class Runtime;
|
||||
@ -34,6 +36,7 @@ class Runtime;
|
||||
namespace Standard {
|
||||
|
||||
class StandardPlugIn;
|
||||
class MidiPlayer;
|
||||
|
||||
class CursorModifier : public Modifier {
|
||||
public:
|
||||
@ -112,8 +115,14 @@ private:
|
||||
|
||||
class MidiModifier : public Modifier {
|
||||
public:
|
||||
MidiModifier();
|
||||
~MidiModifier();
|
||||
|
||||
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::MidiModifier &data);
|
||||
|
||||
bool respondsToEvent(const Event &evt) const override;
|
||||
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
|
||||
|
||||
#ifdef MTROPOLIS_DEBUG_ENABLE
|
||||
const char *debugGetTypeName() const override { return "MIDI Modifier"; }
|
||||
#endif
|
||||
@ -155,6 +164,10 @@ private:
|
||||
ModeSpecificUnion _modeSpecific;
|
||||
|
||||
Common::SharedPtr<Data::Standard::MidiModifier::EmbeddedFile> _embeddedFile;
|
||||
|
||||
bool _isActive;
|
||||
|
||||
StandardPlugIn *_plugIn;
|
||||
};
|
||||
|
||||
class ListVariableModifier : public VariableModifier {
|
||||
@ -206,12 +219,18 @@ struct StandardPlugInHacks {
|
||||
class StandardPlugIn : public MTropolis::PlugIn {
|
||||
public:
|
||||
StandardPlugIn();
|
||||
~StandardPlugIn();
|
||||
|
||||
void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
|
||||
|
||||
const StandardPlugInHacks &getHacks() const;
|
||||
StandardPlugInHacks &getHacks();
|
||||
|
||||
MidiPlayer *getMidi() const;
|
||||
|
||||
int8 allocateMidiSource();
|
||||
void deallocateMidiSource(int8 source);
|
||||
|
||||
private:
|
||||
PlugInModifierFactory<CursorModifier, Data::Standard::CursorModifier> _cursorModifierFactory;
|
||||
PlugInModifierFactory<STransCtModifier, Data::Standard::STransCtModifier> _sTransCtModifierFactory;
|
||||
@ -221,7 +240,11 @@ private:
|
||||
PlugInModifierFactory<ListVariableModifier, Data::Standard::ListVariableModifier> _listVarModifierFactory;
|
||||
PlugInModifierFactory<SysInfoModifier, Data::Standard::SysInfoModifier> _sysInfoModifierFactory;
|
||||
|
||||
Common::SharedPtr<MidiPlayer> _midi;
|
||||
StandardPlugInHacks _hacks;
|
||||
|
||||
Common::Array<int8> _deallocatedSources;
|
||||
int8 _lastAllocatedSourceID;
|
||||
};
|
||||
|
||||
} // End of namespace Standard
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "common/ptr.h"
|
||||
|
||||
class MidiDriver;
|
||||
|
||||
namespace MTropolis {
|
||||
|
||||
class PlugIn;
|
||||
|
Loading…
x
Reference in New Issue
Block a user