
    3j2                    2   d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddlm
Z
 ddlmZ  e	j                  d      Z G d	 d
e      Z G d de
j                         Z G d d      Z G d d      Z G d d      Zedk(  rddlZ ej,                          yy)a   
Attempts at reading pure .nwc files in music21

First will solve uncompressed .nwc then compressed .nwc

Thanks to Juria90 and the nwc2xml project for solving so many of the documentation problems.
No part of this code is taken from that project, but this project would have been impossible
without his work.

Translates .nwc into .nwctxt and then uses Jordi Guillen's .nwctxt translator to go from
there to music21.

BETA -- does not work for many file elements and is untested.

Demo, showing the extent of problems.  The measure numbers are not set.  Lyrics are missing.
Drum is still poorly handled.
This is very beta.  Much better would be to convert the file into .xml or .nwctxt first.

::

    >>> #_DOCS_SHOW c = converter.parse('/Users/Hildegard/Desktop/test1.nwc')
    >>> p = common.getSourceFilePath() / 'noteworthy' / 'cuthbert_test1_v175.nwc' #_DOCS_HIDE
    >>> c = converter.parse(p) #_DOCS_HIDE
    >>> c.show('text')
    {0.0} <music21.metadata.Metadata object at ...>
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.instrument.Violin 'Violin'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.clef.TrebleClef>
            {0.0} <music21.tempo.MetronomeMark animato Quarter=120>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.note.Note G>
            {1.0} <music21.note.Note C>
            {2.0} <music21.note.Note C>
            {3.0} <music21.note.Note B>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note C>
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.instrument.Violin 'Violin'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.clef.TrebleClef>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.note.Note G>
            {1.0} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.5} <music21.note.Note G>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note G>
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.instrument.Viola 'Viola'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.clef.AltoClef>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.note.Note D>
            {2.0} <music21.note.Note C#>
            {2.6667} <music21.note.Note D>
            {3.3333} <music21.note.Note E>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note E>
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.instrument.Violoncello 'Violoncello'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.clef.BassClef>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.note.Note G>
            {1.0} <music21.note.Note F>
            {2.0} <music21.note.Note E>
            {3.0} <music21.note.Note G>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note C>

    >>> #_DOCS_SHOW c = converter.parse('/Users/Hildegard/Desktop/jingle1.nwc')
    >>> p = common.getSourceFilePath() / 'noteworthy' / 'jingle_v175.nwc' #_DOCS_HIDE
    >>> c = converter.parse(p) #_DOCS_HIDE
    >>> c.show('text')
    {0.0} <music21.metadata.Metadata object at 0x7fe8c0a5ffa0>
    {0.0} <music21.stream.Part 0x7fe8c0920100>
        {0.0} <music21.instrument.Piano 'Piano'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.expressions.TextExpression 'Lively'>
            {0.0} <music21.expressions.TextExpression 'F'>
            {0.0} <music21.clef.TrebleClef>
            {0.0} <music21.tempo.MetronomeMark animato Quarter=120>
            {0.0} <music21.key.KeySignature of 1 flat>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.note.Note A>
            {1.0} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Rest quarter>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note A>
            {1.0} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Rest quarter>
        {8.0} <music21.stream.Measure 1 offset=8.0>
            {0.0} <music21.note.Note A>
            {1.0} <music21.note.Note C>
            {2.0} <music21.note.Note F>
            {3.5} <music21.note.Note G>
        {12.0} <music21.stream.Measure 2 offset=12.0>
            {0.0} <music21.note.Note A>
            {3.0} <music21.note.Rest quarter>
        {16.0} <music21.stream.Measure 3 offset=16.0>
            {0.0} <music21.expressions.TextExpression 'Bb'>
            {0.0} <music21.note.Note B->
            {1.0} <music21.note.Note B->
            {2.0} <music21.note.Note B->
            {3.5} <music21.note.Note B->
        {20.0} <music21.stream.Measure 4 offset=20.0>
            {0.0} <music21.expressions.TextExpression 'F'>
            {0.0} <music21.note.Note B->
            {1.0} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Note A>
            {3.5} <music21.note.Note A>
        {24.0} <music21.stream.Measure 5 offset=24.0>
            {0.0} <music21.expressions.TextExpression 'G'>
            {0.0} <music21.bar.Barline type=regular>
            {0.0} <music21.note.Note A>
            {1.0} <music21.note.Note G>
            {2.0} <music21.note.Note G>
            {3.0} <music21.note.Note A>
        {28.0} <music21.stream.Measure 6 offset=28.0>
            {0.0} <music21.expressions.TextExpression 'C7'>
            {0.0} <music21.note.Note G>
            {2.0} <music21.note.Note C>
            {4.0} <music21.bar.Repeat direction=end>
        {28.0} <music21.spanner.RepeatBracket 1
                <music21.stream.Measure 5 offset=24.0><music21.stream.Measure 6 offset=28.0>>
        {32.0} <music21.stream.Measure 7 offset=32.0>
            {0.0} <music21.expressions.TextExpression 'C7'>
            {0.0} <music21.bar.Barline type=regular>
            {0.0} <music21.note.Note C>
            {1.0} <music21.note.Note C>
            {2.0} <music21.note.Note B->
            {3.0} <music21.note.Note G>
        {36.0} <music21.stream.Measure 8 offset=36.0>
            {0.0} <music21.expressions.TextExpression 'F'>
            {0.0} <music21.note.Note F>
            {3.0} <music21.note.Rest quarter>
    {0.0} <music21.stream.Part 0x7fe8c0921660>
        {0.0} <music21.instrument.Piano 'Piano'>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.clef.BassClef>
            {0.0} <music21.key.KeySignature of 1 flat>
            {0.0} <music21.meter.TimeSignature 4/4>
            {0.0} <music21.chord.Chord F3 A3 C4>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.chord.Chord F3 A3 C4>
        {8.0} <music21.stream.Measure 1 offset=8.0>
            {0.0} <music21.chord.Chord F3 A3 C4>
        {12.0} <music21.stream.Measure 2 offset=12.0>
            {0.0} <music21.chord.Chord F3 A3 C4>
            {1.0} <music21.note.Rest quarter>
            {2.0} <music21.chord.Chord F3 A3 C4>
            {3.0} <music21.note.Rest quarter>
        {16.0} <music21.stream.Measure 3 offset=16.0>
            {0.0} <music21.chord.Chord F3 B-3 D4>
        {20.0} <music21.stream.Measure 4 offset=20.0>
            {0.0} <music21.chord.Chord F3 A3 C4>
            {1.0} <music21.note.Rest quarter>
            {2.0} <music21.note.Rest half>
        {24.0} <music21.stream.Measure 5 offset=24.0>
            {0.0} <music21.bar.Barline type=regular>
            {0.0} <music21.chord.Chord G3 B3>
            {2.0} <music21.note.Rest half>
        {28.0} <music21.stream.Measure 6 offset=28.0>
            {0.0} <music21.chord.Chord E3 B-3 C4>
            {4.0} <music21.bar.Repeat direction=end>
        {28.0} <music21.spanner.RepeatBracket 1
                 <music21.stream.Measure 5 offset=24.0><music21.stream.Measure 6 offset=28.0>>
        {32.0} <music21.stream.Measure 7 offset=32.0>
            {0.0} <music21.bar.Barline type=regular>
            {0.0} <music21.chord.Chord E3 B-3 C4>
            {1.0} <music21.note.Rest quarter>
            {2.0} <music21.note.Rest half>
        {36.0} <music21.stream.Measure 8 offset=36.0>
            {0.0} <music21.chord.Chord F3 A3 C4>
            {3.0} <music21.note.Rest quarter>

    )annotationsN)	TypedDict)environment)exceptions21)	constantsznoteworthy.translatec                  6    e Zd ZU ded<   ded<   ded<   ded<   y)FontDictbytesnameintsizestylecharsetN)__name__
