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/document/io/HydrogenXMLHandler.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/document/io/HydrogenXMLHandler.cpp')
-rw-r--r-- | src/document/io/HydrogenXMLHandler.cpp | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/src/document/io/HydrogenXMLHandler.cpp b/src/document/io/HydrogenXMLHandler.cpp new file mode 100644 index 0000000..68e1b20 --- /dev/null +++ b/src/document/io/HydrogenXMLHandler.cpp @@ -0,0 +1,403 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio 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 rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + 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 "HydrogenXMLHandler.h" + +#include "base/Event.h" +#include "base/BaseProperties.h" +#include <klocale.h> +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "base/Composition.h" +#include "base/Instrument.h" +#include "base/MidiProgram.h" +#include "base/NotationTypes.h" +#include "base/Segment.h" +#include "base/Track.h" +#include <qstring.h> + + +namespace Rosegarden +{ + +HydrogenXMLHandler::HydrogenXMLHandler(Composition *composition, + InstrumentId drumIns): + m_composition(composition), + m_drumInstrument(drumIns), + m_inNote(false), + m_inInstrument(false), + m_inPattern(false), + m_inSequence(false), + m_patternName(""), + m_patternSize(0), + m_sequenceName(""), + m_position(0), + m_velocity(0.0), + m_panL(0.0), + m_panR(0.0), + m_pitch(0.0), + m_instrument(0), + m_id(0), + m_muted(false), + m_fileName(""), + m_bpm(0), + m_volume(0.0), + m_name(""), + m_author(""), + m_notes(""), + m_songMode(false), + m_version(""), + m_currentProperty(""), + m_segment(0), + m_currentTrackNb(0), + m_segmentAdded(false), + m_currentBar(0), + m_newSegment(false) +{} + +bool +HydrogenXMLHandler::startDocument() +{ + RG_DEBUG << "HydrogenXMLHandler::startDocument" << endl; + + m_inNote = false; + m_inInstrument = false; + m_inPattern = false; + m_inSequence = false; + + // Pattern attributes + // + m_patternName = ""; + m_patternSize = 0; + + // Sequence attributes + // + m_sequenceName = ""; + + // Note attributes + // + m_position = 0; + m_velocity = 0.0; + m_panL = 0.0; + m_panR = 0.0; + m_pitch = 0.0; + m_instrument = 0; + + // Instrument attributes + // + m_id = 0; + m_muted = false; + m_instrumentVolumes.clear(); + m_fileName = ""; + + // Global attributes + // + m_bpm = 0; + m_volume = 0.0; + m_name = ""; + m_author = ""; + m_notes = ""; + m_songMode = false; + m_version = ""; + + m_currentProperty = ""; + + m_segment = 0; + m_currentTrackNb = 0; + m_segmentAdded = 0; + m_currentBar = 0; + m_newSegment = false; + + return true; +} + +bool +HydrogenXMLHandler::startElement(const QString& /*namespaceURI*/, + const QString& /*localName*/, + const QString& qName, + const QXmlAttributes& /*atts*/) +{ + QString lcName = qName.lower(); + + if (lcName == "note") { + + if (m_inInstrument) + return false; + + m_inNote = true; + + } else if (lcName == "instrument") { + + // Beware instrument attributes inside Notes + if (!m_inNote) + m_inInstrument = true; + } else if (lcName == "pattern") { + m_inPattern = true; + m_segmentAdded = false; // flag the segments being added + } else if (lcName == "sequence") { + + // Create a new segment and set some flags + // + m_segment = new Segment(); + m_newSegment = true; + m_inSequence = true; + } + + m_currentProperty = lcName; + + return true; +} + +bool +HydrogenXMLHandler::endElement(const QString& /*namespaceURI*/, + const QString& /*localName*/, + const QString& qName) +{ + QString lcName = qName.lower(); + + if (lcName == "note") { + + RG_DEBUG << "HydrogenXMLHandler::endElement - Hydrogen Note : position = " << m_position + << ", velocity = " << m_velocity + << ", panL = " << m_panL + << ", panR = " << m_panR + << ", pitch = " << m_pitch + << ", instrument = " << m_instrument + << endl; + + timeT barLength = m_composition->getBarEnd(m_currentBar) - + m_composition->getBarStart(m_currentBar); + + timeT pos = m_composition->getBarStart(m_currentBar) + + timeT( + double(m_position) / double(m_patternSize) * double(barLength)); + + // Insert a rest if we've got a new segment + // + if (m_newSegment) { + Event *restEvent = new Event(Note::EventRestType, + m_composition->getBarStart(m_currentBar), + pos - m_composition->getBarStart(m_currentBar), + Note::EventRestSubOrdering); + m_segment->insert(restEvent); + m_newSegment = false; + } + + // Create and insert this event + // + Event *noteEvent = new Event(Note::EventType, + pos, Note(Note::Semiquaver).getDuration()); + + // get drum mapping from instrument and calculate velocity + noteEvent->set + <Int>( + BaseProperties::PITCH, 36 + m_instrument); + noteEvent->set + <Int>(BaseProperties::VELOCITY, + int(127.0 * m_velocity * m_volume * + m_instrumentVolumes[m_instrument])); + m_segment->insert(noteEvent); + + m_inNote = false; + + } else if (lcName == "instrument" && m_inInstrument) { + + RG_DEBUG << "HydrogenXMLHandler::endElement - Hydrogen Instrument : id = " << m_id + << ", muted = " << m_muted + << ", volume = " << m_instrumentVolumes[m_instrument] + << ", filename = \"" << m_fileName << "\"" + << endl; + + m_inInstrument = false; + + } else if (lcName == "pattern") { + m_inPattern = false; + + if (m_segmentAdded) { + + // Add a blank track to demarcate patterns + // + Track *track = new Track + (m_currentTrackNb, m_drumInstrument, m_currentTrackNb, + "<blank spacer>", false); + m_currentTrackNb++; + m_composition->addTrack(track); + + m_segmentAdded = false; + + // Each pattern has it's own bar so that the imported + // song shows off each pattern a bar at a time. + // + m_currentBar++; + } + + } else if (lcName == "sequence") { + + // If we're closing out a sequencer tab and we have a m_segment then + // we should close up and add that segment. Only create if we have + // some Events in it + // + if (m_segment->size() > 0) { + + m_segment->setTrack(m_currentTrackNb); + + Track *track = new Track + (m_currentTrackNb, m_drumInstrument, m_currentTrackNb, + m_patternName, false); + m_currentTrackNb++; + + // Enforce start and end markers for this bar so that we have a + // whole bar unit segment. + // + m_segment->setEndMarkerTime(m_composition->getBarEnd(m_currentBar)); + QString label = QString("%1 - %2 %3 %4").arg(strtoqstr(m_patternName)) + .arg(strtoqstr(m_sequenceName)) + .arg(i18n(" imported from Hydrogen ")).arg(strtoqstr(m_version)); + m_segment->setLabel(qstrtostr(label)); + + m_composition->addTrack(track); + m_composition->addSegment(m_segment); + m_segment = 0; + + m_segmentAdded = true; + } + + m_inSequence = false; + + } + + return true; +} + +bool +HydrogenXMLHandler::characters(const QString& chars) +{ + QString ch = chars.stripWhiteSpace(); + if (ch == "") + return true; + + if (m_inNote) { + if (m_currentProperty == "position") { + m_position = ch.toInt(); + } else if (m_currentProperty == "velocity") { + m_velocity = qstrtodouble(ch); + } else if (m_currentProperty == "pan_L") { + m_panL = qstrtodouble(ch); + } else if (m_currentProperty == "pan_R") { + m_panR = qstrtodouble(ch); + } else if (m_currentProperty == "pitch") { + m_pitch = qstrtodouble(ch); + } else if (m_currentProperty == "instrument") { + m_instrument = ch.toInt(); + + // Standard kit conversion - hardcoded conversion for Hyrdogen's default + // drum kit. The m_instrument mapping for low values maps well onto the + // kick drum GM kit starting point (MIDI pitch = 36). + // + switch (m_instrument) { + case 11: // Cowbell + m_instrument = 20; + break; + case 12: // Ride Jazz + m_instrument = 15; + break; + case 14: // Ride Rock + m_instrument = 17; + break; + case 15: // Crash Jazz + m_instrument = 16; + break; + + default: + break; + } + + } + } else if (m_inInstrument) { + if (m_currentProperty == "id") { + m_id = ch.toInt(); + } else if (m_currentProperty == "ismuted") { + if (ch.lower() == "true") + m_muted = true; + else + m_muted = false; + } else if (m_currentProperty == "filename") { + m_fileName = qstrtostr(chars); // don't strip whitespace from the filename + } else if (m_currentProperty == "volume") { + m_instrumentVolumes.push_back(qstrtodouble(ch)); + } + + + } else if (m_inPattern) { + + // Pattern attributes + + if (m_currentProperty == "name") { + if (m_inSequence) + m_sequenceName = qstrtostr(chars); + else + m_patternName = qstrtostr(chars); + } else if (m_currentProperty == "size") { + m_patternSize = ch.toInt(); + } + + } else { + + // Global attributes + if (m_currentProperty == "version") { + m_version = qstrtostr(chars); + } else if (m_currentProperty == "bpm") { + + m_bpm = qstrtodouble(ch); + m_composition->addTempoAtTime + (0, Composition::getTempoForQpm(m_bpm)); + + } else if (m_currentProperty == "volume") { + m_volume = qstrtodouble(ch); + } else if (m_currentProperty == "name") { + m_name = qstrtostr(chars); + } else if (m_currentProperty == "author") { + m_author = qstrtostr(chars); + } else if (m_currentProperty == "notes") { + m_notes = qstrtostr(chars); + } else if (m_currentProperty == "mode") { + if (ch.lower() == "song") + m_songMode = true; + else + m_songMode = false; + } + } + + return true; +} + +bool +HydrogenXMLHandler::endDocument() +{ + RG_DEBUG << "HydrogenXMLHandler::endDocument" << endl; + return true; +} + +} |