
    rh؉                       S r SSKJr  SSKJr  SSKrSSKrSSKr	SSK
r
SSKJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr   " S S\R2                  5      r " S S5      r " S S\R8                  5      r " S S\R8                  5      r\S:X  a  SSKr\R@                  " \5        gg)a  
A beta version of a complete .capx to music21 converter.

Currently only handles one <voice> per <staff> and does not deal with
Slurs, Dynamics, Ornamentation, etc.

Does not handle pickup notes, which are defined simply with an early barline
(same as incomplete bars at the end).
    )annotations)StringION)bar)chord)clef)common)duration)exceptions21)layout)key)meter)note)pitch)stream)tiec                      \ rS rSrSrg)CapellaImportExceptionO    N)__name__
__module____qualname____firstlineno____static_attributes__r       X/home/james-whalen/.local/lib/python3.13/site-packages/music21/capella/fromCapellaXML.pyr   r   O   s    r   r   c                  J   \ rS rSrSrS rS%S jrS rS&S jrS&S jr	S'S	 jr
S&S
 jrS&S jrS&S jrS rS rS rS rS rS rS rS r\R.                  \R0                  \R2                  \R4                  \R6                  S.rS rS rS rS r S r!SSSSSS S!.r"S" r#S# r$S$r%g)(CapellaImporterS   a  
Object for importing .capx, CapellaXML files into music21 (from which they can be
converted to musicxml, MIDI, lilypond, etc.)

Note that Capella stores files closer to their printed versions -- that is to say,
Systems enclose all the parts for that system and have new clefs etc.
c                .    S U l         S U l        S U l        g N)xmlTextzipFilenamemainDom)selfs    r   __init__CapellaImporter.__init__\   s    r   c                    U R                  U5        U R                  5         U R                  U R                  5      nUSL a  U$ U R	                  U5      nU$ )z
main program: opens a file given by filename and returns a complete
music21 Score from it.

If systemScore is True then it skips the step of making Parts from Systems
and Measures within Parts.
T)readCapellaXMLFileparseXMLTextsystemScoreFromScorer$   partScoreFromSystemScore)r%   filenamesystemScorescoreObj	partScores        r   scoreFromFileCapellaImporter.scoreFromFilea   sU     	),,T\\:$O55h?Ir   c                    [        U5      U l        [        R                  " [        U5      S5       nUR	                  S5      nSSS5        WU l        U$ ! , (       d  f       N= f)z
Reads in a .capx file at `filename`, stores it as self.zipFilename, unzips it,
extracts the score.xml embedded file, sets self.xmlText to the contents.

Returns self.xmlText
rz	score.xmlN)strr#   zipfileZipFilereadr"   )r%   r-   zipFileHandler"   s       r   r)   "CapellaImporter.readCapellaXMLFiler   sN     x=__S]C0M#((5G 1 10s   A
A"Nc                   Uc  U R                   n[        U[        5      (       d  UR                  S5      n[        R
                  R                  R                  [        U5      5      nU H;  u  p4SUR                  ;   d  M  UR                  R                  SS5      S   Ul	        M=     UR                  U l        U R                  $ )z
Takes the string (or unicode string) in xmlText and parses it with `xml.etree`.
Sets `self.mainDom` to the dom object and returns the dom object.
zutf-8}   )r"   
isinstancer5   decodexmletreeElementTree	iterparser   tagsplitrootr$   )r%   r"   itunusedels        r   r*   CapellaImporter.parseXMLText   s    
 ?llG'3''nnW-GYY"",,Xg->?JFbff}c1-a0  ww||r   c                T    [         R                  R                  R                  U5      $ )a  
Utility method, especially for the documentation examples/tests, which uses
`xml.etree.ElementTree` to parse the string and returns its root object.

Not used by the main parser

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> funnyTag = ci.domElementFromText(
...    '<funny yes="definitely"><greg/>hi<greg><ha>ha</ha>' +
...    '<greg type="embedded"/></greg></funny>')
>>> funnyTag
<Element 'funny' at 0x...>

iter searches recursively

>>> len(list(funnyTag.iter('greg')))
3

findall does not:

>>> len(funnyTag.findall('greg'))
2
)r@   rA   rB   
fromstring)r%   r"   s     r   domElementFromText"CapellaImporter.domElementFromText   s    0 yy$$//88r   c           	     |   UR                  [        R                  5      n0 nU H  nUR                  U5      nUR                  [        R
                  5      n[        U5       H  u  pxUR                  U;  a7  [        R
                  " 5       n	UR                  U	l        XS.X8R                  '   OX8R                     S   n	U H6  n
U	R                  [        R                  " U
R                  U-   5      U
5        M8     U	R                  5         M     M     [        R                  " 5       n[        [        U5      5       Vs/ s H  nSPM     nnU H  nX>   nUS   XS   '   M     U H  nUc  [!        S5        M  UR                  ["        R$                  5      nUR                  [&        R(                  5      nSnSnU H  nUU:X  a  UR+                  U5        M  UnM      U H  nUU:X  a  UR+                  U5        M  UnM      UR-                  SS9  UR                  SU5        M     UR                  5         U$ s  snf )	z
Take a :class:`~music21.stream.Score` object which is organized
by Systems and return a new `Score` object which is organized by
Parts.
)partnumberrP   NrQ   z#part entries do not match partDict!T)inPlacer   )getElementsByClassr   SystemelementOffsetr   Part	enumerateid
coreInsertr   opFracoffsetcoreElementsChangedScorerangelenprintr   Clefr   KeySignatureremovemakeMeasures)r%   r.   systemStreampartDictById
thisSystemsystemOffset
partStreamjthisPartnewPartrI   newScoreipartspartIdpartDictpclefskeySignatureslastCleflastKeySignatureckss                          r   r,   (CapellaImporter.partScoreFromSystemScore   s     #55fmmD8:&J '44Z@L#66v{{CJ(4;;l2$kkmG!)GJ9@0NL-*;;7?G"B&&v}}RYY5M'NPRS #++-  5 ' <<>7<S=N7O(P7O!7O(P"F#+H(0(8E8$% # Ay;<((3E001A1ABMH#=HHQK H	 
 $))HHRL')$	 $
 NN4N( 1%? @ 	$$&K )Qs   >H9c                   Uc  [         R                  " 5       nUR                  S5      nU(       d  [        S5      e[	        U5      S:  a  [        S5      eUS   nUR                  S5      nU(       d  [        S5      e[        U5       H1  u  pgU R                  U5      nUS-   Ul        UR                  U5        M3     UR                  5         U$ )a(  
returns an :class:`~music21.stream.Score` object from a <score> tag.

The Score object is not a standard music21 Score object which contains
parts, then measures, then voices, but instead contains systems which
optionally contain voices, which contain parts.  No measures have yet
been created.
systemsz1Cannot find a <systems> tag in the <score> objectr=   zMFound more than one <systems> tag in the <score> object, what does this mean?r   systemzHCannot find any <system> tags in the <systems> tag in the <score> object)
r   r]   findallr   r_   rW   systemFromSystemsystemNumber
coreAppendr\   )	r%   scoreElementr/   systemsListsystemsElement
systemListr   rg   	systemObjs	            r   r+   $CapellaImporter.systemScoreFromScore   s     ||~H"**95(CE E{a(_a a$Q#++H5
(Z\ \ )2*(=$L--j9I%1A%5I"	* )>
 	$$&r   c                   Uc  [         R                  " 5       nUR                  S5      nU(       d  [        S5      e[	        U5      S:  a  [        S5      eUS   nUR                  S5      nU(       d  [        S5      eU GH  nSnS	UR
                  ;   a  UR
                  S	   n[        R                  " 5       nXxl        UR                  S
5      n	U	(       d  [        S5      eU	S   n
U
R                  S5      nU(       d  [        S5      e[	        U5      S:X  aX  US   nUR                  S5      nU(       d  [        S5      e[	        U5      S:  a  [        S5      eUS   nU R                  X5        UR                  SU5        GM     U$ )z
returns a :class:`~music21.stream.System` object from a <system> tag.
The System object will contain :class:`~music21.stream.Part` objects
which will have the notes, etc. contained in it.

TODO: Handle multiple <voices>
stavesz.No <staves> tag found in this <system> elementr=   z9More than one <staves> tag found in this <system> elementr   staffzFNo <staff> tag found in the <staves> element for this <system> elementUnknownPartr   voicesz[No <voices> tag found in the <staff> tag for the <staves> element for this <system> elementvoicezoNo <voice> tag found in the <voices> tag for the <staff> tag for the <staves> element for this <system> elementnoteObjectszNo <noteObjects> tag found in the <voice> tag found in the <voices> tag for the <staff> tag for the <staves> element for this <system> elementzMore than one <noteObjects> tag found in the <voice> tag found in the <voices> tag for the <staff> tag for the <staves> element for this <system> element)r   rT   r}   r   r_   attribr   rV   rX   streamFromNoteObjectsinsert)r%   systemElementr   
stavesListstavesElement	staffListthisStaffElementrp   partObj
voicesListvoicesElement	voiceListthisVoiceElementnoteObjectsListthisNoteObjects                  r   r~    CapellaImporter.systemFromSystem  s    I"**84
()YZZz?Q(KM M"1!))'2	(XZ Z )"F+222)00:kkmGJ)11(;J,23 3 'qMM%--g6I,CD D 9~"#,Q< "2":":="I&023 3 '!+067 7 "1!3**>CQ(E !*F r   c                   Uc  [         R                  " 5       nOUnU R                  U R                  U R                  U R
                  U R                  U R                  S.nU Hw  nSnUR                  nXt;  a  [        SU 35        M&  XG   " U5      n[        U[        5      (       a  U H  nUR                  U5        M     Ma  Uc  Mf  UR                  U5        My     UR                  5         U$ )aJ  
Converts a <noteObjects> tag into a :class:`~music21.stream.Stream` object
which is returned.
A Stream can be given as an optional argument, in which case the objects of this
Stream are appended to this object.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> noteObjectsString = r"""
...           <noteObjects>
...                <clefSign clef="G2-"/>
...                <keySign fifths="-1"/>
...                <chord>
...                    <duration base="1/2"/>
...                    <lyric>
...                        <verse i="0">das,</verse>
...                        <verse i="1">scherz,</verse>
...                    </lyric>
...                    <heads>
...                        <head pitch="G4"/>
...                    </heads>
...                </chord>
...                <chord>
...                    <duration base="1/2"/>
...                    <lyric>
...                        <verse i="0">so</verse>
...                        <verse i="1">der</verse>
...                    </lyric>
...                    <heads>
...                        <head pitch="A4"/>
...                    </heads>
...                </chord>
...                <barline type="end"/>
...            </noteObjects>
...            """
>>> noteObjectsElement = ci.domElementFromText(noteObjectsString)
>>> streamObj = ci.streamFromNoteObjects(noteObjectsElement)
>>> streamObj.show('text')
{0.0} <music21.clef.Treble8vbClef>
{0.0} <music21.key.KeySignature of 1 flat>
{0.0} <music21.note.Note G>
{2.0} <music21.note.Note A>
{4.0} <music21.bar.Barline type=final>

>>> streamObj.highestTime
4.0
N)clefSignkeySigntimeSignrestr   barlinezUnknown tag type: )r   StreamclefFromClefSignkeySignatureFromKeySigntimeSignatureFromTimeSignrestFromRestchordOrNoteFromChordbarlineListFromBarlinerD   r`   r>   listr   r\   )	r%   noteObjectsElement	streamObjsmappingdrI   dTagelSubs	            r   r   %CapellaImporter.streamFromNoteObjectsH  s    ` AA#44"::#==,, 55"99 $AB55D"*4&12]1%b$''!#U+ "$ZLL$ $ 	
r   c                    [         R                  " 5       nUR                  S5      nU R                  US   5      Ul        U$ )a"  
Returns a :class:`~music21.rest.Rest` object from a <rest> tag.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> restElement = ci.domElementFromText('<rest><duration base="1/2"/></rest>')
>>> r = ci.restFromRest(restElement)
>>> r
<music21.note.Rest half>
>>> r.duration.type
'half'
r	   r   )r   Restr}   durationFromDurationr	   )r%   restElementr4   durationLists       r   r   CapellaImporter.restFromRest  s:     IIK"**:6..|A?
r   c                   UR                  S5      nUR                  S5      n[        U5      S:w  d  [        U5      S:w  a  [        S5      eU R                  US   5      nSnU(       d  [        S5      e[        U5      S:X  a  US   nO[        R
                  " U5      nU R                  US   5      Ul        UR                  S5      nU(       a  U R                  US   5      nXel	        U$ )a?  
returns a :class:`~music21.note.Note` or :class:`~music21.chord.Chord`
from a chordElement -- a `Note`
is returned if the <chord> has one <head> element, a `Chord` is
returned if there are multiple <head> elements.


>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> chordElement = ci.domElementFromText(
...     '<chord><duration base="1/1"/><heads><head pitch="G4"/></heads></chord>')
>>> n = ci.chordOrNoteFromChord(chordElement)
>>> n
<music21.note.Note G>
>>> n.duration
<music21.duration.Duration 4.0>

This one is an actual chord

>>> chordElement = ci.domElementFromText(
...        '<chord><duration base="1/8"/>' +
...        '<heads><head pitch="G4"/><head pitch="A5"/></heads></chord>')
>>> c = ci.chordOrNoteFromChord(chordElement)
>>> c
<music21.chord.Chord G3 A4>
>>> c.duration
<music21.duration.Duration 0.5>
r	   headsr=   zMalformed chord!r   Nlyric)
r}   r_   r   notesFromHeadsr   Chordr   r	   lyricListFromLyriclyrics)r%   chordElementr   	headsList	notesListnoteOrChord
lyricsLists          r   r   $CapellaImporter.chordOrNoteFromChord  s    < $++J7 ((1	|!S^q%8();<<''	!5	();<<y>Q#A,K++i0K#88aI!))'2
00A?J!+r   c                ~    / nUR                  S5      nU H#  nUR                  U R                  U5      5        M%     U$ )aZ  
returns a list of :class:`~music21.note.Note` elements for each <head> in <heads>

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> headsElement = ci.domElementFromText(
...    '<heads><head pitch="B7"><alter step="-1"/></head><head pitch="C2"/></heads>')
>>> ci.notesFromHeads(headsElement)
[<music21.note.Note B->, <music21.note.Note C>]
head)r}   appendnoteFromHead)r%   headsElementnotesheadDomListheadElements        r   r   CapellaImporter.notesFromHeads  s?     "**62&KLL**;78 'r   c                   SUR                   ;  a  [        S5      eUR                   S   n[        R                  " 5       nX#l        UR
                  S-
  Ul        UR                  S5      n[        U5      S:  a  [        S5      e[        U5      S:X  a$  U R                  US   5      nXSR                  l
        UR                  S5      n[        U5      S:  a  [        S5      e[        U5      S:X  a  U R                  US   5      nXsl        U$ )	a)  
return a :class:`~music21.note.Note` object from a <head> element.  This will become
part of Chord._notes if there are multiple, but in any case, it needs to be a Note
not a Pitch for now, because it could have Tie information

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> headElement = ci.domElementFromText(
...      '<head pitch="B7"><alter step="-1"/><tie end="true"/></head>')
>>> n = ci.noteFromHead(headElement)
>>> n
<music21.note.Note B->
>>> n.octave  # capella octaves are one higher than written
6
>>> n.tie
<music21.tie.Tie stop>
r   z.Cannot deal with <head> element without pitch!r=   alterz+Cannot deal with multiple <alter> elements!r   r   z)Cannot deal with multiple <tie> elements!)r   r   r   NotenameWithOctaveoctaver}   r_   accidentalFromAlterr   
accidental
tieFromTier   )r%   r   noteNameWithOctavenaltersacctiesthisTies           r   r   CapellaImporter.noteFromHead  s    $ +,,,()YZZ(//8IIK-88a<$$W-v;?()VWWv;!**6!95C!$GG""5)t9q=()TUUt9>ood1g.GEr   c                    SUR                   ;   a  [        UR                   S   5      nO[        S5        Sn[        R                  " U5      nSUR                   ;   a  UR                   S   S:X  a  SUl        U$ )a  
return a :class:`~music21.pitch.Accidental` object from an <alter> tag.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> alter = ci.domElementFromText('<alter step="-1"/>')
>>> ci.accidentalFromAlter(alter)
<music21.pitch.Accidental flat>

The only known display type is "suppress"

>>> alter = ci.domElementFromText('<alter step="2" display="suppress"/>')
>>> accidentalObject = ci.accidentalFromAlter(alter)
>>> accidentalObject
<music21.pitch.Accidental double-sharp>
>>> accidentalObject.displayType
'never'
stepzNo alteration...r   displaysuppressnever)r   intr`   r   
AccidentaldisplayType)r%   alterElement
alterationr   s       r   r   #CapellaImporter.accidentalFromAlter  sr    $ \(((\0089J$%Jz*+++0C0CI0NR\0\%CO
r   c                   SnSnSUR                   ;   a  UR                   S   S:X  a  SnSUR                   ;   a  UR                   S   S:X  a  SnSnUSL a  USL a  SnOUSL a  SnO	USL a  S	nOg[        R                  " U5      nU$ )
a`  
returns a :class:`~music21.tie.Tie` element from a <tie> tag

if begin == 'true' then Tie.type = start


>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> tieEl = ci.domElementFromText('<tie begin="true"/>')
>>> ci.tieFromTie(tieEl)
<music21.tie.Tie start>

if end == 'true' then Tie.type = stop

>>> tieEl = ci.domElementFromText('<tie end="true"/>')
>>> ci.tieFromTie(tieEl)
<music21.tie.Tie stop>

if begin == 'true' and end == 'true' then Tie.type = continue (is this right???)

>>> tieEl = ci.domElementFromText('<tie begin="true" end="true"/>')
>>> ci.tieFromTie(tieEl)
<music21.tie.Tie continue>
FbegintrueTendNcontinuestartstop)r   r   Tie)r%   
tieElementr   r   tieTypetieObjs         r   r   CapellaImporter.tieFromTie;  s    0 j'''J,=,=g,F&,PEJ%%%**;*;E*Bf*LCD=SD[ Gd]GD[G!r   c                    / nUR                  S5      nU H*  nU R                  U5      nUc  M  UR                  U5        M,     U$ )a  
returns a list of :class:`~music21.note.Lyric` objects from a <lyric> tag


>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> lyricEl = ci.domElementFromText(
...      '<lyric><verse i="0" hyphen="true">di</verse>' +
...      '<verse i="1">man,</verse><verse i="2">frau,</verse></lyric>')
>>> ci.lyricListFromLyric(lyricEl)
[<music21.note.Lyric number=1 syllabic=begin text='di'>,
 <music21.note.Lyric number=2 syllabic=single text='man,'>,
 <music21.note.Lyric number=3 syllabic=single text='frau,'>]
verse)r}   lyricFromVerser   )r%   lyricElement	lyricListversesr   	thisLyrics         r   r   "CapellaImporter.lyricListFromLyricg  sO     	%%g.A++A.I$  +  r   c                   SnSnSUR                   ;   a  [        UR                   S   5      S-   nSUR                   ;   a  UR                   S   S:X  a  SnUR                  nUb  US:X  a  g[        R                  " XBUS	S
9nU$ )ag  
returns a :class:`~music21.note.Lyric` object from a <verse> tag

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> verse = ci.domElementFromText('<verse i="0" hyphen="true">di&quot;</verse>')
>>> ci.lyricFromVerse(verse)
<music21.note.Lyric number=1 syllabic=begin text='di"'>

Does not yet support 'align' attribute

if the text is empty, returns None
r=   singlern   hyphenr   r   N T)textrQ   syllabicapplyRaw)r   r   r  r   Lyric)r%   r   verseNumberr  r  r   s         r   r   CapellaImporter.lyricFromVerse}  s     %,,ell3/014Ku||#X(>&(HHzz<42:JJDxZ^_ELr   )treblebassaltotenorzG2-c                l   SUR                   ;   a  UR                   S   nX R                  ;   a  U R                  U   " 5       $ US   S:X  a  [        R                  " 5       $ [	        U5      S:  aE  USS nSn[	        U5      S:  a  US   S:X  a  SnOUS   S:X  a  Sn[        R
                  " X45      nU$ g	)
a`  
returns a :class:`~music21.clef.Clef` object or subclass from a <clefSign> tag.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> clefSign = ci.domElementFromText('<clefSign clef="treble"/>')
>>> ci.clefFromClefSign(clefSign)
<music21.clef.TrebleClef>

>>> clefSign = ci.domElementFromText('<clefSign clef="G2-"/>')
>>> ci.clefFromClefSign(clefSign)
<music21.clef.Treble8vbClef>

>>> clefSign = ci.domElementFromText('<clefSign clef="F1+"/>')
>>> clefObject = ci.clefFromClefSign(clefSign)
>>> clefObject
<music21.clef.FClef>
>>> clefObject.sign
'F'
>>> clefObject.line
1
>>> clefObject.octaveChange
1
r   r   rr   r=      +-N)r   clefMappingr   PercussionClefr_   clefFromString)r%   r   	clefValueclefSignAndLineclefOctaveChangeclefObjs         r   r    CapellaImporter.clefFromClefSign  s    2 X__$ /I,,,''	2441$**,,Y!#"+Aa.#$ y>A% |s*+,("1,+-(--oPr   c                    SUR                   ;   a.  [        UR                   S   5      n[        R                  " U5      $ g)a  
Returns a :class:`~music21.key.KeySignature` object from a keySign tag.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> keySign = ci.domElementFromText('<keySign fifths="-1"/>')
>>> ci.keySignatureFromKeySign(keySign)
<music21.key.KeySignature of 1 flat>
fifthsN)r   r   r   rb   )r%   r   	keyFifthss      r   r   'CapellaImporter.keySignatureFromKeySign  s9     w~~%GNN845I##I.. &r   c                |    SUR                   ;   a,  UR                   S   nUS:w  a  [        R                  " U5      $ gg)a  
Returns a :class:`~music21.meter.TimeSignature` object from a timeSign tag.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> timeSign = ci.domElementFromText('<timeSign time="4/4"/>')
>>> ci.timeSignatureFromTimeSign(timeSign)
<music21.meter.TimeSignature 4/4>

>>> timeSign = ci.domElementFromText('<timeSign time="infinite"/>')
>>> ci.timeSignatureFromTimeSign(timeSign) is None
True
timeinfiniteN)r   r   TimeSignature)r%   r   
timeStrings      r   r   )CapellaImporter.timeSignatureFromTimeSign  s=     X__$!0JZ'**:66r   c                   [         R                  " 5       nSUR                  ;   aR  UR                  S   nUR                  S5      nUS:w  a,  [	        USU 5      n[	        X4S-   S 5      nSU-  U-  nXrl        SUR                  ;   a  [	        UR                  S   5      nXl        UR                  S	5      n	U	 H%  n
U R                  U
5      nUR                  U5        M'     U$ )
a  
Return a music21.duration.Duration element from an XML Element representing
a duration.

>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> durationTag = ci.domElementFromText('<duration base="1/32" dots="1"/>')
>>> durationObj = ci.durationFromDuration(durationTag)
>>> durationObj
<music21.duration.Duration 0.1875>
>>> durationObj.type
'32nd'
>>> durationObj.dots
1

Here with Tuplets

>>> durationTag2 = ci.domElementFromText(
...      '<duration base="1/4"><tuplet count="3"/></duration>')
>>> d2 = ci.durationFromDuration(durationTag2)
>>> d2
<music21.duration.Duration 2/3>
>>> d2.type
'quarter'
>>> d2.tuplets
(<music21.duration.Tuplet 3/2>,)


Does not handle noDuration='true', display, churchStyle on rest durations
base/r  r   r=   Ng      @dotstuplet)
r	   Durationr   findr   quarterLengthr&  r}   tupletFromTupletappendTuplet)r%   durationElementdur	baseValue
slashIndexfirstNumbersecondNumberr*  	dotNumbertupletsr   r'  s               r   r   $CapellaImporter.durationFromDuration  s    < !_+++'..v6I",JR!)Aj"9:"9!^_#=>!${!2l B$1!_+++O226:;I H!))(3A**1-FV$  
r   c                B   SnSnSUR                   ;   a1  [        UR                   S   5      nSnX#S-  :  a  US-  nX#S-  :  a  M  SUR                   ;   a  UR                   S   S:X  a  US-  nSUR                   ;   a  [        S5        [        R                  " X#5      nU$ )a   
Returns a :class:`~music21.duration.Tuplet` object from a <tuplet> tag.


>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> tupletTag = ci.domElementFromText('<tuplet count="3"/>')
>>> ci.tupletFromTuplet(tupletTag)
<music21.duration.Tuplet 3/2>

does not handle 'tripartite' = True
r=   countr  prolongr   
tripartitezOWE DON'T HANDLE TRIPARTITE YET! Email the file and a pdf so I can figure it out)r   r   r`   r	   Tuplet)r%   tupletElement	numeratordenominatortups        r   r+   CapellaImporter.tupletFromTuplet(  s     	m***M009:IKAo-q  Ao-,,,1E1Eg1NRX1X1K=///ac ooi5
r   normaldoublefinalr   r   z	end-start)r   rA  r   repEndrepBeginrepEndBeginc                D   / nSnSUR                   ;   Ga
  UR                   S   nUR                  S5      (       a  X@R                  ;   a  U R                  U   nUR                  S5      S:  a'  UR	                  [
        R                  " S5      5        SnUR                  S5      S:  a3  [
        R                  " S5      nUSL a  SUl        UR	                  U5        U$ X@R                  ;   a2  UR	                  [
        R                  " U R                  U   5      5        U$ )	a  
Indication that the barline at this point should be something other than normal.

Capella does not indicate measure breaks or barline breaks normally, so the only barlines
that are indicated are unusual ones.

Returns a LIST of :class:`~music21.bar.Barline` or :class:`~music21.bar.Repeat` objects
because the `repEndBegin` type requires two `bar.Repeat` objects to encode in `music21`.


>>> ci = capella.fromCapellaXML.CapellaImporter()
>>> barlineTag = ci.domElementFromText('<barline type="end"/>')
>>> ci.barlineListFromBarline(barlineTag)
[<music21.bar.Barline type=final>]

>>> repeatTag = ci.domElementFromText('<barline type="repEndBegin"/>')
>>> ci.barlineListFromBarline(repeatTag)
[<music21.bar.Repeat direction=end>, <music21.bar.Repeat direction=start>]

Ftyperepr   r  Tr   r=   )	r   
startswith
barlineMapr)  r   r   RepeatpriorityBarline)r%   barlineElementbarlineListhasRepeatEndbarlineType
repeatTypestartReps          r   r   &CapellaImporter.barlineListFromBarlineM  s    * ^***(//7K%%e,,//1!%!=J!u-2#**3::e+<='+!w/"4#&::g#6'4/01H-#**84
  //1&&s{{4??;3O'PQr   c                    g)z
not implemented
Nr   )r%   drawObjs     r   slurFromDrawObjSlur#CapellaImporter.slurFromDrawObjSlurw  s     	r   )r$   r"   r#   )Fr!   )r.   stream.ScorereturnrY  )&r   r   r   r   __doc__r&   r1   r)   r*   rM   r,   r+   r~   r   r   r   r   r   r   r   r   r   r   
TrebleClefBassClefAltoClef	TenorClefTreble8vbClefr  r   r   r   r   r+  rJ  r   rW  r   r   r   r   r   r   S   s    
" 94@D D9vM^$6p"*X:*X,> "__==== NN,,	K*X/.2h: %$ !%!,J(Tr   r   c                      \ rS rSrS rSrg)Testi~  c                   SSK Jn  [        5       n[        R                  " 5       S-  nUS-  nUR                  U5      nU R                  [        UR                  5      S5        U R                  [        UR                  5       R                  5      S5        U R                  SUR                  UR                  S   S5      5        U R                  S	UR                  UR                  S   S
5      5        g )Nr   )r  capellaNu_rue_mit_sorgen.capx      zmass!r=   scherzr  )music21r  r   r   getSourceFilePathr1   assertEqualr_   ro   assertGreaterrecurser   assertInassembleLyrics)r%   r  cicapellaDirPath
oswaldPathr0   s         r   testCompleteTest.testComplete  s     113i?#&??
$$Z0	Y__-q13y0028892>gt229??13EqIJh 3 3IOOA4F JKr   r   N)r   r   r   r   rs  r   r   r   r   rb  rb  ~  s    
Lr   rb  c                  $    \ rS rSrSrS rS rSrg)TestExternali  Tc                    [        5       n[        R                  " 5       S-  nUS-  nUR                  U5      nU R                  (       a  UR	                  5         g g Nrd  re  )r   r   rj  r1   show)r%   rp  rq  rr  r0   s        r   rs  TestExternal.testComplete  sN    113i?#&??
$$Z0	99NN r   c                D   [        5       n[        R                  " 5       S-  nUS-  nUR                  U5        UR	                  5         UR                  UR                  R                  5      nUR                  U5      nU R                  (       a  UR                  5         g g rx  )
r   r   rj  r)   r*   r+   r$   documentElementr,   ry  )r%   rp  rq  rr  r/   r0   s         r   xtestImportSorgenTestExternal.xtestImportSorgen  s    113i?#&??

j)

 **2::+E+EF//9	99NN r   r   N)r   r   r   r   ry  rs  r}  r   r   r   r   rv  rv    s    Dr   rv  __main__)!r[  
__future__r   ior   typingtunittestxml.etree.ElementTreer@   r6   ri  r   r   r   r   r	   r
   r   r   r   r   r   r   r   Music21Exceptionr   r   TestCaserb  rv  r   mainTestr   r   r   <module>r     s    #                   N	\:: 	h hVL8 L8$$ < zT r   