__module____qualname____annotations__     O/DATA/.local/lib/python3.12/site-packages/music21/noteworthy/binaryTranslate.pyr	   r	      s    
K
IJLr   r	   c                      e Zd Zy)"NoteworthyBinaryTranslateExceptionN)r   r   r   r   r   r   r   r      s    r   r   c            	          e Zd ZdZddZddZdddZd dZd dZd dZ	d!d"dZ
d d"d	Zd d#d
ZdddddddddZd dZd$dZd%d&dZd ZddZd'dZd Zy)(NWCConvertera  
    A converter object for binary .nwc files.  Do not normally use directly; use converter.parse.

    >>> nwcc = noteworthy.binaryTranslate.NWCConverter()
    >>> nwcc
    <music21.noteworthy.binaryTranslate.NWCConverter object at 0x...>
    >>> nwcc.fileContents
    b''
    >>> nwcc.parsePosition
    0
    >>> nwcc.version  # version of nwc file to be parsed
    200
    >>> nwcc.numberOfStaves
    0
    >>> nwcc.staves
    []
    c                   d| _         d| _        d| _        d| _        d| _        d| _        g | _        d| _        g | _        d| _	        d| _
        d| _        d| _        d| _        d | _        d| _        d| _        d | _        d| _        d| _        d | _        d | _        d | _        d | _        d | _        d| _        d| _        i | _        y )Nr   r         s   Maestro)fileContentsparsePositionversionnumberOfStavestitlePageInfopageNumberStartstavescommentfontslyricistgroupVisibilityallowLayeringmarginsnotationTypefaceextendLastSystem
