function Tala(name, nAksharas, layoutSpec, predefName) 
{
     /**
      * # of aksharas in tala cycle
      * @type int
      * @private
      */
     this.fAksharaCount = nAksharas;

     /**
      * name of tala
      * @type String
      * @private
      */
     this.fName         = name;

     /**
      * @type Array
      * parts of tala
      * @private
      */
     this.fParts        = new Array();

     /**
      * @type TalaLayoutSpecification
      * layout specification of tala
      */
    this.fLayoutSpec  = layoutSpec;

    /**
     * @type TalaLayout
     * the layout based on the spec
     */
    this.fLayout = null;


    /**
     * return the akshara count
     * @return akshara count
     * @type int
     */
    this.aksharaCount = function() { return this.fAksharaCount; }

    /**
     * return the layout spec
     * @type {TalaLayoutSpecification}
     */
    this.getLayoutSpec = function() { return this.fLayoutSpec; }

    /**
     * return the layout based on the layout spec
     * @type {TalaLayout}
     */
    this.getLayout = function() { return this.fLayout; }

    /**
     * set the layout spec
     * @param {TalaLayoutSpecification} layoutSpec	layour specification
     */
    this.setLayoutSpec = function(layoutSpec) {
	this.fLayoutSpec = layoutSpec;
    }

     /**
      * if not-null the predefined name for this tala
      */
    this.fPredefName = predefName;

     /**
      * return the name
      * @return name of tala
      * @type String
      */
     this.name = function()  { return this.fName; }

     /**
      * return the parts in the tala (a linked list)
      * @return first part in tala - head of linked list
      * @type TalaPart
      */
     this.parts = function()  { return this.fParts; }

     /**
      * add a tala part
      * @param {int}    talaIndex akshara index of part within a cycle
      * @param {GATI}   gati      the gati
      * @param {String} marker	  the tala marker to put out when akshara 
      *                           count of a tala cycle reaches talaIndex
      * @return true if successful, false else
      * @type boolean
      */
     this.addPart = function(talaIndex, gati, marker) {
	if( talaIndex < 0 || talaIndex >= this.fAksharaCount ) return false;
	if( !isValidGati(gati) ) return false;
	this.fParts[this.fParts.length] = new TalaPart(talaIndex,gati,marker);
	return true;
     }

     /**
      * <b>must</b> be called after adding parts
      */
     this.finalizeParts = function(layout) {
	this.fLayout = layout;
     }

     /**
      * get the # of parts in the tala
      * @type int
      */
     this.getPartCount = function() {  return this.fParts.length; }

     /**
      * return a part given its index
      * @type TalaPart
      */
     this.getNthPart = function(talaIndex) {
	if( talaIndex >= 0 && talaIndex < this.fParts.length ) return this.fParts[talaIndex];
	return null;
     }

     /**
      * return the tala part that contains the index talaIndex
      *
      * @param {int} talaIndex	index (akshara) in a tala cycle
      *
      * @return the part containing the index (or null if no such part)
      * @type TalaPart
      */
     this.getPart = function(talaIndex) {
	var i;
	var nIndex, part;
	var parts = this.fParts;
	var nparts = parts.length;
     	for( i = 0; i < nparts; i++ ) {
	    part = parts[i];
	    if( (i+1) < nparts ) nIndex = parts[i+1].fIndex;
	    else	         nIndex = this.fAksharaCount;
	    if( talaIndex >= part.fIndex && talaIndex < nIndex ) 
		return part;
	}
	return null;
     }

     /**
      * return the tala part duration (in aksharas) of the tala part 
      * containing the index talaIndex
      *
      * @param {int} talaIndex	index (akshara) in a tala cycle
      * @return the duration (in aksharas) of the part containing the 
      *         index (or 0 if no such part)
      * @type int
      */
     this.getPartDuration = function(talaIndex) {
	var i;
	var nIndex, part;
     	for( i = 0; i < this.fParts.length; i++ ) {
	    part = this.fParts[i];
	    if( (i+1) < this.fParts.length ) nIndex = this.fParts[i+1].fIndex;
	    else			     nIndex = this.fAksharaCount;
	    if( talaIndex >= part.fIndex && talaIndex < nIndex ) 
		return nIndex - part.fIndex;
	}
	return 0;
     }

     /**
      * return the tala part duration (in aksharas) of the nth tala part 
      *
      * @param {int} n		the tala part
      * @return the duration (in aksharas) of the part containing the 
      *         index (or 0 if no such part)
      * @type int
      */
     this.getNthPartDuration = function(n) {
	if( n < 0 && n >= this.fParts.length ) return 0;

	var nIndex;
	if( n < (this.fParts.length-1))
	    nIndex = this.fParts[n+1].fIndex;
	else
	    nIndex = this.fAksharaCount;
	return nIndex - this.fParts[n].fIndex;
     }


     /**
      * can we switch gati on this tala?
      * This is allowed only all parts of tala are of same gati
      */
     this.canSwitchGati = function() {
	if( this.fParts.length == 0 ) return false;
	var g = this.fParts[0].fGati;
	for(i = 1; i < this.fParts.length; i++ ) {
	    if( this.fParts[i].fGati != g ) return false;
	}
	return true;
     }

     this.switchGati = function(gati) {
	if( !this.canSwitchGati()) {
	    alert("cannot switch gati/nadai with this tala");
	    return false;
	}
	var curgati = this.fParts[0].fGati;
	if( gati == this.fParts[0].fGati ) return true;	// no change
	for(i = 0; i < this.fParts.length; i++ )
	    this.fParts[i].fGati = gati;

	if( this.fLayout != null ) 
	    this.fLayout.switchGati(curgati, gati);
	return true;
     }

     /**
      * override of {@link SongPart#toXML}
      */
    this.toXML = function() {
	if( this.fPredefName ) {
	    var x = XMLUtils.createXMLNode( this.XMLTagName() );
	    x.setAttribute( "predefined", this.fPredefName );
	    x.setAttribute( "layout", this.fLayoutSpec.toXMLAttribVal() );
	    return x;
	}
	return null;
     }
}
/**
 * @class
 * represents a tala and is made up of {@link TalaPart}s, and also a 
 * {@link TalaLayoutSpecification} that specifies how to lay it out
 *
 * @constructor
 * @param {String} name	    name of the tala
 * @param {int}    nAksharas # of aksharas in the tala
 * @param {TalaLayoutSpecification} layourSpec	layour specification
 * @param {String} predefName (optional) if specified the predefined name for tala
 */
