/***
 *	----------------------------
 *	jMusician Namespace
 *	----------------------------
 */
jMusician 						= {};

/***
 *	========================================================
 *	TODO :
 *	--------------------------------------------------------
 *	- Loose arrows when music has been played at least once
 *	----------------------- NOT IN JS ----------------------
 *	- Connects
 *	- Trills
 *	- Pick-up Notes
 *	- Crescendo/Decrescendo
 *	---------------- NOT IN JS | NOT IN WAV ----------------
 *	- Time Signatures
 *	- Dots													// Use the . sign ( quar. )
 *	- Ties													// Use the plus sign ( quar+eighth )
 *	- Slurs
 *	- Repeats
 *	- Triplets
 *	- Chords
 *	------------------- IN JS, NOT IN WAV ------------------
 *	- Clef
 *	- Staccato/Long/etc.
 *	- Volume
 *	========================================================
 */

	/***
	 *	----------------------------
	 *	Global Storage
	 *	----------------------------
	 */
		
		/***
		 *	cursorAt
		 *	----------------------------
		 *	Holds current location of
		 *	the cursor.
		 *	----------------------------
		 */
		jMusician.cursorAt 				= undefined;
		
		/***
		 *	cursorX
		 *	----------------------------
		 *	Holds current X location of
		 *	the cursor.
		 *	----------------------------
		 */
		jMusician.cursorX				= undefined;
		
		/***
		 *	cursorY
		 *	----------------------------
		 *	Holds current Y location of
		 *	the cursor.
		 *	----------------------------
		 */
		jMusician.cursorY				= 31;
		
		/***
		 *	currentBar
		 *	----------------------------
		 *	Holds number of the current
		 *	measure.
		 *	----------------------------
		 */
		jMusician.currentBar 			= 1;
			
		/***
		 *	currentKey
		 *	----------------------------
		 *	Holds the current key of the
		 *	piece.
		 *	----------------------------
		 */
		jMusician.currentKey 			= undefined;
		
		/***
		 *	currentKey
		 *	----------------------------
		 *	Holds the current mods to
		 *	each note in the current
		 *	measure.
		 *	----------------------------
		 */
		jMusician.currentMods			= { A: undefined,	B: undefined,	C: undefined,	D: undefined,	E: undefined,	F: undefined,	G: undefined };
				
		/***
		 *	currentKey
		 *	----------------------------
		 *	Holds the current accent of
		 *	the next note.
		 *	----------------------------
		 */
		jMusician.currentAccent			= undefined;
		
		/***
		 *	currentKey
		 *	----------------------------
		 *	Holds the current duration
		 *	selected.
		 *	----------------------------
		 */
		jMusician.currentDuration		= 'whole';
		
		/***
		 *	currentClef
		 *	----------------------------
		 *	Holds the current clef of
		 *	the piece.
		 *	----------------------------
		 */
		jMusician.currentClef			= 'g';
			
		/***
		 *	items
		 *	----------------------------
		 *	Holds pointers to all of the
		 *	items placed on the sheet.
		 *	----------------------------
		 */
		jMusician.items					= [];
			
		/***
		 *	music
		 *	----------------------------
		 *	Holds the stored music
		 *	already written to the page.
		 *	----------------------------
		 */
		jMusician.music					= [];
		
		jMusician.title					= '{ New Song 01 }';
		jMusician.instrument			= '{ Vocals }';
		jMusician.instrumentKey			= 'C';
		jMusician.composer				= 'C';
			
		jMusician.onReady				= function() {};
			
	/***
	 *	----------------------------
	 *	Global Settings
	 *	----------------------------
	 */
		
		/***
		 *	keys
		 *	----------------------------
		 *	Holds the global settings
		 *	for all of the major/minor
		 *	key scales.
		 *	----------------------------
		 */
		jMusician.keys 					= {
											'C'		: {	A: 0,	B: 0,	C: 0,	D: 0,	E: 0,	F: 0,	G: 0,	type: 'flat' ,	width: 0	} ,
											'F'		: {	A: 0,	B: -1,	C: 0,	D: 0,	E: 0,	F: 0,	G: 0,	type: 'flat' ,	width: 10	} ,
											'Bb'	: {	A: 0,	B: -1,	C: 0,	D: 0,	E: -1,	F: 0,	G: 0,	type: 'flat' ,	width: 18	} ,
											'Eb'	: {	A: -1,	B: -1,	C: 0,	D: 0,	E: -1,	F: 0,	G: 0,	type: 'flat' ,	width: 26	} ,
											'Ab'	: {	A: -1,	B: -1,	C: 0,	D: -1,	E: -1,	F: 0,	G: 0,	type: 'flat' ,	width: 34	} ,
											'Db'	: {	A: -1,	B: -1,	C: 0,	D: -1,	E: -1,	F: 0,	G: -1,	type: 'flat' ,	width: 42	} ,
											'Gb'	: {	A: -1,	B: -1,	C: -1,	D: -1,	E: -1,	F: 0,	G: -1,	type: 'flat' ,	width: 50	} ,
											'Cb'	: {	A: -1,	B: -1,	C: -1,	D: -1,	E: -1,	F: -1,	G: -1,	type: 'flat' ,	width: 60	} ,
											'G'		: {	A: 0,	B: 0,	C: 0,	D: 0,	E: 0,	F: 1,	G: 0,	type: 'sharp' ,	width: 10	} ,
											'D'		: {	A: 0,	B: 0,	C: 1,	D: 0,	E: 0,	F: 1,	G: 0,	type: 'sharp' ,	width: 18	} ,
											'A'		: {	A: 0,	B: 0,	C: 1,	D: 0,	E: 0,	F: 1,	G: 1,	type: 'sharp' ,	width: 26	} ,
											'E'		: {	A: 0,	B: 0,	C: 1,	D: 1,	E: 0,	F: 1,	G: 1,	type: 'sharp' ,	width: 34	} ,
											'B'		: {	A: 1,	B: 0,	C: 1,	D: 1,	E: 0,	F: 1,	G: 1,	type: 'sharp' ,	width: 42	} ,
											'F#'	: {	A: 1,	B: 0,	C: 1,	D: 1,	E: 1,	F: 1,	G: 1, 	type: 'sharp' ,	width: 50	} ,
											'C#'	: {	A: 1,	B: 1,	C: 1,	D: 1,	E: 1,	F: 1,	G: 1,	type: 'sharp' ,	width: 60	}
										};
										
		/***
		 *	transpositions
		 *	----------------------------
		 *	Holds the global settings
		 *	for all of the transposition
		 *	keys.
		 *	----------------------------
		 */						
		jMusician.traspositions			= {
											'Bb'	: -2 ,
											'Eb'	: 3
										};
			
		/***
		 *	positions
		 *	----------------------------
		 *	Holds the vertical positions
		 *	of all of the notes in the
		 *	scale.
		 *	----------------------------
		 */
		jMusician.positions				= [ {} , {} ,
											{	A: 55,	B: 52,	C: 70,	D: 67,	E: 64,	F: 61,	G: 58	} ,
											{	A: 34,	B: 31,	C: 49,	D: 46,	E: 43,	F: 40,	G: 37	} ,
											{	A: 13,	B: 10,	C: 28,	D: 25,	E: 22,	F: 19,	G: 16	} ,
											{	A: -8,	B: -11,	C: 7,	D: 4,	E: 1,	F: -2,	G: -5	}
										];
			
		/***
		 *	lines
		 *	----------------------------
		 *	Holds the number of lines
		 *	above/below the scale every
		 *	note needs.
		 *	----------------------------
		 */
		jMusician.lines					= [ {} , {} ,
											{	A: -2,	B: -1,	C: -4,	D: -4,	E: -3,	F: -3,	G: -2	} ,
											{	A: 0,	B: 0,	C: -1,	D: 0,	E: 0,	F: 0,	G: 0	} ,
											{	A: 1,	B: 1,	C: 0,	D: 0,	E: 0,	F: 0,	G: 0	} ,
											{	A: 4,	B: 5,	C: 2,	D: 2,	E: 3,	F: 3,	G: 4	}
										];
			
		/***
		 *	bgTop
		 *	----------------------------
		 *	Holds the vertical position
		 *	of the notes in the images
		 *	for each duration.
		 *	----------------------------
		 */
		jMusician.bgTop					= { whole: 0 , half: -23 , quar: -46 , eighth: -69 , sixth: -92 };
			
		/***
		 *	bgTop
		 *	----------------------------
		 *	Holds the horizontal
		 *	position of the notes in the
		 *	images for each duration.
		 *	----------------------------
		 */
		jMusician.bgLeft				= { whole: 0 , half: -4 , quar: -7 , eighth: -8 , sixth: -8 };
			
		/***
		 *	widths
		 *	----------------------------
		 *	Holds the width of the notes
		 *	in the images for each
		 *	duration.
		 *	----------------------------
		 */
		jMusician.widths				= { whole: 32 , half: 24 , quar: 18 , eighth: 16 , sixth: 16 };
		
		
		
		jMusician.createDOMArray		= function( nodes ) {
											var attrs		= nodes[1];
											var ae			= jMusician.attachEvent;
											var cda			= jMusician.createDOMArray;
											var el			= document.createElement( nodes[0] );
												el.tabIndex = -1;
											for( var attr in attrs ) {
												if( attr.toString() == 'styles' ) {
													var styles = attrs[attr];
													for( var style in styles )
														el.style[style] = styles[style];
												} else if( attr.toString() == 'events' ) {
													var events = attrs[attr];
													for( var e in events )
														ae( el , e.toString() , events[e] );
												} else if( attr.toString() == 'register' ) {
													var reg = attrs[attr];
													if( reg.owner != undefined && reg.object != undefined )
														reg.owner[reg.object] = el;
												} else if( attr.toString() == 'object' ) {
													object = attrs[attr];
												} else {
													el[attr] = attrs[attr];
												}
											}
											if( nodes.length >= 3 ) {
												for(var index=2 ; index<nodes.length ; index++ ) {
													el.appendChild( cda( nodes[index] ) );
												}
											}
											return el;
										};
		
		jMusician.attachEvent			= function( id , evt , proc , capture ) {
											if( typeof( id ) == 'string' )				var el = document.getElementById(id);
											else										var el = id;
											try {
												if (window.attachEvent)					el.attachEvent( 'on' + evt , proc );
												else if (window.addEventListener)		el.addEventListener( evt , proc , ( capture != undefined ? capture : false ) );
											} catch(e) {
											}
										};
										
		jMusician.transpose				= function( note ) {
		};
										
		jMusician.sharpNote				= function( note ) {
											var l	= note.note;
											var o	= note.register;
											switch( l ) {
												// Natural		// Sharp		// Flat			// Letter		// Octave		// Break
												case 'C' :		case 'B#' :						l = 'C#';						break;
																case 'C#' :		case 'Db' :		l = 'D';						break;
												case 'D' :										l = 'D#';						break;
																case 'D#' :		case 'Eb' :		l = 'E';						break;
												case 'E' :						case 'Fb' :		l = 'F';						break;
												case 'F' :		case 'E#' :						l = 'F#';						break;
																case 'F#' :		case 'Gb' :		l = 'G';						break;
												case 'G' :										l = 'G#';						break;
																case 'G#' :		case 'Ab' :		l = 'A';						break;
												case 'A' :										l = 'A#';						break;
																case 'A#' :		case 'Bb' :		l = 'B';						break;
												case 'B' :						case 'Cb' :		l = 'C';		o++;			break;
												default :																		break;
											}
											return { note: l , register: o };
										};
		
		jMusician.flatNote				= function( note ) {
											var l	= note.note;
											var o	= note.register;
											switch( l ) {
												// Natural		// Sharp		// Flat			// Letter		// Octave	// Break
												case 'C' :		case 'B#' :						l = 'B';		o--;		break;
																case 'C#' :		case 'Db' :		l = 'C';					break;
												case 'D' :										l = 'C#';					break;
																case 'D#' :		case 'Eb' :		l = 'D';					break;
												case 'E' :						case 'Fb' :		l = 'D#';					break;
												case 'F' :		case 'E#' :						l = 'E';					break;
																case 'F#' :		case 'Gb' :		l = 'F';					break;
												case 'G' :										l = 'F#';					break;
																case 'G#' :		case 'Ab' :		l = 'G';					break;
												case 'A' :										l = 'G#';					break;
																case 'A#' :		case 'Bb' :		l = 'A';					break;
												case 'B' :						case 'Cb' :		l = 'A#';					break;
												default :																	break;
											}
											return { note: l , register: o };
										};
			
		jMusician.highlightNote			= function( i ) {
											k = -1;
											this.unhighlightNotes();
											for( var j=0 ; j<this.items.length ; j++ ) {
												if( this.items[j].note != undefined ) {
													k++;
													if( k == i )
														this.items[j].node.className += ' highlight';
												}
											}
										};
			
		jMusician.unhighlightNotes		= function() {
											for( var j=0 ; j<this.items.length ; j++ ) {
												if( this.items[j].note != undefined && this.items[j].node.className.indexOf( ' highlight' ) != -1 )
													this.items[j].node.className = this.items[j].node.className.replace( / highlight/g , '' );
											}
										};
			
	/***
	 *	----------------------------
	 *	Global Mouse Methods
	 *	----------------------------
	 */
		
		/***
		 *	selectItem
		 *	----------------------------
		 *	Selects the given item.
		 *	----------------------------
		 */
		jMusician.selectItem			= function( el ) {
											if( this.cursorAt != undefined && this.cursorAt != 'end' )
												this.deselectItem( this.cursorAt );
											el.firstChild.className = 'cursor active';
											el.firstChild.style.top = ( ( this.cursorY + 2 ) + 'px' );
											this.cursorAt = el;
											this.cursorX = eval( el.id.replace( 'jM_item_' , '' ) );
										};
		
		/***
		 *	deselectItem
		 *	----------------------------
		 *	Deselects the given item.
		 *	----------------------------
		 */
		jMusician.deselectItem			= function( el ) {
											el.firstChild.className = 'cursor';
											this.cursorAt = undefined;
											this.cursorX = undefined;
										};
		
	/***
	 *	----------------------------
	 *	Global Key Methods
	 *	----------------------------
	 */
		
		/***
		 *	getKey
		 *	----------------------------
		 *	Handles all of the keyboard
		 *	input.
		 *	----------------------------
		 */
		jMusician.getKey				= function(e) {
											if( !e ) var e = window.event;
											if( e.keyCode ) var k = e.keyCode;
											else			var k = e.which;
											switch( k ) {
												case 37:																						// Left - Select previous item
													jMusician.selectPrevious();
													return false;
													break;
												case 39:																						// Right - Select next item
													jMusician.selectNext();
													return false;
													break;
												case 38:																						// Up - Move cursor up 3 px
													if( jMusician.cursorY >= -5 )
														jMusician.cursorY -= 3;
													if( jMusician.cursorAt != undefined ) {
														jMusician.selectItem( jMusician.cursorAt );
													} else {
														jMusician.selectItem( document.getElementById('added').firstChild );
													}
													return false;
													break;
												case 40:																						// Down - Move cursor down 3 px
													if( jMusician.cursorY <= 55 )
														jMusician.cursorY += 3;
													if( jMusician.cursorAt != undefined ) {
														jMusician.selectItem( jMusician.cursorAt );
													} else {
														jMusician.selectItem( document.getElementById('added').firstChild );
													}
													return false;
													break;
												case 8:																							// Backspace
													if( jMusician.cursorX == 0 ) return;
													var items = [];
													for( var i=0 ; i<jMusician.items.length ; i++ ) {
														if( i != jMusician.cursorX - 1 )	items.push( jMusician.items[i] );
														else								jMusician.items[i].remove();
													}
													jMusician.items = items;
													jMusician.reload();
													jMusician.selectItem( document.getElementById('added').childNodes[ jMusician.cursorX - 1 ] );
													return false;
													break;
												case 46:																						// Delete
													if( jMusician.cursorX == jMusician.items.length ) return;
													var items = [];
													for( var i=0 ; i<jMusician.items.length ; i++ ) {
														if( i != jMusician.cursorX )		items.push( jMusician.items[i] );
														else								jMusician.items[i].remove();
													}
													jMusician.items = items;
													jMusician.reload();
													jMusician.selectItem( document.getElementById('added').childNodes[ jMusician.cursorX ] );
													return false;
													break;
												case 27:																						// ESC - Unselect Item
													if( jMusician.cursorAt != undefined )
														jMusician.deselectItem( jMusician.cursorAt );
													return false;
													break;
												case 13:																						// Enter
													var register, note;
													for( var i=0 ; i<jMusician.positions.length ; i++ ) {
														for( var j in jMusician.positions[i] ) {
															if( jMusician.positions[i][j] == jMusician.cursorY ) {
																register = i;
																note = j;
															}
														}
													}
													jMusician.insertNote( register , note , jMusician.currentDuration , jMusician.currentAccent , false );
													return false;
													break;
												case 32:																						// Space - Rest Note
													// TODO :
													return false;
													break;
												case 49:																						// 1 - Whole
												case 97:
													jMusician.updateDuration('whole');
													return false;
													break;
												case 50:																						// 2 - Half
												case 98:
													jMusician.updateDuration('half');
													return false;
													break;
												case 51:																						// 3 - Quarter
												case 99:
													jMusician.updateDuration('quar');
													return false;
													break;
												case 52:																						// 4 - Eighth
												case 100:
													jMusician.updateDuration('eighth');
													return false;
													break;
												case 53:																						// 5 - Sixteenth
												case 101:
													jMusician.updateDuration('sixth');
													return false;
													break;
												case 78:																						// N - Natural
													return false;
													break;
												case 83:																						// S - Sharp
													return false;
													break;
												case 70:																						// F - Flat
													return false;
													break;
												case 84:																						// T - Tempo
													return false;
													break;
												case 190:																						// . - Dotted
													return false;
													break;
												case 9:																							// Tab - Bars
													var								type = 'minor';
													if( e.shiftKey )				type = 'major';
												//	if( e.ctrlKey )					type = 'srepeat';
												//	if( e.ctrlKey && e.shiftKey )	type = 'erepeat';
													jMusician.insertBar( type );
													return false;
													break;
												default:
													console.log(k);
													break;
											}
										};
		
		/***
		 *	selectNext
		 *	----------------------------
		 *	Selects the next item.
		 *	----------------------------
		 *	RIGHT ARROW
		 *	----------------------------
		 */
		jMusician.selectNext			= function() {
											if( this.cursorAt == undefined ) {
												this.selectItem( document.getElementById('added').firstChild );
											} else if( this.cursorAt.nextSibling != undefined ) {
												this.selectItem( this.cursorAt.nextSibling );
											} else {
												// TODO
											}
										};
		
		/***
		 *	selectPrevious
		 *	----------------------------
		 *	Selects the previous item.
		 *	----------------------------
		 *	LEFT ARROW
		 *	----------------------------
		 */
		jMusician.selectPrevious		= function() {
											if( this.cursorAt == undefined ) {
												this.selectItem( document.getElementById('added').lastChild );
											} else if( this.cursorAt.previousSibling != undefined ) {
												this.selectItem( this.cursorAt.previousSibling );
											}
										};
			
	/***
	 *	----------------------------
	 *	Global Update Methods
	 *	----------------------------
	 */
			
		/***
		 *	setTitle
		 *	----------------------------
		 *	Sets the title of the piece.
		 *	----------------------------
		 */
		jMusician.setTitle				= function( title ) { document.getElementById('title').innerHTML = title; this.title = title; };
			
		/***
		 *	setInstrument
		 *	----------------------------
		 *	Sets the instrument and its
		 *	key.
		 *	----------------------------
		 */
		jMusician.setInstrument			= function( instrument , key ) { document.getElementById('subtitle').innerHTML = key + ' ' + instrument; this.instrument = instrument; this.instrumentKey = key; };
			
		/***
		 *	setInstrument
		 *	----------------------------
		 *	Sets the instrument and its
		 *	key.
		 *	----------------------------
		 */
		jMusician.setComposer			= function( composer ) { document.getElementById('composer').innerHTML = 'Composed by: ' + composer; this.composer = composer; };
			
		/***
		 *	setClef
		 *	----------------------------
		 *	Sets the clef of the piece.
		 *	----------------------------
		 */
		jMusician.setClef				= function( clef ) {};
		/* TODO */ 
		
		/***
		 *	updateDuration
		 *	----------------------------
		 *	Sets the currently selected
		 *	duration in the toolbar.
		 *	----------------------------
		 */
		jMusician.updateDuration		= function( dur ) {
											document.getElementById('dur_' + this.currentDuration).className = 'btn ';
											this.currentDuration = dur;
											document.getElementById('dur_' + this.currentDuration).className = 'btn invert';
										};
										
		jMusician.updateClef			= function( clef ) {
											document.getElementById('clef_' + this.currentClef).className = 'btn ';
											this.currentClef = clef;
											document.getElementById('clef_' + this.currentClef).className = 'btn invert';
											this.reload();
										};
											
		
	/***
	 *	----------------------------
	 *	Global Add Methods
	 *	----------------------------
	 */
			
		/***
		 *	setKey
		 *	----------------------------
		 *	Adds a new key.
		 *	----------------------------
		 */
		jMusician.setKey				= function( key ) { this.items.push( new jMusician.Key( key ) ); this.reload(); };
			
		/***
		 *	setTempo
		 *	----------------------------
		 *	Sets the tempo.
		 *	----------------------------
		 */
		jMusician.setTempo				= function( tempo ) { this.items.push( new jMusician.Tempo( tempo ) ); this.reload(); };
			
		/***
		 *	setVolume
		 *	----------------------------
		 *	Sets the volume.
		 *	----------------------------
		 */
		jMusician.setVolume				= function( volume ) { this.items.push( new jMusician.Volume( volume ) ); this.reload(); };
			
		/***
		 *	addNote
		 *	----------------------------
		 *	Adds a new note.
		 *	----------------------------
		 */
		jMusician.addNote				= function( register , note , duration , accent , hold ) { this.items.push( new jMusician.Note( register , note , duration , accent , hold ) ); this.reload(); };
			
		/***
		 *	addBar
		 *	----------------------------
		 *	Adds a new standard bar.
		 *	----------------------------
		 */
		jMusician.addBar				= function( type ) { this.items.push( new jMusician.Bar( type ) ); this.reload(); };
		
	/***
	 *	----------------------------
	 *	Toolbar Insert Methods
	 *	----------------------------
	 */
			
		/***
		 *	insertItem
		 *	----------------------------
		 *	Inserts a new item.
		 *	----------------------------
		 */
		jMusician.insertItem			= function( node ) {
											if( this.cursorAt == undefined ) return;
											var items = [];
											for( var i=0 ; i<this.cursorX ; i++ )
												items.push( this.items[i] );
											var register, note;
											for( var i=0 ; i<this.positions.length ; i++ ) {
												for( var j in this.positions[i] ) {
													if( this.positions[i][j] == this.cursorY ) {
														register = i;
														note = j;
													}
												}
											}
											items.push( node );
											for( var i=this.cursorX ; i<this.items.length ; i++ )
												items.push( this.items[i] );
											this.items = items;
											this.reload();
											this.cursorX++;
											this.selectItem( document.getElementById('added').childNodes[ this.cursorX ] );
										};
		
		// TIME SIGNATURE
		
		/***
		 *	insertKey
		 *	----------------------------
		 *	Inserts a new key.
		 *	----------------------------
		 */
		jMusician.insertKey				= function() { if( this.cursorAt == undefined ) return; var key = prompt( 'New Key:' ); if( key != undefined ) this.insertItem( new this.Key( key ) ); };
		
		/***
		 *	insertTempo
		 *	----------------------------
		 *	Inserts a new tempo.
		 *	----------------------------
		 */
		jMusician.insertTempo			= function() { if( this.cursorAt == undefined ) return; var tempo = prompt( 'New Tempo:' ); if( tempo != undefined ) this.insertItem( new this.Tempo( tempo ) ); };
		
		/***
		 *	insertVolume
		 *	----------------------------
		 *	Inserts a new volume.
		 *	----------------------------
		 */
		jMusician.insertVolume			= function( volume ) { this.insertItem( new this.Volume( volume ) ); };
		
		/***
		 *	insertNote
		 *	----------------------------
		 *	Inserts a new note.
		 *	----------------------------
		 */
		jMusician.insertNote			= function( register , note , duration , accent , hold ) { this.insertItem( new this.Note( register , note , duration , accent , hold ) ); };
		
		/***
		 *	insertBar
		 *	----------------------------
		 *	Inserts a new bar.
		 *	----------------------------
		 */
		jMusician.insertBar				= function( type ) { this.insertItem( new this.Bar( type ) ); };
		
	/***
	 *	----------------------------
	 *	Loading Method
	 *	----------------------------
	 */
			
		/***
		 *	reload
		 *	----------------------------
		 *	Reloads needed data.
		 *	----------------------------
		 */
		jMusician.reload				= function() {
			
											this.currentBar		= 1;
											this.currentKey		= undefined;
											this.currentMods	= { A: undefined,	B: undefined,	C: undefined,	D: undefined,	E: undefined,	F: undefined,	G: undefined };
											
											var wav		= [];
											
											wav.push( "@title\t" + this.title );
											wav.push( "@inst\t" + this.instrument );
											wav.push( "@base\t" + this.instrumentKey );
											wav.push( "@comp\t" + this.composer );
											wav.push( "@clef\t" + this.currentClef );
											
											document.getElementById('song').innerHTML		= '';
											
											for( var i=0 ; i<this.items.length ; i++ ) {
												var w = this.items[i].getWAV();
												if( w != null )	wav.push( w );
												document.getElementById('added').appendChild( this.items[i].getHTML( i ) );
											}
											
											document.getElementById('added').appendChild( this.End.getHTML( i ) );
											
											document.getElementById('clef').className		= 'clef clef_' + this.currentClef;
											document.getElementById('clef').style.height	= ( ( document.getElementById('page').offsetHeight ) + 'px' );
											document.getElementById('song').innerHTML		= wav.join("\n");
											
										};
			
		/***
		 *	reload
		 *	----------------------------
		 *	Reloads needed data.
		 *	----------------------------
		 */
		jMusician.clear				= function() {
										this.items = [];
										this.reload();
									};
									
		jMusician.onload			= function() {
			
										document.body.appendChild( jMusician.createDOMArray( [ 'DIV' , { id: 'background' } ] ) );
										
										document.body.appendChild( jMusician.createDOMArray( [ 'INPUT' , { id: 'key_handler' , events: { blur: function() { this.focus(); return false; } } } ] ) );
										
										document.body.appendChild( jMusician.createDOMArray(
											[ 'DIV' , { id: 'jMusician' } ,
											 	[ 'DIV' , { className: 'title' , id: 'title' , innerHTML: '{ Title }' } ] ,
												[ 'DIV' , { className: 'subtitle' , id: 'subtitle' , innerHTML: '{ Instrument }' } ] ,
												[ 'DIV' , { className: 'composer' , id: 'composer' , innerHTML: '{ Composer }' } ] ,
												[ 'TABLE' , { cellPadding: 0 , cellSpacing: 0 , border: 0 , id: 'sheet' } ,
												 	[ 'TBODY' , {} ,
													 	[ 'TR' , {} ,
														 	[ 'TD' , { valign: 'top' , styles: { width: '30px' } } ,
															 	[ 'DIV' , { id: 'clef' , className: 'clef treble' } ]
															] ,
															[ 'TD' , { valign: 'top' } ,
															 	[ 'DIV' , { id: 'page' , className: 'page' } ,
																 	[ 'DIV' , { className: 'start' } ] ,
																	[ 'SPAN' , { id: 'added' } ] ,
																	[ 'DIV' , { className: 'end' } ]
																]
															]
														]
													]
												]
											]
										) );
									
										document.body.appendChild( jMusician.createDOMArray(
											[ 'FORM' , { action: 'javascript:;' , method: 'get' , id: 'form' , events: { submit: function() { return false; } } } ,
											 	[ 'TEXTAREA' , { name: 'song' , id: 'song' } ] ,
											 	[ 'INPUT' , { type: 'hidden' , name: 'channels' , id: 'channels' , value: '1' } ] ,
											 	[ 'INPUT' , { type: 'hidden' , name: 'sampleRate' , id: 'sampleRate' , value: '4024' } ] ,
											 	[ 'INPUT' , { type: 'hidden' , name: 'bitDepth' , id: 'bitDepth' , value: '16' } ] ,
											 	[ 'INPUT' , { type: 'hidden' , name: 'volume' , id: 'volume' , value: '32767' } ] ,
											 	[ 'INPUT' , { type: 'image' , className: 'btn invert' , id: 'dur_whole' , src: './images/buttons/whole.jpg' , events: { click: function() { jMusician.updateDuration('whole'); } } } ] ,
											 	[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'dur_half' , src: './images/buttons/half.jpg' , events: { click: function() { jMusician.updateDuration('half'); } } } ] ,
											 	[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'dur_quar' , src: './images/buttons/quarter.jpg' , events: { click: function() { jMusician.updateDuration('quar'); } } } ] ,
											 	[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'dur_eighth' , src: './images/buttons/eighth.jpg' , events: { click: function() { jMusician.updateDuration('eighth'); } } } ] ,
											 	[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'dur_sixth' , src: './images/buttons/sixteenth.jpg' , events: { click: function() { jMusician.updateDuration('sixth'); } } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'note_natural' , src: './images/buttons/natural.jpg' , styles: { marginLeft: '6px' } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'note_sharp' , src: './images/buttons/sharp.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'note_flat' , src: './images/buttons/flat.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn invert' , id: 'clef_g' , src: './images/buttons/clef_g.jpg' , events: { click: function() { jMusician.updateClef('g'); } } , styles: { marginLeft: '6px' } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'clef_c' , src: './images/buttons/clef_c.jpg' , events: { click: function() { jMusician.updateClef('c'); } } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'clef_f' , src: './images/buttons/clef_f.jpg' , events: { click: function() { jMusician.updateClef('f'); } } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/key.jpg' , events: { click: function() { jMusician.insertKey(); } } , styles: { marginLeft: '6px' } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/tempo.jpg' , events: { click: function() { jMusician.insertTempo(); } } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/four-four.jpg' , styles: { marginLeft: '6px' } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/three-four.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/six-eight.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/full-time.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/cut-time.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/fff.jpg' , styles: { marginLeft: '6px' } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/ff.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/f.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/mf.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/mp.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/p.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/pp.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , src: './images/buttons/ppp.jpg' } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'playButton' , src: './images/buttons/play.jpg' , styles: { marginLeft: '6px' , padding: '2px 4px' } , events: { click: function() { jMusic.play(); } } } ] ,
												[ 'INPUT' , { type: 'image' , className: 'btn' , id: 'stopButton' , src: './images/buttons/stop.jpg' , styles: { padding: '2px 4px' } , events: { click: function() { jMusic.stop(); } } } ]
											]
										) );
			
										document.body.appendChild( jMusician.createDOMArray( [ 'DIV' , { id: 'players' } ] ) );
										
										document.getElementById('playButton').disabled 		= false;
										document.getElementById('stopButton').disabled 		= true;
										document.getElementById('key_handler').onkeydown 	= function(e) { if( jMusician.getKey(e) == false ) return false; };
										document.body.onmousedown 							= function() { document.getElementById('key_handler').focus(); return false; };
										document.getElementById('key_handler').focus();
										
										this.onReady();
										
									};
						