copyright1
copyright2increaseNoteSpacingauthortitlemeasureStartmeasureNumbersmirrorMarginsstaffLabelssinsuserstaffHeightcurrentAlterations)selfkeywordss     r   __init__zNWCConverter.__init__   s    #& &(!%'
"&)"#!'1 $!$!$#'  
 "!		24r   c                    t        |d      5 }|j                         | _        ddd       | j                          | j	                         S # 1 sw Y   )xY w)a  
        Parse a file (calls .toStream)

        >>> #_DOCS_SHOW fp = '/Users/cuthbert/desktop/cuthbert_test1.nwc'
        >>> fp = str(common.getSourceFilePath()/'noteworthy'/'cuthbert_test1.nwc') #_DOCS_HIDE
        >>> nwcc = noteworthy.binaryTranslate.NWCConverter()
        >>> nwcc.fileContents
        b''
        >>> streamObj = nwcc.parseFile(fp)
        >>> len(nwcc.fileContents)  # binary
        1139
        >>> nwcc.fileContents[0:80]
        b'[NoteWorthy ArtWare]\x00\x00\x00[NoteWorthy
                 Composer]\x00\x01\x02\x02\x00\x00\x00N/A\x000_JldRQMSKq6M5a3FQqK_g\x00\x00\x00'
        >>> streamObj
        <music21.stream.Score ...>
        rbN)openreadr   parsetoStream)r:   fpfs      r   	parseFilezNWCConverter.parseFile
  s?    & "d^q !D 

}} ^s   AAc                P    || _         | j                          | j                         S )z^
        same as parseFile but takes a string (in Py3, bytes) of binary data instead.
        )r   rA   rB   )r:   bytesIns     r   parseStringzNWCConverter.parseString"  s!     $

}}r   c                    | j                   }| j                  }t        j                  d|||dz          d   }|du r
|dz   | _        |S )ak  
        Helper module: read a little-endian short value to an integer

        >>> nwcc = noteworthy.binaryTranslate.NWCConverter()
        >>> nwcc.fileContents = b''
        >>> nwcc.parsePosition
        0
        >>> nwcc.readLEShort()
        258
        >>> nwcc.parsePosition
        2
        >>> nwcc.readLEShort()
        259
        >>> nwcc.parsePosition
        4

        Or to not update the parsePosition, send False:
        >>> nwcc.parsePosition = 0
        >>> nwcc.readLEShort(False)
        258
        >>> nwcc.readLEShort(False)
        258
        >>> nwcc.parsePosition
        0
        z<h   r   T)r   r   structunpackr:   updateParsePositionfcppvalues        r   readLEShortzNWCConverter.readLEShort*  sR    4 dBr"q&M215$&!#aDr   c                t    | j                   }| j                  }t        |||dz          }|du r
|dz   | _        |S )zx
        changes a byte into an unsigned int
        (i.e., if the byte is > 127 then it's subtracted from 256)
        r   T)r   r   ordrM   s        r   	byteToIntzNWCConverter.byteToIntL  sG    
 Br"q&M"$&!#aDr   c                <    | j                  |      }|dkD  r|dz
  }|S )zu
        changes a byte into a signed int
        (i.e., if the byte is > 127 then it's subtracted from 256)
              )rU   )r:   rN   vals      r   byteToSignedIntzNWCConverter.byteToSignedIntY  s(    
 nn019)C
r   c                b    | j                   }| j                  }||||z    }|du r
||z   | _        |S )zc
        reads the next bytesToRead bytes and then (optionally) updates self.parsePosition
        T)r   r   )r:   bytesToReadrN   rO   rP   rQ   s         r   	readByteszNWCConverter.readBytesc  sE     2b;&'$&!#k!1Dr   c                    | j                   }	 |j                  d| j                        }|dk(  r|| j                  d }n|| j                  | }|du r
|dz   | _        |S # t        $ r d}Y Aw xY w)z
        reads self.fileContents up to, but not including, the next position of \x00.

        updates the parsePosition unless updateParsePosition is False
        r   NTr   )r   indexr   
ValueError)r:   rN   rO   nulPositionrets        r   	readToNULzNWCConverter.readToNULn  s     	((1d&8&89K "T''()CT''4C$&!,qD
  	K	s   A A,+A,c                    | j                   }d| _         | j                         }|dk7  ry| j                         }| j                         }| j                         }|dk7  ry|du r|dk7  r|| _         y)Nr   s   [NoteWorthy ArtWare]Fz[NoteWorthy Composer]T)r   rd   )r:   rN   storedPPheader1junkheader2s         r   isValidNWCFilezNWCConverter.isValidNWCFile  sv    %%.."--~~~~.."--%'HM!)Dr   x                  r      )i  i  i2  i7  iF  iK  i   i  c                    | j                   }d| _         | j                  |      }|du r|| _         || j                  v r | j                  |   | _        | j                  S t	        d       d| _        | j                  S )N-   Fz:No Version Found! Most likely a newer version.  Using 2.01rq   )r   rR   versionFromHexr    print)r:   rN   rf   fileVersionRaws       r   fileVersionzNWCConverter.fileVersion  s~    %%))*=>%'!)DT000..~>DL
 || NODL||r   c                .    | xj                   |z  c_         y N)r   )r:   numBytess     r   	skipByteszNWCConverter.skipBytes  s    h&r   c                z    | j                   }| j                  }|||dz    |k(  r|dz  }|||dz    |k(  r|| _         y )Nr   )r   r   )r:   nulrP   rO   s       r   advanceToNotNULzNWCConverter.advanceToNotNUL  sO    BFms"!GB BFms"r   c                X   | j                   dd dk(  r)ddl}|j                  | j                   dd       }|| _         d| _        | j	                          g | _        t        | j                        D ]9  }t        |       }|j                          | j
                  j                  |       ; y)zO
        the main parse routine called by parseFile() or parseString()
        r      s   [NWZ] N)parent)r   zlib
