summaryrefslogtreecommitdiffstats
path: root/src/sound/MappedEvent.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/sound/MappedEvent.cpp
downloadrosegarden-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.cpp593
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 <glaurent@telegraph-road.org>,
+ Chris Cannam <cannam@all-day-breakfast.com>,
+ Richard Bown <bownie@bownie.com>
+
+ 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;
+
+}