@class
represents a tala and is made up of  TalaParts, and also a
TalaLayoutSpecification that specifies how to lay it out


@class represents a tala and is made up of TalaParts and also a TalaLayoutSpecification that specifies how to lay it out
function Tala(name, nAksharas, layoutSpec, predefName) 
{
     this.fAksharaCount = nAksharas;
     this.fName         = name;
     this.fParts        = new Array();
    this.fLayoutSpec  = layoutSpec;
    this.fLayout = null;
    this.aksharaCount = function() { return this.fAksharaCount; }
    this.getLayoutSpec = function() { return this.fLayoutSpec; }
    this.getLayout = function() { return this.fLayout; }
    this.setLayoutSpec = function(layoutSpec) {
	this.fLayoutSpec = layoutSpec;
    }
    this.fPredefName = predefName;
     this.name = function()  { return this.fName; }
     this.parts = function()  { return this.fParts; }
     this.addPart = function(talaIndex, gati, marker) {
	if( talaIndex < 0 || talaIndex >= this.fAksharaCount ) return false;
	if( !isValidGati(gati) ) return false;
	this.fParts[this.fParts.length] = new TalaPart(talaIndex,gati,marker);
	return true;
     }
     this.finalizeParts = function(layout) {
	this.fLayout = layout;
     }
     this.getPartCount = function() {  return this.fParts.length; }
     this.getNthPart = function(talaIndex) {
	if( talaIndex >= 0 && talaIndex < this.fParts.length ) return this.fParts[talaIndex];
	return null;
     }
     this.getPart = function(talaIndex) {
	var i;
	var nIndex, part;
	var parts = this.fParts;
	var nparts = parts.length;
     	for( i = 0; i < nparts; i++ ) {
	    part = parts[i];
	    if( (i+1) < nparts ) nIndex = parts[i+1].fIndex;
	    else	         nIndex = this.fAksharaCount;
	    if( talaIndex >= part.fIndex && talaIndex < nIndex ) 
		return part;
	}
	return null;
     }
     this.getPartDuration = function(talaIndex) {
	var i;
	var nIndex, part;
     	for( i = 0; i < this.fParts.length; i++ ) {
	    part = this.fParts[i];
	    if( (i+1) < this.fParts.length ) nIndex = this.fParts[i+1].fIndex;
	    else			     nIndex = this.fAksharaCount;
	    if( talaIndex >= part.fIndex && talaIndex < nIndex ) 
		return nIndex - part.fIndex;
	}
	return 0;
     }
     this.getNthPartDuration = function(n) {
	if( n < 0 && n >= this.fParts.length ) return 0;
	var nIndex;
	if( n < (this.fParts.length-1))
	    nIndex = this.fParts[n+1].fIndex;
	else
	    nIndex = this.fAksharaCount;
	return nIndex - this.fParts[n].fIndex;
     }
     this.canSwitchGati = function() {
	if( this.fParts.length == 0 ) return false;
	var g = this.fParts[0].fGati;
	for(i = 1; i < this.fParts.length; i++ ) {
	    if( this.fParts[i].fGati != g ) return false;
	}
	return true;
     }
     this.switchGati = function(gati) {
	if( !this.canSwitchGati()) {
	    alert("cannot switch gati/nadai with this tala");
	    return false;
	}
	var curgati = this.fParts[0].fGati;
	if( gati == this.fParts[0].fGati ) return true;	
	for(i = 0; i < this.fParts.length; i++ )
	    this.fParts[i].fGati = gati;
	if( this.fLayout != null ) 
	    this.fLayout.switchGati(curgati, gati);
	return true;
     }
    this.toXML = function() {
	if( this.fPredefName ) {
	    var x = XMLUtils.createXMLNode( this.XMLTagName() );
	    x.setAttribute( "predefined", this.fPredefName );
	    x.setAttribute( "layout", this.fLayoutSpec.toXMLAttribVal() );
	    return x;
	}
	return null;
     }
}
function Tala ( name , nAksharas , layoutSpec , predefName ) { this . fAksharaCount = nAksharas ; this . fName = name ; this . fParts = new Array ( ) ; this . fLayoutSpec = layoutSpec ; this . fLayout = null ; this . aksharaCount = function ( ) { return this . fAksharaCount ; } this . getLayoutSpec = function ( ) { return this . fLayoutSpec ; } this . getLayout = function ( ) { return this . fLayout ; } this . setLayoutSpec = function ( layoutSpec ) { this . fLayoutSpec = layoutSpec ; } this . fPredefName = predefName ; this . name = function ( ) { return this . fName ; } this . parts = function ( ) { return this . fParts ; } this . addPart = function ( talaIndex , gati , marker ) { if ( talaIndex < 0 || talaIndex >= this . fAksharaCount ) return false ; if ( ! isValidGati ( gati ) ) return false ; this . fParts [ this . fParts . length ] = new TalaPart ( talaIndex , gati , marker ) ; return true ; } this . finalizeParts = function ( layout ) { this . fLayout = layout ; } this . getPartCount = function ( ) { return this . fParts . length ; } this . getNthPart = function ( talaIndex ) { if ( talaIndex >= 0 && talaIndex < this . fParts . length ) return this . fParts [ talaIndex ] ; return null ; } this . getPart = function ( talaIndex ) { var i ; var nIndex , part ; var parts = this . fParts ; var nparts = parts . length ; for ( i = 0 ; i < nparts ; i ++ ) { part = parts [ i ] ; if ( ( i + 1 ) < nparts ) nIndex = parts [ i + 1 ] . fIndex ; else nIndex = this . fAksharaCount ; if ( talaIndex >= part . fIndex && talaIndex < nIndex ) return part ; } return null ; } this . getPartDuration = function ( talaIndex ) { var i ; var nIndex , part ; for ( i = 0 ; i < this . fParts . length ; i ++ ) { part = this . fParts [ i ] ; if ( ( i + 1 ) < this . fParts . length ) nIndex = this . fParts [ i + 1 ] . fIndex ; else nIndex = this . fAksharaCount ; if ( talaIndex >= part . fIndex && talaIndex < nIndex ) return nIndex - part . fIndex ; } return 0 ; } this . getNthPartDuration = function ( n ) { if ( n < 0 && n >= this . fParts . length ) return 0 ; var nIndex ; if ( n < ( this . fParts . length - 1 ) ) nIndex = this . fParts [ n + 1 ] . fIndex ; else nIndex = this . fAksharaCount ; return nIndex - this . fParts [ n ] . fIndex ; } this . canSwitchGati = function ( ) { if ( this . fParts . length == 0 ) return false ; var g = this . fParts [ 0 ] . fGati ; for ( i = 1 ; i < this . fParts . length ; i ++ ) { if ( this . fParts [ i ] . fGati != g ) return false ; } return true ; } this . switchGati = function ( gati ) { if ( ! this . canSwitchGati ( ) ) { alert ( "cannot switch gati/nadai with this tala" ) ; return false ; } var curgati = this . fParts [ 0 ] . fGati ; if ( gati == this . fParts [ 0 ] . fGati ) return true ; for ( i = 0 ; i < this . fParts . length ; i ++ ) this . fParts [ i ] . fGati = gati ; if ( this . fLayout != null ) this . fLayout . switchGati ( curgati , gati ) ; return true ; } this . toXML = function ( ) { if ( this . fPredefName ) { var x = XMLUtils . createXMLNode ( this . XMLTagName ( ) ) ; x . setAttribute ( "predefined" , this . fPredefName ) ; x . setAttribute ( "layout" , this . fLayoutSpec . toXMLAttribVal ( ) ) ; return x ; } return null ; } }
@class
 represents a tala and is made up of {@link TalaPart}s, and also a
 {@link TalaLayoutSpecification} that specifies how to lay it out