decompressr   parseHeaderr$   ranger!   NWCStaffrA   append)r:   r   fcNewi	thisStaffs        r   rA   zNWCConverter.parse  s     Qq!\1OOD$5$5ab$9:E %D t**+A -IOOKKy) ,r   c                0   | j                          | j                          | j                  d       | j                         | _        | j                         }| j                  d       | j                         | _        | j                         | _        | j                  dk\  r| j                         | _        | j                         | _	        | j                         | _
        | j                         | _        | j                         | _        | j                         | _        | j                  d      }| j                         | _        | j                  d      }| j#                         | _        | j                  dk\  r| j                         | _        nd| _        | j                         }| j                  d      }| j                  dk\  r+| j                  d	      | _        | j                         | _        | j                  dk\  r| j                         | _        | j#                         | _        | j                  d
kD  rd}n| j                  dkD  rd}nd}| j1                          | j                  d       g | _        t5        |      D ]  }| j                         | j                         | j                         dd}| j                         }| j                         |d<   |d   dk(  rd|d<   |d   dk(  rd|d<   | j2                  j7                  |        | j                         | _        | j                         | _        | j#                         | _        | j                  dk\  r| j                  d       | j                         | _        | j                  d       y)z]
        Sets a ton of information from the header, and advances the parse position.
           
   r      r   rl   s   0.0 0.0 0.0 0.0rJ       ro      r   )r   r   r   r   r   r   r   s   Times New Romanr   N) rj   rw   r{   rd   r7   r1   r0   r    r'   r-   r.   r%   rU   r,   r/   r]   r3   rR   r2   r*   r(   r)   r+   r8   r~   r&   r   r   r"   r5   r#   r!   )r:   unused_unknownunused	fontCountr   fontDicts         r   r   zNWCConverter.parseHeader  s    	 	qNN$	)r^^%
nn&<<3 NN,DM..*..*~~' $ 0#'>>#3 ""nn." ,,.<<3>>+DL-DL!"<<3#'>>"#5D !%!1D<<3$(NN$4D!++-<<#I\\CIIq
y!A()(	"H ^^%F"&.."2HY3&#5 1$#% JJh' "  "^^-  >>+#//1<<3NN1"nn.qr   c                6   d}| j                   r!|d| j                   j                  d      z   z  }| j                  r!|d| j                  j                  d      z   z  }|g}| j                  D ]*  }|j	                         }|D ]  }|j                  |        , |S )N z|SongInfo|Title:latin_1z|Author:)r1   decoder0   r$   dumpr   )r:   infosdumpObjectssstaffDumpObjectssdos         r   dumpToNWCTextzNWCConverter.dumpToNWCText  s    ::'$***;*;I*FFFE;;Z$++"4"4Y"???EgA vvx'""3' ( 
 r   c                p    ddl m} |j                         }|j                  | j	                               }|S )Nr   )	translate)music21.noteworthyr   NoteworthyTranslator	parseListr   )r:   r   nwtr   s       r   rB   zNWCConverter.toStream+  s/    0,,.MM$,,./r   N)returnNone)rC   zpathlib.Path | str)r   )rG   r
   )T)r   T)r   r
   )r   bool)r   )    )r}   r
   r   z	list[str])r   r   r   __doc__r<   rE   rH   rR   rU   rZ   r]   rd   rj   rt   rw   r{   r~   rA   r   r   rB   r   r   r   r   r      s{    "5>0 D	.  "!!!!!!!N' *&Pdr   r   c                  8    e Zd ZdZd	dZd Zd
dZd Zd Zd Z	y)r   aC  
    A NWCStaff is a list of NWCObjects (see :meth:`parseObjects`) associated to metadata
    (see :meth:`parseHeader`). It may also contain some lyrics (see :meth:`parseLyrics`).
    It defines a :meth:`dump` method that return a list of string containing the
    nwctxt-formatted content of each object of the staff.
    c                    || _         g | _        g | _        d| _        d | _        d | _        d | _        d | _        d | _        d| _	        d | _
        d| _        d| _        d| _        d | _        d| _        d| _        d| _        y )Nr   r   )r   lyricsobjectsinstrumentNamegrouplayerWithNextStafftransposition
