/* -*- c-basic-offset: 2; indent-tabs-mode: nil; -*- */
/*
* FreeDots -- MusicXML to braille music transcription
*
* Copyright 2008-2010 Mario Lang All Rights Reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details (a copy is included in the LICENSE.txt file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License
* along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This file is maintained by Mario Lang <mlang@delysid.org>.
*/
package freedots.musicxml;
import java.util.ArrayList;
import java.util.List;
import freedots.music.KeySignature;
import freedots.music.TimeSignature;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/** A wrapper around the attributes element.
*/
public final class Attributes {
private final Element element;
public Attributes(final Element element) {
this.element = element;
}
public int getDivisions() {
NodeList nodeList = element.getElementsByTagName("divisions");
if (nodeList.getLength() == 1) {
Node textNode = nodeList.item(0).getChildNodes().item(0);
int divisions = Math.round(Float.parseFloat(textNode.getNodeValue()));
return divisions;
}
return 0;
}
public int getStaves() {
NodeList nodeList = element.getElementsByTagName("staves");
if (nodeList.getLength() == 1) {
Node textNode = nodeList.item(0).getChildNodes().item(0);
int staves = Integer.parseInt(textNode.getNodeValue());
return staves;
}
return 0;
}
public List<Clef> getClefs() {
NodeList nodeList = element.getElementsByTagName("clef");
List<Clef> clefs = new ArrayList<Clef>();
for (int index = 0; index < nodeList.getLength(); index++) {
clefs.add(new Clef((Element)nodeList.item(index)));
}
return clefs;
}
public Time getTime() {
NodeList nodeList = element.getElementsByTagName("time");
if (nodeList.getLength() == 1) {
return new Time((Element)nodeList.item(0));
} else if (nodeList.getLength() > 1) {
System.err.println("Unhandled multiple time signatures in attributes");
}
return null;
}
public List<Key> getKeys() {
NodeList nodeList = element.getElementsByTagName("key");
List<Key> keys = new ArrayList<Key>();
for (int index = 0; index < nodeList.getLength(); index++) {
keys.add(new Key((Element)nodeList.item(index)));
}
return keys;
}
public Transpose getTranspose() {
for (Node node = element.getFirstChild(); node != null;
node = node.getNextSibling())
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element)node;
if ("transpose".equals(child.getTagName()))
return new Transpose(child);
}
return null;
}
class Clef extends freedots.music.Clef {
private Element element = null;
private String staffNumber = null;
Clef(final Element element) {
super(getClefSignFromElement(element));
if (sign != Sign.percussion && sign != Sign.none) {
line = getClefLineFromElement(element);
}
this.element = element;
if (element.hasAttribute("number"))
staffNumber = element.getAttribute("number");
}
public int getStaffNumber() {
if (staffNumber != null) return Integer.parseInt(staffNumber) - 1;
return 0;
}
}
class Time extends TimeSignature {
private Element element = null;
Time(final Element element) {
super(getBeatsFromElement(element), getBeatTypeFromElement(element));
this.element = element;
}
}
class Key extends KeySignature {
private Element element = null;
private String staffName = null;
Key(final Element element) {
super(getFifthsFromElement(element));
this.element = element;
staffName = element.getAttribute("number");
if (staffName.equals("")) staffName = null;
}
public String getStaffName() { return staffName; }
}
final class Transpose {
private Element chromatic, diatonic, octaveChange, doubleDown;
Transpose(final Element element) {
for (Node node = element.getFirstChild(); node != null;
node = node.getNextSibling())
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element)node;
if ("chromatic".equals(child.getTagName())) chromatic = child;
else if ("diatonic".equals(child.getTagName())) diatonic = child;
else if ("octave-change".equals(child.getTagName())) octaveChange = child;
else if ("double".equals(child.getTagName())) doubleDown = child;
}
}
public int getChromatic() {
if (chromatic != null)
return Integer.parseInt(chromatic.getTextContent());
return 0;
}
public int getOctaveChange() {
if (octaveChange != null)
return Integer.parseInt(octaveChange.getTextContent());
return 0;
}
}
private static int getBeatsFromElement(Element element)
throws MusicXMLParseException {
NodeList nodeList = element.getElementsByTagName("beats");
int nodeCount = nodeList.getLength();
if (nodeCount >= 1) {
Node textNode = nodeList.item(nodeCount-1).getChildNodes().item(0);
return Integer.parseInt(textNode.getNodeValue());
}
throw new MusicXMLParseException("missing <beats> element");
}
private static int
getBeatTypeFromElement(Element element) throws MusicXMLParseException {
NodeList nodeList = element.getElementsByTagName("beat-type");
int nodeCount = nodeList.getLength();
if (nodeCount >= 1) {
Node textNode = nodeList.item(nodeCount-1).getChildNodes().item(0);
return Integer.parseInt(textNode.getNodeValue());
}
throw new MusicXMLParseException("missing <beat-type> element");
}
private static int
getFifthsFromElement(Element element) throws MusicXMLParseException {
NodeList nodeList = element.getElementsByTagName("fifths");
int nodeCount = nodeList.getLength();
if (nodeCount >= 1) {
Node textNode = nodeList.item(nodeCount-1).getChildNodes().item(0);
return Integer.parseInt(textNode.getNodeValue());
}
throw new MusicXMLParseException("missing <fifths> element");
}
private static Clef.Sign getClefSignFromElement(Element element) throws MusicXMLParseException {
NodeList nodeList = element.getElementsByTagName("sign");
int nodeCount = nodeList.getLength();
if (nodeCount >= 1) {
Node textNode = nodeList.item(nodeCount-1).getChildNodes().item(0);
return Enum.valueOf(Clef.Sign.class, textNode.getNodeValue());
}
throw new MusicXMLParseException("missing <sign> element");
}
static int getClefLineFromElement(Element element) throws MusicXMLParseException {
NodeList nodeList = element.getElementsByTagName("line");
int nodeCount = nodeList.getLength();
if (nodeCount >= 1) {
Node textNode = nodeList.item(nodeCount-1).getChildNodes().item(0);
return Integer.parseInt(textNode.getNodeValue());
}
throw new MusicXMLParseException("missing <line> element");
}
}