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/base/Event.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/base/Event.cpp')
-rw-r--r-- | src/base/Event.cpp | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/src/base/Event.cpp b/src/base/Event.cpp new file mode 100644 index 0000000..e63e51b --- /dev/null +++ b/src/base/Event.cpp @@ -0,0 +1,445 @@ +// -*- 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 <cstdio> +#include <cctype> +#include <iostream> +#include "Event.h" +#include "XmlExportable.h" + +#if (__GNUC__ < 3) +#include <strstream> +#define stringstream strstream +#else +#include <sstream> +#endif + +namespace Rosegarden +{ +using std::string; +using std::ostream; + +PropertyName Event::EventData::NotationTime = "!notationtime"; +PropertyName Event::EventData::NotationDuration = "!notationduration"; + + +Event::EventData::EventData(const std::string &type, timeT absoluteTime, + timeT duration, short subOrdering) : + m_refCount(1), + m_type(type), + m_absoluteTime(absoluteTime), + m_duration(duration), + m_subOrdering(subOrdering), + m_properties(0) +{ + // empty +} + +Event::EventData::EventData(const std::string &type, timeT absoluteTime, + timeT duration, short subOrdering, + const PropertyMap *properties) : + m_refCount(1), + m_type(type), + m_absoluteTime(absoluteTime), + m_duration(duration), + m_subOrdering(subOrdering), + m_properties(properties ? new PropertyMap(*properties) : 0) +{ + // empty +} + +Event::EventData *Event::EventData::unshare() +{ + --m_refCount; + + EventData *newData = new EventData + (m_type, m_absoluteTime, m_duration, m_subOrdering, m_properties); + + return newData; +} + +Event::EventData::~EventData() +{ + if (m_properties) delete m_properties; +} + +timeT +Event::EventData::getNotationTime() const +{ + if (!m_properties) return m_absoluteTime; + PropertyMap::const_iterator i = m_properties->find(NotationTime); + if (i == m_properties->end()) return m_absoluteTime; + else return static_cast<PropertyStore<Int> *>(i->second)->getData(); +} + +timeT +Event::EventData::getNotationDuration() const +{ + if (!m_properties) return m_duration; + PropertyMap::const_iterator i = m_properties->find(NotationDuration); + if (i == m_properties->end()) return m_duration; + else return static_cast<PropertyStore<Int> *>(i->second)->getData(); +} + +void +Event::EventData::setTime(const PropertyName &name, timeT t, timeT deft) +{ + if (!m_properties) m_properties = new PropertyMap(); + PropertyMap::iterator i = m_properties->find(name); + + if (t != deft) { + if (i == m_properties->end()) { + m_properties->insert(PropertyPair(name, new PropertyStore<Int>(t))); + } else { + static_cast<PropertyStore<Int> *>(i->second)->setData(t); + } + } else if (i != m_properties->end()) { + delete i->second; + m_properties->erase(i); + } +} + +PropertyMap * +Event::find(const PropertyName &name, PropertyMap::iterator &i) +{ + PropertyMap *map = m_data->m_properties; + + if (!map || ((i = map->find(name)) == map->end())) { + + map = m_nonPersistentProperties; + if (!map) return 0; + + i = map->find(name); + if (i == map->end()) return 0; + } + + return map; +} + +bool +Event::has(const PropertyName &name) const +{ +#ifndef NDEBUG + ++m_hasCount; +#endif + + PropertyMap::const_iterator i; + const PropertyMap *map = find(name, i); + if (map) return true; + else return false; +} + +void +Event::unset(const PropertyName &name) +{ +#ifndef NDEBUG + ++m_unsetCount; +#endif + + unshare(); + PropertyMap::iterator i; + PropertyMap *map = find(name, i); + if (map) { + delete i->second; + map->erase(i); + } +} + + +PropertyType +Event::getPropertyType(const PropertyName &name) const + // throw (NoData) +{ + PropertyMap::const_iterator i; + const PropertyMap *map = find(name, i); + if (map) { + return i->second->getType(); + } else { + throw NoData(name.getName(), __FILE__, __LINE__); + } +} + + +string +Event::getPropertyTypeAsString(const PropertyName &name) const + // throw (NoData) +{ + PropertyMap::const_iterator i; + const PropertyMap *map = find(name, i); + if (map) { + return i->second->getTypeName(); + } else { + throw NoData(name.getName(), __FILE__, __LINE__); + } +} + + +string +Event::getAsString(const PropertyName &name) const + // throw (NoData) +{ + PropertyMap::const_iterator i; + const PropertyMap *map = find(name, i); + if (map) { + return i->second->unparse(); + } else { + throw NoData(name.getName(), __FILE__, __LINE__); + } +} + +// We could derive from XmlExportable and make this a virtual method +// overriding XmlExportable's pure virtual. We don't, because this +// class has no other virtual methods and for such a core class we +// could do without the overhead (given that it wouldn't really gain +// us anything anyway). + +string +Event::toXmlString() +{ + return toXmlString(0); +} + +string +Event::toXmlString(timeT expectedTime) +{ + std::stringstream out; + + out << "<event"; + + if (getType().length() != 0) { + out << " type=\"" << getType() << "\""; + } + + if (getDuration() != 0) { + out << " duration=\"" << getDuration() << "\""; + } + + if (getSubOrdering() != 0) { + out << " subordering=\"" << getSubOrdering() << "\""; + } + + if (expectedTime == 0) { + out << " absoluteTime=\"" << getAbsoluteTime() << "\""; + } else if (getAbsoluteTime() != expectedTime) { + out << " timeOffset=\"" << (getAbsoluteTime() - expectedTime) << "\""; + } + + out << ">"; + + // Save all persistent properties as <property> elements + + PropertyNames propertyNames(getPersistentPropertyNames()); + for (PropertyNames::const_iterator i = propertyNames.begin(); + i != propertyNames.end(); ++i) { + + out << "<property name=\"" + << XmlExportable::encode(i->getName()) << "\" "; + string type = getPropertyTypeAsString(*i); + for (unsigned int j = 0; j < type.size(); ++j) { + type[j] = (isupper(type[j]) ? tolower(type[j]) : type[j]); + } + + out << type << "=\"" + << XmlExportable::encode(getAsString(*i)) + << "\"/>"; + } + + // Save non-persistent properties (the persistence applies to + // copying events, not load/save) as <nproperty> elements + // unless they're view-local. View-local properties are + // assumed to have "::" in their name somewhere. + + propertyNames = getNonPersistentPropertyNames(); + for (PropertyNames::const_iterator i = propertyNames.begin(); + i != propertyNames.end(); ++i) { + + std::string s(i->getName()); + if (s.find("::") != std::string::npos) continue; + + out << "<nproperty name=\"" + << XmlExportable::encode(s) << "\" "; + string type = getPropertyTypeAsString(*i); + for (unsigned int j = 0; j < type.size(); ++j) { + type[j] = (isupper(type[j]) ? tolower(type[j]) : type[j]); + } + out << type << "=\"" + << XmlExportable::encode(getAsString(*i)) + << "\"/>"; + } + + out << "</event>"; + +#if (__GNUC__ < 3) + out << std::ends; +#endif + + return out.str(); +} + + +#ifndef NDEBUG +void +Event::dump(ostream& out) const +{ + out << "Event type : " << m_data->m_type.c_str() << '\n'; + + out << "\tAbsolute Time : " << m_data->m_absoluteTime + << "\n\tDuration : " << m_data->m_duration + << "\n\tSub-ordering : " << m_data->m_subOrdering + << "\n\tPersistent properties : \n"; + + if (m_data->m_properties) { + for (PropertyMap::const_iterator i = m_data->m_properties->begin(); + i != m_data->m_properties->end(); ++i) { + out << "\t\t" << i->first.getName() << " [" << i->first.getValue() << "] \t" << *(i->second) << "\n"; + } + } + + if (m_nonPersistentProperties) { + out << "\n\tNon-persistent properties : \n"; + + for (PropertyMap::const_iterator i = m_nonPersistentProperties->begin(); + i != m_nonPersistentProperties->end(); ++i) { + out << "\t\t" << i->first.getName() << " [" << i->first.getValue() << "] \t" << *(i->second) << '\n'; + } + } + + out << "Event storage size : " << getStorageSize() << '\n'; +} + + +int Event::m_getCount = 0; +int Event::m_setCount = 0; +int Event::m_setMaybeCount = 0; +int Event::m_hasCount = 0; +int Event::m_unsetCount = 0; +clock_t Event::m_lastStats = clock(); + +void +Event::dumpStats(ostream& out) +{ + clock_t now = clock(); + int ms = (now - m_lastStats) * 1000 / CLOCKS_PER_SEC; + out << "\nEvent stats, since start of run or last report (" + << ms << "ms ago):" << std::endl; + + out << "Calls to get<>: " << m_getCount << std::endl; + out << "Calls to set<>: " << m_setCount << std::endl; + out << "Calls to setMaybe<>: " << m_setMaybeCount << std::endl; + out << "Calls to has: " << m_hasCount << std::endl; + out << "Calls to unset: " << m_unsetCount << std::endl; + + m_getCount = m_setCount = m_setMaybeCount = m_hasCount = m_unsetCount = 0; + m_lastStats = clock(); +} + +#else + +void +Event::dumpStats(ostream&) +{ + // nothing +} + +#endif + +Event::PropertyNames +Event::getPropertyNames() const +{ + PropertyNames v; + if (m_data->m_properties) { + for (PropertyMap::const_iterator i = m_data->m_properties->begin(); + i != m_data->m_properties->end(); ++i) { + v.push_back(i->first); + } + } + if (m_nonPersistentProperties) { + for (PropertyMap::const_iterator i = m_nonPersistentProperties->begin(); + i != m_nonPersistentProperties->end(); ++i) { + v.push_back(i->first); + } + } + return v; +} + +Event::PropertyNames +Event::getPersistentPropertyNames() const +{ + PropertyNames v; + if (m_data->m_properties) { + for (PropertyMap::const_iterator i = m_data->m_properties->begin(); + i != m_data->m_properties->end(); ++i) { + v.push_back(i->first); + } + } + return v; +} + +Event::PropertyNames +Event::getNonPersistentPropertyNames() const +{ + PropertyNames v; + if (m_nonPersistentProperties) { + for (PropertyMap::const_iterator i = m_nonPersistentProperties->begin(); + i != m_nonPersistentProperties->end(); ++i) { + v.push_back(i->first); + } + } + return v; +} + +void +Event::clearNonPersistentProperties() +{ + if (m_nonPersistentProperties) m_nonPersistentProperties->clear(); +} + +size_t +Event::getStorageSize() const +{ + size_t s = sizeof(Event) + sizeof(EventData) + m_data->m_type.size(); + if (m_data->m_properties) { + for (PropertyMap::const_iterator i = m_data->m_properties->begin(); + i != m_data->m_properties->end(); ++i) { + s += sizeof(i->first); + s += i->second->getStorageSize(); + } + } + if (m_nonPersistentProperties) { + for (PropertyMap::const_iterator i = m_nonPersistentProperties->begin(); + i != m_nonPersistentProperties->end(); ++i) { + s += sizeof(i->first); + s += i->second->getStorageSize(); + } + } + return s; +} + +bool +operator<(const Event &a, const Event &b) +{ + timeT at = a.getAbsoluteTime(); + timeT bt = b.getAbsoluteTime(); + if (at != bt) return at < bt; + else return a.getSubOrdering() < b.getSubOrdering(); +} + +} |