partVolume	stereoPancoloralignSyllablenumberOfLyricsnumberOfObjectslinesr   staffOffsetlabellyricAlignment)r:   r   s     r   r<   zNWCStaff.__init__9  s    $*)+(*%(
"&!
! 
	
r   c                d    | j                          | j                          | j                          y ry   )r   parseLyricsparseObjects)r:   s    r   rA   zNWCStaff.parseM  s&    r   c                8   g }| j                   r| j                   j                  d      nd}| j                  r| j                  j                  d      n|}d|z   }|j                  |       d|z   }|t        j
                  v r0|dz  }|t        t        j
                  j                  |            z  }|dt        | j                        z   z  }|j                  |       | j                  D ]-  }|j                  } ||      }|dk7  s|j                  |       / |S )Nr   zAcoustic Grand Pianoz|AddStaff|Name:z|StaffInstrument|Name:z|Patch:z|Trans:r   )r   r   r   r   r   MidiInstrumentsstrr`   r   r   
dumpMethod)	r:   r   
instruNamer   staffStringstaffInstruStringodmds	            r   r   zNWCStaff.dumpV  s    ,, ))00;1 	 15



!!),
'%/;'4zA222*Y%>%>%D%DZ%P!QQYT-?-?)@@@,-AB1ABw""1%	  r   c                   | j                   }|j                         | _        |j                  dk\  r*|j                         | _        |j                         | _        |j                         | _        |j                  dk\  r|j                  d       |j                         | _	        |j                         | _        |j                         | _        |j                         | _        |j                         | _        |j                         | _        |j                         | _        |j                         | _        n|j                  dk(  r|j                  d       |j                         }d|cxk  rt%        t&        j(                        k  rn n|dz
  nd}t&        j(                  |   j+                  d      | _        |j                  d       |j-                         | _        |j                  d	       |j                         | _        |j                         | _        | j"                  dkD  r+|j                         | _        |j                         | _        y d| _        d| _        y )
Nr      rp      r   r   r   r   r   )r   rd   r   r    r   r   r   r{   rU   r   rR   r   r   r   r   r   r   r   lenr   r   encoderZ   r   r   )r:   pinstruPatchr`   s       r   r   zNWCStaff.parseHeaders  s   KKKKM	99DJ"#++-D[[]
 99" KKODJ '(mmoD#!"DmmoDO]]_DNDJ!"D"#--/DYY#KKO++-K'(;'WY=V=V9W'WK!O]^E"+";";E"B"I"I)"TDKKO!"!2!2!4DKKN!"D"#--/D""#--/D }}D"#D Dr   c                l   | j                   }g }t        | j                        D ]  }g }	 |j                         }|dkD  s|j                         }|j                  }|j                         }d}	d}
|	du r=|
dkD  r8|j                         }|
dz  }
|dk(  rd}	n|j                  |       |	du r|
dkD  r8||z   |_        |j                  |        | j                  dkD  r|j                         }|j                         }|| _        |S # t        j
                  $ r d}t        j                  d       Y w xY w)Nr   z/Could not read lyrics. Trying with zero length.Ti  r   r   F)r   r   r   rR   rK   errorenvironLocalwarnr   rd   r   r   )r:   r   r   r   	syllableslyricBlockSizeunused_lyricSizeparsePositionStartrh   
continueItmaxReadsyllablejunk_2s                r   r   zNWCStaff.parseLyrics  s5   KKt**+AIU!" !#$==? %&__" }}!
 D(Wq[ {{}HqLG3%*
!((2 !D(Wq[ #5~"Ei(7 ,< "==?D? << U!"!!"STUs   D*D32D3c                2   | j                   }g }|j                         | _        |j                  dkD  r| xj                  dz  c_        t	        | j                        D ]0  }t        | |      }|j                          |j                  |       2 || _        |S )Nrm   rJ   staffParentparserParent)	r   rR   r   r    r   	NWCObjectrA   r   r   )r:   r   r   r   
thisObjects        r   r   zNWCStaff.parseObjects  s    KK }}99s?  A%  t++,A"t!DJNN:& - r   N)r   r   r   r   r   )
r   r   r   r   r<   rA   r   r   r   r   r   r   r   r   r   2  s'     (::!z(Tr   r   c                      e Zd ZdZddZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zeeee	e
eeeeeeeeeeeeeegZy)r   aV  
    NWCObject class is a union that can be used for each type of object contained in a staff.

    An object binary blob starts with its type.
    The parse() method calls the appropriate method depending on the object type.
    Each parsing method should set up the 'dumpMethod' method that return the nwctxt version
    of the object.
    c                X   || _         || _        d | _        d| _        d| _        d| _        d| _        d| _        d | _        d | _	        d | _
        d| _        d| _        d| _        d| _        d| _        d | _        d| _        d| _        d| _        d | _        d | _        d | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _         d | _!        d| _"        d| _#        d| _$        d| _%        d| _&        d | _'        d | _(        dd}|| _)        y )Nr   r   c                     y)Nr   r   
inner_selfs    r   genericDumpMethodz-NWCObject.__init__.<locals>.genericDumpMethod  s    r   )r   r   )*r   r   type	placementposr   localRepeatCountdatadata1data2data3delayclefTypeoffsetvisibledurationdurationStrfontsharpsoctaveShiftoctaveShiftNameclefName
attribute1
attribute2
stemLengthdotsbitsdenominatortieInfovolumebasevelocitycountr   rQ   flats	keyString	numeratoralterationStrdotAttributetextr   )r:   r   r   r   s       r   r<   zNWCObject.__init__  s8   %0*6	
 !	



	#			
	

 		 ,r   c                D   | j                   }|j                         }|t        | j                        k\  s|dk  r$t	        d| dt        | j                               |j
                  dk\  r|j                         | _        nd| _        | j                  |   } ||        y)zP
        determine what type of object I am, and set things accordingly
        r   zCannot translate objectType: z	; max is ro   N)r   rR   r   