// TIME SIGNATURE

jMusician.End = {
	
	node : undefined ,
	
	getHTML : function( i ) {
		if( this.node == undefined ) {
			this.node = jMusician.createDOMArray(
				[ 'DIV' , { className: 'obj' , events: { click: function() { jMusician.selectItem( this ); } } } ,
					[ 'DIV' , { className: 'cursor' } ]
				]
			);
		}
		return this.node;
	}
	
};
													
/***
 *	----------------------------
 *	jMusician.Key
 *	----------------------------
 */
jMusician.Key = function( key ) {
	
	this.key				= key;
	this.node				= undefined;
	
	this.remove = function() {
		this.getHTML().parentNode.removeChild( this.getHTML() );
		this.node = undefined;
	};
	
	this.getHTML = function( i ) {
		if( this.node == undefined ) {
			if( ( jMusician.currentKey == undefined || jMusician.currentKey == 'C' ) && this.key == 'C' ) {
				this.node = jMusician.createDOMArray(
					[ 'DIV' , { className: 'obj key natural_sharp' , styles: { left: ((jMusician.currentKey==undefined)?('-6px;'):('')) , width: '10px' } , events: { click: function() { jMusician.selectItem( this ); } } } ,
						[ 'DIV' , { className: 'cursor' , styles: { left: ((jMusician.currentKey==undefined)?('3px'):('')) } } ] ,
						[ 'DIV' , { className: 'value' } ]
					]
				);
			} else {
				this.node = jMusician.createDOMArray(
					[ 'DIV' , { className: 'obj key ' +  jMusician.keys[this.key].type , styles: { left: '-6px' , width: jMusician.keys[this.key].width + 'px' } , events: { click: function() { jMusician.selectItem( this ); } } } ,
						[ 'DIV' , { className: 'cursor' , styles: { left: '3px' } } ] ,
						[ 'DIV' , { className: 'value' } ]
					]
				);
			}
		}
		this.node.id = 'jM_item_' + i;
		jMusician.currentKey = this.key;
		return this.node;
	};
	
	this.getWAV = function() {
		return	"@key\t" + this.key;
	};
	
};
										
