/***************************************************************** MusicMl by the Connection Factory, March 5, 1998 (c) Copyright notice A simple MusicML Applet wich reads a MusicML document parses it with the microsoft xml parser and then parses the document tree to display it on a lightweight component. The com.ms.xml.. classes are by Microsoft and can be found at http://www.microsoft.com/ MusicML (c) Copyright by The Connection Factory B.V. Grotekerkplein 38 3011 GE Rotterdam the Netherlands +31 10 4046870 info@tcf.nl You may use this code for educational purposes only. Feel free to experiment with it. Commercial usage of any part of MusicML including its java classes and DTD description is prohibited. If you do want to use MusicML for commercial usage contact The Connection Factory at the above mentioned address *****************************************************************/ import com.ms.xml.parser.* ; import com.ms.xml.om.Document ; import com.ms.xml.om.Element ; import com.ms.xml.util.XMLOutputStream ; import com.ms.xml.util.Name ; import com.ms.xml.om.ElementEnumeration; import com.ms.xml.om.ElementImpl ; import com.ms.xml.util.Name ; import com.ms.xml.om.ElementFactory ; import java.util.Enumeration ; import java.io.* ; import java.io.PrintStream ; import java.net.* ; import java.awt.* ; import java.util.Vector ; import java.awt.event.* ; import java.applet.* ; /* * the MusicML applet class */ public class MusicML extends Applet { public void init(){ xmlFile = getParameter("XMLFILE"); rowWidth = Integer.parseInt( getParameter("ROWWIDTH") ); if (xmlFile != null) { Document d = null; try { // create the xml url URL url = new URL( xmlFile ); // create the xml document d = new Document(); InputStream instream = null; d.setCaseInsensitive(caseInsensitive); d.setLoadExternal(loadexternal); // load and parse the document d.load(url); //garbage collection System.gc(); } catch (Exception e) { System.out.println(e); } //display our music document if (d != null) { setLayout( new BorderLayout() ); Music musicDocument = new Music(d, rowWidth); add( "Center", musicDocument ); } } } // locals int rowWidth ; String xmlFile ; boolean caseInsensitive = false; boolean loadexternal = true ; } /* * Our MusicML lightweight */ class Music extends Canvas{ /* * local variables */ ElementImpl e = null ; /* * staff cursors */ int[] locx = new int[2] ; int[] locy = new int[2] ; /* * size variables * a lot of sizing is done relatively to the linespacing parameter */ int rowheight = 200 ; // spacing between 2 musicrows int rowlength = 600 ; // default length int linespacing = 6 ; // space between to lines on a staff int notespacing = 3 ; // space between to successive notes int innerspace = 80 ; // space between first and second staff int stok = 20 ; // size of the line attached to a single note Vector coordinates = null ; // coordinate memory for beams int lineStart_x = 0 ; int lineStart_y = 0 ; boolean first ; boolean treble ; boolean doublesize = false ; int pos = 0 ; int factor2 ; boolean dot ; int maxYPos ; /* * Fonts */ Font textFont = new Font( "Arial", Font.BOLD, 10 ); Font dynamicsFont = new Font( "Arial", Font.ITALIC, 14 ); /* * constructor */ public Music( ElementImpl e, int rowlength ){ this.e = e ; this.rowlength = rowlength; setBackground( Color.white ); } /* * paint, draw the complete document */ public void paint( Graphics g ){ if( e != null ){ // several inits locx[0] = 0; locx[1] = 0; locy[0] = 30; locy[1] = 30+innerspace; first = true; treble = false; g.setFont( textFont ); // display the Element implementation displayTree( g, e, false, false ); } } /* * displayTree, reads the entire Element Implementation * and draws it on the Graphics input. */ public void displayTree( Graphics lg, ElementImpl e, boolean chordpending, boolean beampending ){ boolean whole = false; if( e.getTagName() != null ){ /***************************************************** * * * process the tags defined in the DTD * * * *****************************************************/ /********************** * element * **********************/ if( e.getTagName().getName().equals("musicrow") ){ locx[0] = 0; locx[1] = 0; doublesize = false; if( !first ){ locy[0] = locy[0] + rowheight; locy[1] = locy[1] + rowheight; } else { first = false; } for( int i=0; i<5; i++){ lg.drawLine( locx[0], locy[0]+i*linespacing, locx[0]+rowlength, locy[0]+i*linespacing ); } if( e.getAttribute("size").toString().equals("two") ){ doublesize = true; for( int i=0; i<5; i++){ lg.drawLine( locx[1], locy[1] + i*linespacing, locx[1]+rowlength, locy[1] + i*linespacing ); } } // begin and end vertical bar lg.drawLine( locx[0], locy[0], locx[0], locy[0]+innerspace + 4*linespacing ); lg.drawLine( locx[0]+rowlength, locy[0], locx[0]+rowlength, locy[0]+innerspace + 4*linespacing ); } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("entrypart") ){ pos = 0; if( e.getAttribute("position").toString().equals("two") ){ pos = 1; } locx[pos] += 5; if( e.getAttribute("cleff").toString().equals("bass") ){ drawKey(locx[pos], locy[pos]-3*notespacing, true, lg); } else { if( e.getAttribute("cleff").toString().equals("treble") ){ drawKey(locx[pos], locy[pos], false, lg); } } locx[pos] +=15; } /************************ * element * ************************/ if( e.getTagName().getName().equals("subsegment") ){ pos = 0; if( e.getAttribute("position").toString().equals("two") ){ pos = 1; } } /************************************** * element , sharp or flat * **************************************/ if( e.getTagName().getName().equals("molkruis") ){ locx[pos] += 7; String level = "zero"; if( e.getAttribute("level") != null ){ level = e.getAttribute("level").toString(); } String name = "g"; if( e.getAttribute("name") != null ){ name = e.getAttribute("name").toString(); } int type = 0; String what = e.getAttribute("notetype").toString(); if( what.equals("sharp") ){ type = 1; } factor2 = 0; dot = true; int ypos = 0; ypos = calcYPosition( level, name ); drawMolKruis( locx[pos], ypos, type, lg ); } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("rest") ){ locx[pos] += 15; drawRest(lg, locx[pos], locy[pos], e.getAttribute("size").toString() ); } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("chord") ){ locx[pos] += 15; chordpending = true; maxYPos = locy[pos]; } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("beam") ){ beampending = true; coordinates = new Vector(); } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("note") ){ if( ! chordpending ){ locx[pos] += 15; } String level = "zero"; if( e.getAttribute("level") != null ){ level = e.getAttribute("level").toString(); } String beat = "quarter"; if( e.getAttribute("beat") != null ){ beat = e.getAttribute("beat").toString(); } String notetype = ""; if( e.getAttribute("notetype") != null ){ notetype = e.getAttribute("notetype").toString(); } String name = "g"; if( e.getAttribute("name") != null ){ name = e.getAttribute("name").toString(); } String dynamics = ""; if( e.getAttribute("dynamics") != null ){ dynamics = e.getAttribute("dynamics").toString(); } factor2 = 0; dot = true; int ypos = 0; ypos = calcYPosition( level, name ); // position for text above if( !chordpending ){ maxYPos = ypos; } else { if( ypos < maxYPos ){ maxYPos = ypos; } } // first if there is a type draw it if( notetype.equals("sharp") ){ //# drawMolKruis( locx[pos], ypos, 1, lg ); locx[pos] += 7; } else if ( notetype.equals("flat") ){ //mol drawMolKruis( locx[pos], ypos, 0, lg ); locx[pos] += 7; } //draw supporting lines for high notes if( factor2 < 0 ){ int startshift = notespacing; if( dot ){ startshift = linespacing; } for( int i=ypos+startshift; i= 0 ){ int startshift = notespacing; if( dot ){ startshift = 0; } for( int i=ypos+startshift; i>locy[pos]; i -= linespacing ){ lg.drawLine( locx[pos]-2, i, locx[pos]+linespacing+2, i ); } } if( beat.equals("quarter") || beat.equals("eighth") || beat.equals("sixteenth") || beat.equals("threequarter") ){ lg.fillOval( locx[pos], ypos, linespacing,linespacing ); if( beat.equals("threequarter") ){ // dot means note is between 2 lines // not dot means note is on the line if( dot ){ lg.fillRect( locx[pos]+8, ypos+2, 2,2 ); } else { lg.fillRect( locx[pos]+8, ypos, 2,2 ); } } } else if ( beat.equals("half") ){ lg.drawOval( locx[pos], ypos, linespacing,linespacing ); } else if ( beat.equals("whole") ){ whole = true; lg.drawOval( locx[pos], ypos, linespacing,linespacing ); lg.drawOval( locx[pos]+1, ypos+1, linespacing-2,linespacing-2 ); } // down or up ? // beams, and chords are allways drawn down if( chordpending || beampending || (ypos < locy[pos]) ){ lineStart_x = locx[pos]; lineStart_y = ypos+notespacing; // draw line for non beams and non whole notes if( !beampending && !whole ){ lg.drawLine( lineStart_x, lineStart_y, lineStart_x, lineStart_y+stok ); // draw single flag if( beat.equals("eighth") ){ drawFlag( lg, lineStart_x, lineStart_y+stok, false ); } // draw double flag if( beat.equals("sixteenth") ){ drawFlag( lg, lineStart_x, lineStart_y+stok, false ); drawFlag( lg, lineStart_x, lineStart_y+stok-2*notespacing, false ); } } } else { lineStart_x = locx[pos]+linespacing; lineStart_y = ypos+notespacing; // draw line for non beam if( !beampending && !whole ){ lg.drawLine( lineStart_x, lineStart_y, lineStart_x, lineStart_y-stok ); // draw single flag if( beat.equals("eighth") ){ drawFlag( lg, lineStart_x, lineStart_y-stok, true ); } // draw double flag if( beat.equals("sixteenth") ){ drawFlag( lg, lineStart_x, lineStart_y-stok, true ); drawFlag( lg, lineStart_x, lineStart_y-stok+2*notespacing, true ); } } } if( beampending ){ // store x,y coordinate coordinates.addElement( new coordinate( lineStart_x, lineStart_y ) ); } if( !dynamics.equals("") ){ Font savefont = lg.getFont(); lg.setFont( dynamicsFont ); lg.drawString( dynamics, locx[pos], locy[pos]+50 ); lg.setFont( savefont ); } } } /******************************************************************** * recursively displaying the subtree * ********************************************************************/ for (ElementEnumeration en = new ElementEnumeration(e); en.hasMoreElements(); ){ ElementImpl child = (ElementImpl)en.nextElement(); displayTree(lg, child, chordpending, beampending); } /****************************************************************** / / \ EEEE L EEEE M M EEEE N N TTT SSSS / / \ E L E M M M E NN N T S / / \ EE L EE M M EE N NN T SSS \ / / E L E M M E N NN T S \ / / EEEE LLLL EEEE M M EEEE N N T SSSS ******************************************************************/ // tags if( e.getTagName() != null ){ /***************************** * element * *****************************/ if( e.getTagName().getName().equals("entrypart") ){ locx[pos] += 20; String rythm = e.getAttribute("rythm").toString(); Font saveFont = lg.getFont(); lg.setFont( new Font( saveFont.getName(), Font.BOLD, saveFont.getSize()+3 ) ); if( rythm.equals("threequarter") ){ lg.drawString( "3",locx[pos], locy[pos] + 4 *notespacing ); lg.drawString( "4",locx[pos], locy[pos] + 8 *notespacing ); } if( rythm.equals("twoquarter") ){ lg.drawString( "3",locx[pos], locy[pos] + 4 *notespacing ); lg.drawString( "4",locx[pos], locy[pos] + 8 *notespacing ); } if( rythm.equals("sixeight") ){ lg.drawString( "6",locx[pos], locy[pos] + 4 *notespacing ); lg.drawString( "8",locx[pos], locy[pos] + 8 *notespacing ); } if( rythm.equals("half") ){ lg.drawString( "1",locx[pos], locy[pos] + 4 *notespacing ); lg.drawString( "2",locx[pos], locy[pos] + 8 *notespacing ); } if( rythm.equals("fivequarter") ){ lg.drawString( "5",locx[pos], locy[pos] + 4 *notespacing ); lg.drawString( "4",locx[pos], locy[pos] + 8 *notespacing ); } lg.setFont( saveFont ); locx[pos] += 15; } /***************************** * element * *****************************/ // draw text above if( e.getTagName().getName().equals("chord") || e.getTagName().getName().equals("note") ){ if( e.getAttribute("info") != null ){ String info = e.getAttribute("info").toString(); //offset -- distance between top note and text maxYPos -= 6; if( maxYPos > locy[pos]-2*linespacing ){ maxYPos = locy[pos]-2*linespacing; } lg.drawString( info, locx[pos], maxYPos ); } } /*********************** * element * ***********************/ // draw vertical line en shift xposition to max of both if( e.getTagName().getName().equals("segment") ){ if( locx[0] > locx[1] ){ locx[0] += 15; locx[1] = locx[0]; } else { locx[1] += 15; locx[0] = locx[1]; } lg.drawLine( locx[0], locy[0], locx[0], locy[0]+innerspace + 4*linespacing ); } /*********************** * element * ***********************/ if( e.getTagName().getName().equals("beam") ){ beampending = false; int maxy = 0; for( int i=0; i maxy ){ maxy = ((coordinate)coordinates.elementAt( i )).y; } } String size = "single"; if( e.getAttribute("size") != null ){ size = e.getAttribute("size").toString(); if( size.equals("double") ){ maxy += 7; } if( size.equals("triple") ){ maxy += 14; } } for( int i=0; i