objMethodsr   r    rU   r   )r:   r   
objectTypeobjectMethods       r   rA   zNWCObject.parse$  s     ]]_
T__--a4/
|9SEYDZ[] ]99;;=DLDLz2Tr   c                   | j                   }d| _        |j                         | _        |j                         | _        | j                  t        t        j                        k  r"t        j                  | j                     | _        | j                  t        t        j                        k  r"t        j                  | j                     | _
        d }|| _        y)z,
        clef info,
        4 bytes
        Clefc                    d}| j                   r|d| j                   z   dz   z  }| j                  r|d| j                  z   dz   z  }|S )Nz|Clef|zType:|zOctaveShift:)r   r   r   builds     r   r   zNWCObject.clef.<locals>.dumpJ  sR    E"":#6#66<<))**D*DDsJJLr   N)r   r   rR   r   r   r   r   	ClefNamesr   OctaveShiftNamesr   r   r:   r   r   s      r   clefzNWCObject.clef9  s    
 	==?==3y2233%//>DMc)"<"<==#,#=#=d>N>N#OD 	 r   c                   | j                   }d| _        |j                         | _        |j	                  d       |j                         | _        |j	                  d       | j                  dkD  r?| j                  t        j                  v r#t        j                  | j                     | _        nU| j
                  dkD  r?| j
                  t        j                  v r#t        j                  | j
                     | _        nd| _        d }|| _
        y)z0
        Key signature
        10 bytes
        KeySigr      r   r   c                $    d| j                   z   }|S )Nz|Key|Signature:)r	  r  s     r   r   zNWCObject.keySig.<locals>.dumpl  s    %
(<(<<ELr   N)r   r   rU   r  r{   r   r   FlatMaskr	  	SharpMaskr   r  s      r   keySigzNWCObject.keySigT  s    
 	[[]
	Akkm	A ::>djjI,>,>>&//

;DN[[1_	0C0C!C&00=DNDN	 r   c                    | j                   }d| _        |j                         | _        |j                         | _        i | j                   _        d }|| _        y)z*
        Bar line
        2 bytes
        Barlinec                    d}d| j                   cxk  rt        t        j                        k  r)n |S t        j                  | j                      }|d|z   z  }|S )Nz|Bar|r   z|Style:)r   r   r   	BarStyles)r   r  styleStrings      r   r   zNWCObject.barline.<locals>.dump~  sX    E:##>c)*=*=&>> L (11*2B2BC[00Lr   N)r   r   rU   r   r   r9   r   r  s      r   barlinezNWCObject.barliner  sM    
 	[[]
 !/1,	 r   c                    | j                   }d| _        |j                         | _        |j	                  d       d }|| _        y)z)
        Endings
        2 bytes
        Endingr   c                2    dt        | j                        z   S )Nz|Ending|Endings:)r   r   r   s    r   r   zNWCObject.ending.<locals>.dump  s    %J,<,<(===r   N)r   r   rU   r   r{   r   r  s      r   endingzNWCObject.ending  s<    
 	[[]
	A	> r   c                L    | j                   }d| _        |j                  d       y)z,
        Instrument
        8 bytes
        
Instrument   N)r   r   r{   r:   r   s     r   
instrumentzNWCObject.instrument  s#    
  	 	
Ar   c                    | j                   }d| _        |j                         | _        |j                         | _        d| j                  z  | _        |j                         | _        d }|| _        y)z0
        Time signature
        6 bytes
        TimeSigr   c                >    d| j                    d| j                   }|S )Nz|TimeSig|Signature:/)r
  r  r  s     r   r   zNWCObject.timeSig.<locals>.dump  s'    )**>*>)?qAWAW@XYELr   N)r   r   rR   r
  r  r  r   r   r  s      r   timeSigzNWCObject.timeSig  s[    
 	MMO			>]]_
	 r   c                N   | j                   }d| _        |j                         | _        |j                         | _        |j                         | _        |j                         | _        |j                  dk  r|j                         }|j                         | _
        d }|| _        y)zL
        Tempo indications
        5 bytes + null terminated string
        Temporo   c                     d| j                    S )Nz|Tempo|Tempo:)rQ   r   s    r   r   zNWCObject.tempo.<locals>.dump  s    ":#3#3"455r   N)r   r   rU   r   r   rR   rQ   r  r    rd   r  r   )r:   r   rh   r   s       r   tempozNWCObject.tempo  s{    
 	;;=]]_