/***
 *	----------------------------
 *	jMusician.Tempo
 *	----------------------------
 */
jMusician.Tempo = function( tempo ) {
	
	this.tempo				= tempo;
	this.node				= undefined;
	
	this.remove = function() {
		this.getHTML().parentNode.removeChild( this.getHTML() );
		this.node = undefined;
	};
	
	this.getHTML = function( i ) {
		if( this.node == undefined ) {
			this.node = jMusician.createDOMArray(
				[ 'DIV' , { className: 'obj tempo' , events: { click: function() { jMusician.selectItem( this ); } } } ,
					[ 'DIV' , { className: 'cursor' } ] ,
					[ 'DIV' , { className: 'value' , innerHTML: '= ' + this.tempo } ]
				]
			);
		}
		this.node.id = 'jM_item_' + i;
		return this.node;
	};
	
	this.getWAV = function() {
		return	"@tempo\t" + this.tempo;
	};
	
};
										
/***
 *	----------------------------
 *	jMusician.Volume
 *	----------------------------
 */
jMusician.Volume = function( volume ) {
	
	this.volume				= volume;
	this.node				= undefined;
	
	this.remove = function() {
		this.getHTML().parentNode.removeChild( this.getHTML() );
		this.node = undefined;
	};
	
	this.getHTML = function( i ) {
		if( this.node == undefined ) {
			this.node = jMusician.createDOMArray(
				[ 'DIV' , { className: 'obj vol' , events: { click: function() { jMusician.selectItem( this ); } } } ,
					[ 'DIV' , { className: 'cursor' } ] ,
					[ 'DIV' , { className: 'value' } ,
					 	[ 'SPAN' , { innerHTML: this.volume } ]
					]
				]
			);
		}
		this.node.id = 'jM_item_' + i;
		return this.node;
	};
	
	this.getWAV = function() {
		return	"@vol\t" + this.volume;
	};
	
};
										
