diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
commit | 145364a8af6a1fec06556221e66d4b724a62fc9a (patch) | |
tree | 53bd71a544008c518034f208d64c932dc2883f50 /src/sound/MappedEvent.cpp | |
download | rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip |
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/sound/MappedEvent.cpp')
-rw-r--r-- | src/sound/MappedEvent.cpp | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/src/sound/MappedEvent.cpp b/src/sound/MappedEvent.cpp new file mode 100644 index 0000000..9b4ccab --- /dev/null +++ b/src/sound/MappedEvent.cpp @@ -0,0 +1,593 @@ +// -*- c-indentation-style:"stroustrup" c-basic-offset: 4 -*- + +/* + Rosegarden + A sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + The moral right of the authors to claim authorship of this work + has been asserted. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> + +#include <kstddirs.h> + +#include "MappedEvent.h" +#include "BaseProperties.h" +#include "Midi.h" +#include "MidiTypes.h" + +#define DEBUG_MAPPEDEVENT 1 + +namespace Rosegarden +{ + +MappedEvent::MappedEvent(InstrumentId id, + const Event &e, + const RealTime &eventTime, + const RealTime &duration): + m_trackId(0), + m_instrument(id), + m_type(MidiNote), + m_data1(0), + m_data2(0), + m_eventTime(eventTime), + m_duration(duration), + m_audioStartMarker(0, 0), + m_dataBlockId(0), + m_isPersistent(false), + m_runtimeSegmentId( -1), + m_autoFade(false), + m_fadeInTime(RealTime::zeroTime), + m_fadeOutTime(RealTime::zeroTime), + m_recordedChannel(0), + m_recordedDevice(0) + +{ + try { + + // For each event type, we set the properties in a particular + // order: first the type, then whichever of data1 and data2 fits + // less well with its default value. This way if one throws an + // exception for no data, we still have a good event with the + // defaults set. + + if (e.isa(Note::EventType)) { + m_type = MidiNoteOneShot; + long v = MidiMaxValue; + e.get<Int>(BaseProperties::VELOCITY, v); + m_data2 = v; + m_data1 = e.get<Int>(BaseProperties::PITCH); + } else if (e.isa(PitchBend::EventType)) { + m_type = MidiPitchBend; + PitchBend pb(e); + m_data1 = pb.getMSB(); + m_data2 = pb.getLSB(); + } else if (e.isa(Controller::EventType)) { + m_type = MidiController; + Controller c(e); + m_data1 = c.getNumber(); + m_data2 = c.getValue(); + } else if (e.isa(ProgramChange::EventType)) { + m_type = MidiProgramChange; + ProgramChange pc(e); + m_data1 = pc.getProgram(); + } else if (e.isa(KeyPressure::EventType)) { + m_type = MidiKeyPressure; + KeyPressure kp(e); + m_data1 = kp.getPitch(); + m_data2 = kp.getPressure(); + } else if (e.isa(ChannelPressure::EventType)) { + m_type = MidiChannelPressure; + ChannelPressure cp(e); + m_data1 = cp.getPressure(); + } else if (e.isa(SystemExclusive::EventType)) { + m_type = MidiSystemMessage; + m_data1 = MIDI_SYSTEM_EXCLUSIVE; + SystemExclusive s(e); + std::string dataBlock = s.getRawData(); + DataBlockRepository::getInstance()->registerDataBlockForEvent(dataBlock, this); + } else { + m_type = InvalidMappedEvent; + } + } catch (MIDIValueOutOfRange r) { + +#ifdef DEBUG_MAPPEDEVENT + std::cerr << "MIDI value out of range in MappedEvent ctor" + << std::endl; +#else + + ; +#endif + + } catch (Event::NoData d) { + +#ifdef DEBUG_MAPPEDEVENT + std::cerr << "Caught Event::NoData in MappedEvent ctor, message is:" + << std::endl << d.getMessage() << std::endl; +#else + + ; +#endif + + } catch (Event::BadType b) { + +#ifdef DEBUG_MAPPEDEVENT + std::cerr << "Caught Event::BadType in MappedEvent ctor, message is:" + << std::endl << b.getMessage() << std::endl; +#else + + ; +#endif + + } catch (SystemExclusive::BadEncoding e) { + +#ifdef DEBUG_MAPPEDEVENT + std::cerr << "Caught bad SysEx encoding in MappedEvent ctor" + << std::endl; +#else + + ; +#endif + + } +} + +bool +operator<(const MappedEvent &a, const MappedEvent &b) +{ + return a.getEventTime() < b.getEventTime(); +} + +MappedEvent& +MappedEvent::operator=(const MappedEvent &mE) +{ + if (&mE == this) + return * this; + + m_trackId = mE.getTrackId(); + m_instrument = mE.getInstrument(); + m_type = mE.getType(); + m_data1 = mE.getData1(); + m_data2 = mE.getData2(); + m_eventTime = mE.getEventTime(); + m_duration = mE.getDuration(); + m_audioStartMarker = mE.getAudioStartMarker(); + m_dataBlockId = mE.getDataBlockId(); + m_runtimeSegmentId = mE.getRuntimeSegmentId(); + m_autoFade = mE.isAutoFading(); + m_fadeInTime = mE.getFadeInTime(); + m_fadeOutTime = mE.getFadeOutTime(); + m_recordedChannel = mE.getRecordedChannel(); + m_recordedDevice = mE.getRecordedDevice(); + + return *this; +} + +// Do we use this? It looks dangerous so just commenting it out - rwb +// +//const size_t MappedEvent::streamedSize = 12 * sizeof(unsigned int); + +QDataStream& +operator<<(QDataStream &dS, MappedEvent *mE) +{ + dS << (unsigned int)mE->getTrackId(); + dS << (unsigned int)mE->getInstrument(); + dS << (unsigned int)mE->getType(); + dS << (unsigned int)mE->getData1(); + dS << (unsigned int)mE->getData2(); + dS << (unsigned int)mE->getEventTime().sec; + dS << (unsigned int)mE->getEventTime().nsec; + dS << (unsigned int)mE->getDuration().sec; + dS << (unsigned int)mE->getDuration().nsec; + dS << (unsigned int)mE->getAudioStartMarker().sec; + dS << (unsigned int)mE->getAudioStartMarker().nsec; + dS << (unsigned long)mE->getDataBlockId(); + dS << mE->getRuntimeSegmentId(); + dS << (unsigned int)mE->isAutoFading(); + dS << (unsigned int)mE->getFadeInTime().sec; + dS << (unsigned int)mE->getFadeInTime().nsec; + dS << (unsigned int)mE->getFadeOutTime().sec; + dS << (unsigned int)mE->getFadeOutTime().nsec; + dS << (unsigned int)mE->getRecordedChannel(); + dS << (unsigned int)mE->getRecordedDevice(); + + return dS; +} + +QDataStream& +operator<<(QDataStream &dS, const MappedEvent &mE) +{ + dS << (unsigned int)mE.getTrackId(); + dS << (unsigned int)mE.getInstrument(); + dS << (unsigned int)mE.getType(); + dS << (unsigned int)mE.getData1(); + dS << (unsigned int)mE.getData2(); + dS << (unsigned int)mE.getEventTime().sec; + dS << (unsigned int)mE.getEventTime().nsec; + dS << (unsigned int)mE.getDuration().sec; + dS << (unsigned int)mE.getDuration().nsec; + dS << (unsigned int)mE.getAudioStartMarker().sec; + dS << (unsigned int)mE.getAudioStartMarker().nsec; + dS << (unsigned long)mE.getDataBlockId(); + dS << mE.getRuntimeSegmentId(); + dS << (unsigned int)mE.isAutoFading(); + dS << (unsigned int)mE.getFadeInTime().sec; + dS << (unsigned int)mE.getFadeInTime().nsec; + dS << (unsigned int)mE.getFadeOutTime().sec; + dS << (unsigned int)mE.getFadeOutTime().nsec; + dS << (unsigned int)mE.getRecordedChannel(); + dS << (unsigned int)mE.getRecordedDevice(); + + return dS; +} + +QDataStream& +operator>>(QDataStream &dS, MappedEvent *mE) +{ + unsigned int trackId = 0, instrument = 0, type = 0, data1 = 0, data2 = 0; + long eventTimeSec = 0, eventTimeNsec = 0, durationSec = 0, durationNsec = 0, + audioSec = 0, audioNsec = 0; + std::string dataBlock; + unsigned long dataBlockId = 0; + int runtimeSegmentId = -1; + unsigned int autoFade = 0, + fadeInSec = 0, fadeInNsec = 0, fadeOutSec = 0, fadeOutNsec = 0, + recordedChannel = 0, recordedDevice = 0; + + dS >> trackId; + dS >> instrument; + dS >> type; + dS >> data1; + dS >> data2; + dS >> eventTimeSec; + dS >> eventTimeNsec; + dS >> durationSec; + dS >> durationNsec; + dS >> audioSec; + dS >> audioNsec; + dS >> dataBlockId; + dS >> runtimeSegmentId; + dS >> autoFade; + dS >> fadeInSec; + dS >> fadeInNsec; + dS >> fadeOutSec; + dS >> fadeOutNsec; + dS >> recordedChannel; + dS >> recordedDevice; + + mE->setTrackId((TrackId)trackId); + mE->setInstrument((InstrumentId)instrument); + mE->setType((MappedEvent::MappedEventType)type); + mE->setData1((MidiByte)data1); + mE->setData2((MidiByte)data2); + mE->setEventTime(RealTime(eventTimeSec, eventTimeNsec)); + mE->setDuration(RealTime(durationSec, durationNsec)); + mE->setAudioStartMarker(RealTime(audioSec, audioNsec)); + mE->setDataBlockId(dataBlockId); + mE->setRuntimeSegmentId(runtimeSegmentId); + mE->setAutoFade(autoFade); + mE->setFadeInTime(RealTime(fadeInSec, fadeInNsec)); + mE->setFadeOutTime(RealTime(fadeOutSec, fadeOutNsec)); + mE->setRecordedChannel(recordedChannel); + mE->setRecordedDevice(recordedDevice); + + return dS; +} + +QDataStream& +operator>>(QDataStream &dS, MappedEvent &mE) +{ + unsigned int trackId = 0, instrument = 0, type = 0, data1 = 0, data2 = 0; + long eventTimeSec = 0, eventTimeNsec = 0, durationSec = 0, durationNsec = 0, + audioSec = 0, audioNsec = 0; + std::string dataBlock; + unsigned long dataBlockId = 0; + int runtimeSegmentId = -1; + unsigned int autoFade = 0, + fadeInSec = 0, fadeInNsec = 0, fadeOutSec = 0, fadeOutNsec = 0, + recordedChannel = 0, recordedDevice = 0; + + dS >> trackId; + dS >> instrument; + dS >> type; + dS >> data1; + dS >> data2; + dS >> eventTimeSec; + dS >> eventTimeNsec; + dS >> durationSec; + dS >> durationNsec; + dS >> audioSec; + dS >> audioNsec; + dS >> dataBlockId; + dS >> runtimeSegmentId; + dS >> autoFade; + dS >> fadeInSec; + dS >> fadeInNsec; + dS >> fadeOutSec; + dS >> fadeOutNsec; + dS >> recordedChannel; + dS >> recordedDevice; + + mE.setTrackId((TrackId)trackId); + mE.setInstrument((InstrumentId)instrument); + mE.setType((MappedEvent::MappedEventType)type); + mE.setData1((MidiByte)data1); + mE.setData2((MidiByte)data2); + mE.setEventTime(RealTime(eventTimeSec, eventTimeNsec)); + mE.setDuration(RealTime(durationSec, durationNsec)); + mE.setAudioStartMarker(RealTime(audioSec, audioNsec)); + mE.setDataBlockId(dataBlockId); + mE.setRuntimeSegmentId(runtimeSegmentId); + mE.setAutoFade(autoFade); + mE.setFadeInTime(RealTime(fadeInSec, fadeInNsec)); + mE.setFadeOutTime(RealTime(fadeOutSec, fadeOutNsec)); + mE.setRecordedChannel(recordedChannel); + mE.setRecordedDevice(recordedDevice); + + return dS; +} + +void +MappedEvent::addDataByte(MidiByte byte) +{ + DataBlockRepository::getInstance()->addDataByteForEvent(byte, this); +} + +void +MappedEvent::addDataString(const std::string& data) +{ + DataBlockRepository::getInstance()->addDataStringForEvent(data, this); +} + + + +//-------------------------------------------------- + +class DataBlockFile +{ +public: + DataBlockFile(DataBlockRepository::blockid id); + ~DataBlockFile(); + + QString getFileName() + { + return m_fileName; + } + + void addDataByte(MidiByte); + void addDataString(const std::string&); + + void clear() + { + m_cleared = true; + } + bool exists(); + void setData(const std::string&); + std::string getData(); + +protected: + void prepareToWrite(); + void prepareToRead(); + + //--------------- Data members --------------------------------- + QString m_fileName; + QFile m_file; + bool m_cleared; +}; + +DataBlockFile::DataBlockFile(DataBlockRepository::blockid id) + : m_fileName(KGlobal::dirs()->resourceDirs("tmp").first() + QString("/rosegarden_datablock_%1").arg(id)), + m_file(m_fileName), + m_cleared(false) +{ + // std::cerr << "DataBlockFile " << m_fileName.latin1() << std::endl; +} + +DataBlockFile::~DataBlockFile() +{ + if (m_cleared) { +// std::cerr << "~DataBlockFile : removing " << m_fileName.latin1() << std::endl; + QFile::remove + (m_fileName); + } + +} + +bool DataBlockFile::exists() +{ + return QFile::exists(m_fileName); +} + +void DataBlockFile::setData(const std::string& s) +{ + // std::cerr << "DataBlockFile::setData() : setting data to " << m_fileName << std::endl; + prepareToWrite(); + + QDataStream stream(&m_file); + stream.writeRawBytes(s.data(), s.length()); +} + +std::string DataBlockFile::getData() +{ + if (!exists()) + return std::string(); + + prepareToRead(); + + QDataStream stream(&m_file); + // std::cerr << "DataBlockFile::getData() : file size = " << m_file.size() << std::endl; + char* tmp = new char[m_file.size()]; + stream.readRawBytes(tmp, m_file.size()); + std::string res(tmp, m_file.size()); + delete[] tmp; + + return res; +} + +void DataBlockFile::addDataByte(MidiByte byte) +{ + prepareToWrite(); + m_file.putch(byte); +} + +void DataBlockFile::addDataString(const std::string& s) +{ + prepareToWrite(); + QDataStream stream(&m_file); + stream.writeRawBytes(s.data(), s.length()); +} + +void DataBlockFile::prepareToWrite() +{ + // std::cerr << "DataBlockFile[" << m_fileName << "]: prepareToWrite" << std::endl; + if (!m_file.isWritable()) { + m_file.close(); + m_file.open(IO_WriteOnly | IO_Append); + assert(m_file.isWritable()); + } +} + +void DataBlockFile::prepareToRead() +{ +// std::cerr << "DataBlockFile[" << m_fileName << "]: prepareToRead" << std::endl; + if (!m_file.isReadable()) { + m_file.close(); + m_file.open(IO_ReadOnly); + assert(m_file.isReadable()); + } +} + + + +//-------------------------------------------------- + +DataBlockRepository* DataBlockRepository::getInstance() +{ + if (!m_instance) + m_instance = new DataBlockRepository; + return m_instance; +} + +std::string DataBlockRepository::getDataBlock(DataBlockRepository::blockid id) +{ + DataBlockFile dataBlockFile(id); + + if (dataBlockFile.exists()) + return dataBlockFile.getData(); + + return std::string(); +} + + +std::string DataBlockRepository::getDataBlockForEvent(MappedEvent* e) +{ + blockid id = e->getDataBlockId(); + if (id == 0) { + // std::cerr << "WARNING: DataBlockRepository::getDataBlockForEvent called on event with data block id 0" << std::endl; + return ""; + } + return getInstance()->getDataBlock(id); +} + +void DataBlockRepository::setDataBlockForEvent(MappedEvent* e, const std::string& s) +{ + blockid id = e->getDataBlockId(); + if (id == 0) { + // std::cerr << "Creating new datablock for event" << std::endl; + getInstance()->registerDataBlockForEvent(s, e); + } else { + // std::cerr << "Writing " << s.length() << " chars to file for datablock " << id << std::endl; + DataBlockFile dataBlockFile(id); + dataBlockFile.setData(s); + } +} + +bool DataBlockRepository::hasDataBlock(DataBlockRepository::blockid id) +{ + return DataBlockFile(id).exists(); +} + +DataBlockRepository::blockid DataBlockRepository::registerDataBlock(const std::string& s) +{ + blockid id = 0; + while (id == 0 || DataBlockFile(id).exists()) + id = (blockid)random(); + + // std::cerr << "DataBlockRepository::registerDataBlock: " << s.length() << " chars, id is " << id << std::endl; + + DataBlockFile dataBlockFile(id); + dataBlockFile.setData(s); + + return id; +} + +void DataBlockRepository::unregisterDataBlock(DataBlockRepository::blockid id) +{ + DataBlockFile dataBlockFile(id); + + dataBlockFile.clear(); +} + +void DataBlockRepository::registerDataBlockForEvent(const std::string& s, MappedEvent* e) +{ + e->setDataBlockId(registerDataBlock(s)); +} + +void DataBlockRepository::unregisterDataBlockForEvent(MappedEvent* e) +{ + unregisterDataBlock(e->getDataBlockId()); +} + + +DataBlockRepository::DataBlockRepository() +{} + +void DataBlockRepository::clear() +{ +#ifdef DEBUG_MAPPEDEVENT + std::cerr << "DataBlockRepository::clear()\n"; +#endif + + // Erase all 'datablock_*' files + // + QString tmpPath = KGlobal::dirs()->resourceDirs("tmp").first(); + + QDir segmentsDir(tmpPath, "rosegarden_datablock_*"); + for (unsigned int i = 0; i < segmentsDir.count(); ++i) { + QString segmentName = tmpPath + '/' + segmentsDir[i]; + QFile::remove + (segmentName); + } +} + + +void DataBlockRepository::addDataByteForEvent(MidiByte byte, MappedEvent* e) +{ + DataBlockFile dataBlockFile(e->getDataBlockId()); + dataBlockFile.addDataByte(byte); + +} + +void DataBlockRepository::addDataStringForEvent(const std::string& s, MappedEvent* e) +{ + DataBlockFile dataBlockFile(e->getDataBlockId()); + dataBlockFile.addDataString(s); +} + +DataBlockRepository* DataBlockRepository::m_instance = 0; + +} |