KKM	99s?==?DKKM		6 r   c                2   | j                   }d| _        |j                  dk  rt        d       y|j	                         | _        |j	                         | _        |j	                         | _        |j                         | _	        |j                         | _
        y)z*
        dynamics
        7 bytes
        Dynamicro   z3Dynamics on version below 1.70 is not supported yetN)r   r   r    ru   rU   r   r   r   rR   r  r  r0  s     r   dynamiczNWCObject.dynamic  sk    
 	99s?GH{{}DH[[]DNDJMMODM--/DKr   c                   t         j                  | j                     }d}d}| j                  dk(  r'| j                  d   | _        | j                  d   dz  }n| j                  d   | _        | j                  d   dz  }| j
                  }|dz  dkD  rd| _        n|d	z  dkD  rd| _        nd| _        | j                  dk(  r|d
z  }n| j                  dk(  r|dz  }|dkD  r|dz  }|r|dz  }|S )z6
        get duration string for note or rest
        r   FNoter   r      r   rJ   r   z,Dottedz
,DblDottedz,Gracez,Triplet)r   DurationValuesr   r   r   r  r   r   )r:   durStrgracetripletordDots        r   setDurationForObjectzNWCObject.setDurationForObject  s    
 ))$--899 $ 2DOOA&-E $

1D **Q-$&""TMQDItmq DIDI99>iFYY!^l"F19hFj Fr   c                v   | j                   }d| _        |j                  dk  rt        d       n|j	                         | _        |j                  d      | _        |j                  d      | _        |j                         | _
        d| j                  z  | _
        |j	                         | _        |j                  dk  r|j                  d      | _        nd| _        |j                  dk\  r0| j                  d	z  d
k7  r|j	                         | _        nd| _        nd| _        | j                         | _        | j                  dz  }|t!        t"        j$                        k  rt"        j$                  |   | _        nd| _        | j&                  dk(  r8| j                   j(                  j+                  | j                  dz  d      | _        | j&                  d| _        | j&                  | j                   j(                  | j                  dz  <   d| _        | j                  d
   }|dz  d
kD  rd| _        d }|| _        y)z&
        Note
        8 bytes
        r?  ro   z%Cannot yet handle versions before 170r@  rJ   r_   Nr   @   r   r  r      ^c                    d| j                   z   dz   }|d| j                  z   t        | j                        z   | j                  z   dz   z  }|S )Nz
|Note|Dur:r  zPos:)r   r  r   r   r  r  s     r   r   zNWCObject.note.<locals>.dumpB  sc     :#9#99C?Ef"001JNN+, #**+ .11 2E Lr   )r   r   r    ru   rU   r   r]   r   r   rZ   r   r   r   r   rF  r   r   r   AlterationTextsr  r9   getr  r   )r:   r   alterationIndexordAtt1r   s        r   notezNWCObject.note  s   
 	99s?9:KKMDMQDJkk!nDO((*DHDHH}DHkkmDOyyC[[^
!
yyCOOd*q0&'kkmDO '(DO"#  446//D0S!:!:;;!*!:!:?!KD!#D #!%!2!2!E!E!I!I$((UV,XZ![D%!#D=A=O=O,,TXX\://!$dNaDL	 r   c                   | j                   }d| _        |j                  dk  rt        d       n@|j	                         | _        |j                  d      | _        |j                         | _	        | j                         | _        d }|| _        y)z&
        Rest
        8 bytes
        Restrm   z Does not work under version 1.50r   c                *    d| j                   z   dz   }|S )Nz
|Rest|Dur:r  )r   r  s     r   r   zNWCObject.rest.<locals>.dump]  s     :#9#99C?ELr   N)r   r   r    ru   rU   r   r]   r   rR   r   rF  r   r   r  s      r   restzNWCObject.restM  ss    
 	9945KKMDMQDJ--/DK446	 r   c                   | j                   }d| _        d}|j                  dk  r|j                  d      | _        nK|j                  dk(  r&|j                  d      | _        | j                  d   }n|j                  d      | _        |j                  dk\  r>| j                  d	   d
z  dk7  r!t        d       |j                         | _        nd	| _        nd	| _        g | _        t        j                  rt        | t              sJ t        |      D ]:  }t        | |      }|j                          | j                  j!                  |       < d }|| _        y)z?
        Chord member
        8 bytes + n Note objects
        NoteChordMemberr   ro   r   rp   r   r/  r   r  rH  zhave stemLength info!r   c                h   d}i }| j                   D ]w  }|j                  |j                        g ||j                  <   ||j                     j                  |j                  t        |j                        z   |j                  z          y |D ]"  }|d|z   dz   dj                  ||         z   z  }$ |S )N|Chord|Dur:|Pos:,)	r   rM  r   r   r  r   r   r  join)r   r  notesr   ns        r   r   z'NWCObject.noteChordMember.<locals>.dump  s    EE%%99Q]]+3+-E!--(amm$++AOOc!%%j,H199,TU	 & 1w.%(1CCC  Lr   N)r   r   r    r]   r   ru   rU   r   r   tTYPE_CHECKING
isinstancer   r   r   rA   r   r   )r:   r   numberOfNotesr   	chordNoter   s         r   noteChordMemberzNWCObject.noteChordMemberc  s   
 %	99RDJYY#RDJ JJqMMQDJ99