/***
 *	----------------------------
 *	jMusician.Note
 *	----------------------------
 */
jMusician.Note = function( register , note , duration , accent , hold ) {
	
	if( hold == undefined )	var hold = false;
	
	this.register			= register;
	this.note				= note.substr(0,1);
	this.sign				= note.substr(1,1);
	this.duration			= duration;
	this.accent				= accent;
	this.hold				= hold;
	this.node				= undefined;
	
	document.getElementById('note_natural').className	= 'btn';
	document.getElementById('note_sharp').className		= 'btn';
	document.getElementById('note_flat').className		= 'btn';
	
//	document.getElementById('acc_stac').className		= 'btn';
//	document.getElementById('acc_acc').className		= 'btn';
//	document.getElementById('acc_ten').className		= 'btn';
	
	jMusician.currentAccent = undefined;
	
	if( this.sign == '#' ) {
		this.sign = 'sharp';
	} else if( this.sign == 'b' ) {
		this.sign = 'flat';
	} else if( this.sign == 'n' ) {
		this.sign = 'natural';
	}
	
	if( this.accent == '.' ) {
		this.accent = 'stac';
	} else if( this.accent == '>' ) {
		this.accent = 'acc';
	} else if( this.accent == '-' ) {
		this.accent = 'ten';
	}
	
	this.remove = function() {
		this.getHTML().parentNode.removeChild( this.getHTML() );
		this.node = undefined;
	};
	
	this.getHTML = function( i ) {
		var bg_l = -32;
		if( this.register <= 3 )
			bg_l = 0;
		var w = jMusician.widths[this.duration];
		var l = jMusician.bgLeft[this.duration];
		if( this.sign != '' ) {
			w += 2; l += 2;
			if( this.duration == 'half' ) {
				w += 4; l+= 4;
			}
			if( this.duration == 'quar' ) {
				w += 7; l+= 7;
			}
			if( this.duration == 'eighth' || this.duration == 'sixth' ) {
				w += 8; l+= 8;
			}
		}
		var t = jMusician.positions[this.register][this.note];
		if( this.sign == 'sharp' ) 		t -= 3;
		if( this.sign == 'flat' )		t -= 5;
		if( this.sign == 'natural' )	t -= 3;
		var lt = 0;
		var lh = 0;
		if( jMusician.lines[this.register][this.note] != 0 ) {
			lh = ( ( Math.abs(jMusician.lines[this.register][this.note]) * 6 ) + 1 );
			lt = ( ( jMusician.lines[this.register][this.note] > 0 ) ? ( 25 - lh ) : ( 48 ) )
		}
		if( this.node == undefined ) {
			this.node = jMusician.createDOMArray(
				[ 'DIV' , { className: 'obj note' + ((this.sign!='')?(' note_'+this.sign):('')) , styles: { width: w + 'px' , backgroundPosition: ((this.sign!='')?('0px '+t+'px'):('0px 0px')) } , events: { click: function() { jMusician.selectItem( this ); } } } ,
					[ 'DIV' , { className: 'cursor' } ] ,
					[ 'DIV' , { className: 'lines' , styles: { top: lt + 'px' , height: lh + 'px' , display: ((jMusician.lines[this.register][this.note]==0)?('none'):('block')) } } ] ,
					[ 'DIV' , { className: 'fermata' , styles: { display: ((this.hold==false)?('none'):('block')) } } ] ,
					[ 'DIV' , { className: 'accent' + this.accent + '_' + ((this.register<=3)?('up'):('dn')) , styles: { top: ( jMusician.positions[this.register][this.note] - ((this.register<=3)?(-9):(6)) ) + 'px' , display: ((this.accent==undefined)?('none'):('block')) } } ] ,
					[ 'DIV' , { className: 'value' , styles: { top: ((bg_l==0)?(jMusician.positions[this.register][this.note]-12):(jMusician.positions[this.register][this.note])) + 'px' , left: l + 'px' , backgroundPosition: bg_l + 'px ' + jMusician.bgTop[this.duration] + 'px' } } ]
				]
			);
		}
		this.node.id = 'jM_item_' + i;
		return this.node;
	};
	
	this.getWAV = function() {
		var note 		= this.note;
		var register	= this.register;
		if( jMusician.currentKey != undefined ) {
			if( jMusician.keys[jMusician.currentKey][this.note] == 1 && this.sign != 'natural' ) {
				note		= jMusician.sharpNote( { note: this.note , register: this.register } ).note;
				register	= jMusician.sharpNote( { note: this.note , register: this.register } ).register;
			} else if( jMusician.keys[jMusician.currentKey][this.note] == -1 && this.sign != 'natural' ) {
				note		= jMusician.flatNote( { note: this.note , register: this.register } ).note;
				register	= jMusician.flatNote( { note: this.note , register: this.register } ).register;
			}
		}
		if( jMusician.currentMods[this.note] != undefined ) {
			if( jMusician.currentMods[this.note] == 1 && this.sign != 'natural' ) {
				note		= jMusician.sharpNote( { note: this.note , register: this.register } ).note;
				register	= jMusician.sharpNote( { note: this.note , register: this.register } ).register;
			} else if( jMusician.currentMods[this.note] == -1 && this.sign != 'natural' ) {
				note		= jMusician.flatNote( { note: this.note , register: this.register } ).note;
				register	= jMusician.flatNote( { note: this.note , register: this.register } ).register;
			}
		}
		if( this.sign == 'sharp' ) {
			jMusician.currentMods[this.note] = 1;
			note		= jMusician.sharpNote( { note: this.note , register: this.register } ).note;
			register	= jMusician.sharpNote( { note: this.note , register: this.register } ).register;
		} else if( this.sign == 'flat' ) {
			jMusician.currentMods[this.note] = -1;
			note		= jMusician.flatNote( { note: this.note , register: this.register } ).note;
			register	= jMusician.flatNote( { note: this.note , register: this.register } ).register;
		} else if( this.sign == 'natural' ) {
			jMusician.currentMods[this.note] = 0;
		}
		return	register + "\t" + note + "\t" + this.duration;
	//	TODO :	return	this.register + "\t" + note + "\t" + this.duration + ((this.accent!=undefined)?("\t"+this.accent):(""));
	};
	
};
										