@class represents a tala and is made up of { @link TalaPart } s and also a { @link TalaLayoutSpecification } that specifies how to lay it out
/**
      * # of aksharas in tala cycle
      * @type int
      * @private
      */ /**
      * name of tala
      * @type String
      * @private
      */ /**
      * @type Array
      * parts of tala
      * @private
      */ /**
      * @type TalaLayoutSpecification
      * layout specification of tala
      */ /**
     * @type TalaLayout
     * the layout based on the spec
     */ /**
     * return the akshara count
     * @return akshara count
     * @type int
     */ /**
     * return the layout spec
     * @type {TalaLayoutSpecification}
     */ /**
     * return the layout based on the layout spec
     * @type {TalaLayout}
     */ /**
     * set the layout spec
     * @param {TalaLayoutSpecification} layoutSpec	layour specification
     */ /**
      * if not-null the predefined name for this tala
      */ /**
      * return the name
      * @return name of tala
      * @type String
      */ /**
      * return the parts in the tala (a linked list)
      * @return first part in tala - head of linked list
      * @type TalaPart
      */ /**
      * add a tala part
      * @param {int}    talaIndex akshara index of part within a cycle
      * @param {GATI}   gati      the gati
      * @param {String} marker	  the tala marker to put out when akshara 
      *                           count of a tala cycle reaches talaIndex
      * @return true if successful, false else
      * @type boolean
      */ /**
      * <b>must</b> be called after adding parts
      */ /**
      * get the # of parts in the tala
      * @type int
      */ /**
      * return a part given its index
      * @type TalaPart
      */ /**
      * return the tala part that contains the index talaIndex
      *
      * @param {int} talaIndex	index (akshara) in a tala cycle
      *
      * @return the part containing the index (or null if no such part)
      * @type TalaPart
      */ /**
      * return the tala part duration (in aksharas) of the tala part 
      * containing the index talaIndex
      *
      * @param {int} talaIndex	index (akshara) in a tala cycle
      * @return the duration (in aksharas) of the part containing the 
      *         index (or 0 if no such part)
      * @type int
      */ /**
      * return the tala part duration (in aksharas) of the nth tala part 
      *
      * @param {int} n		the tala part
      * @return the duration (in aksharas) of the part containing the 
      *         index (or 0 if no such part)
      * @type int
      */ /**
      * can we switch gati on this tala?
      * This is allowed only all parts of tala are of same gati
      */ // no change /**
      * override of {@link SongPart#toXML}
      */