1$*-."#++- #$DO
??dH---}%A!dCIOOJJi( &
	 r   c                    | j                   }d| _        |j                  dk  rt        d       y|j	                         | _        |j	                         | _        |j	                         | _        y)z'
        Pedal
        3 bytes
        Pedalro   z/Pedal on version below 170 is not yet supportedN)r   r   r    ru   rU   r   r   r   r0  s     r   pedalzNWCObject.pedal  sQ    
 	99s?CD{{}DH[[]DNDJr   c                    | j                   }d| _        |j                  dk\  r+|j                         | _        |j                         | _        nd| _        d| _        |j                         | _        y)z&
        Flow
        4 bytes
        FlowDirro   ir   N)r   r   r    rU   r   r   rR   r   r0  s     r   flowDirzNWCObject.flowDir  sW    
 	99{{}DH[[]DNDH!DN]]_
r   c                B   | j                   }d| _        |j                         | _        |j                         | _        |j
                  dk(  r|j                  d      | _        y|j
                  dkD  r|j                  d      | _        y|j                  d      | _        y)z4
        Midi Instructions
        34 bytes
        MPCrp   r   rn      N)r   r   rU   r   r   r    r]   r   r0  s     r   mpczNWCObject.mpc  st    
 	;;=99RDJYY_RDJRDJr   c                   | j                   }d| _        |j                  dk\  rU|j                         | _        |j                         | _        |j                         | _        |j                         | _        y|j                         | _        | j                  dz  | _        |j                         | _        |j                         | _        |j                         | _        y)z1
        Tempo variation
        4 bytes
        TempoVariationro      N)r   r   r    rU   r   r   r   r   r0  s     r   tempoVariationzNWCObject.tempoVariation  s    
 $	99{{}DH[[]DNDJDJDJd*DJ{{}DH[[]DNDJr   c                    | j                   }d| _        |j                         | _        |j                  dk\  r|j                         | _        nd| _        |j                         | _        y)z3
        Dynamic variation
        3 bytes
        DynamicVariationro   r   Nr   r   rU   r   r    r   r   r0  s     r   dynamicVariationzNWCObject.dynamicVariation  sP    
 &	;;=99[[]DNDN[[]
r   c                    | j                   }d| _        |j                         | _        |j                  dk\  r|j                         | _        nd| _        |j                         | _        y)z-
        Performance
        3 bytes
        Performancero   r   Nru  r0  s     r   performancezNWCObject.performance  sP    
 !	;;=99[[]DNDN[[]
r   c                     j                   }d _        |j                          _        |j	                          _        |j	                          _        |j                          _         fd} j                  | _	        yy)z?
        Text
        3 bytes + null terminated string
        Textc                v    d| j                   j                  d      z   dz   t        j                        z   }|S )Nz|Text|Text:r   rZ  )r  r   r   r   )r   r  r:   s     r   r   zNWCObject.textObj.<locals>.dump   s8    !JOO$:$:9$EEORUVZV^V^R__ELr   N)
r   r   rZ   r   rU   r   r   rd   r  r   r  s   `  r   textObjzNWCObject.textObj  sk    
 	$$&KKM	KKM	KKM		 99 "DO !r   c                b   | j                          d| _        t        j                  rt	        | t
              sJ t        | | j                        }| j                  d   |_	        | j                  |_
        |j                         |_        | j                  j                  |       d }|| _        y)z-
        Rest chord
        10 bytes
        RestChordMemberr   r   c                   d}i }| j                   D ]w  }|j                  |j                        g ||j                  <   ||j                     j                  |j                  t        |j                        z   |j                  z          y d}|D ]Y  }|t        |      dz
  k(  r!|d|z   dz   dj                  ||         z   z  }n |d|z   dz   dj                  ||         z   z  }|dz  }[ |S )	NrX  r   r   z|Dur2:z|Pos2:r[  rY  rZ  )
r   rM  r   r   r  r   r   r  r   r\  )r   r  r]  r   r   r^  s         r   r   z'NWCObject.restChordMember.<locals>.dump  s    EE%%99Q]]+3+-E!--(amm$++AOOc!%%j,H199,TU	 & AE
Q&X\H4sxxa7IIIEWq[72SXXeAh5GGGEQ  Lr   N)rd  r   r_  r`  ra  r   r   r   r   r   r   rF  r   r   r   )r:   rT  r   s      r   restChordMemberzNWCObject.restChordMember  s    
 	%	??dH---T8I8IJ

1ZZ
446

$	& r   N)r   r   r   r   )r   r   r   r   r<   rA   r  r"  r(  r,  r1  r6  r:  r=  rF  rP  rT  rd  rg  rj  rn  rr  rv  ry  r}  r  r  r   r   r   r   r     s    .,`*6<,	$** &PJX,/f'% ) '&###*"N ! "!%Jr   r   __main__)r   
__future__r   pathlibrK   typingr_  r   music21r   r   r   r   Environmentr   r	   Music21Exceptionr   r   r   r   r   mainTestr   r   r   <module>r     s   tj #        (&{&&'=>y 	)F)F 	V Vr
v vrW	 W	t zG r   