/***
 *	----------------------------
 *	jMusician.Bar
 *	----------------------------
 */
jMusician.Bar = function( type ) {
	
	this.type				= ((type==undefined)?('minor'):(type));
	this.node				= undefined;
	
	this.remove = function() {
		this.getHTML().parentNode.removeChild( this.getHTML() );
		this.node = undefined;
	};
	
	this.getHTML = function( i ) {
		if( this.node == undefined ) {
			this.node = jMusician.createDOMArray(
				[ 'DIV' , { className: 'obj bar bar_' + this.type , events: { click: function() { jMusician.selectItem( this ); } } } ,
					[ 'DIV' , { className: 'cursor' } ] ,
					[ 'DIV' , { className: 'value' } ,
					 	[ 'SPAN' , {} ]
					]
				]
			);
		}
		this.node.id = 'jM_item_' + i;
		this.node.firstChild.nextSibling.firstChild.innerHTML = '&nbsp;' + (++jMusician.currentBar) + '&nbsp;';
		return this.node;
	};
	
	this.getWAV = function() {
		jMusician.currentMods = { A: undefined,	B: undefined,	C: undefined,	D: undefined,	E: undefined,	F: undefined,	G: undefined };
		return	"@bar\t" + this.type + "\t" + jMusician.currentBar;
	};
	
};

window.onload = function() { jMusician.onload(); };