# -*- coding: ISO-8859-1 -*-
""" capellaScript -- 27.12.2007 Hans H. Lampe
>>> Transponieren von Instrumenten-Stimmungen
    Mit diesem Skript wird die Stimmung eines Blasinstruments in die Stimmung eines
    anderen Blasinstruments transponiert.|

    Noten außerhalb des Tonumfangs des Zielinstruments werden farbig markiert und
    auf Wunsch automatisch oktaviert.||

    Durch Positionierung des Cursors wird die Notenzeile des Instruments vorbestimmt.||
      
    Bei Orchester-Instrumenten - wie Trompeten, Hörner und Pauken - können auf Wunsch die Tonartvorzeichnungen
    autom. entfernt werden.||

    Bitte die "Dokumentation" (unten) beachten.||


    Rückmeldungen bitte an Hans H. Lampe:|HansHermann.Lampe@t-online.de        
<<<

    Die Transposition erfolgt in zwei Schritten: Zuerst wird von der aktuellen Tonart zur
    "klingenden Tonart" transponiert und danach zur "notierten" Tonart des "Zielinstruments".
    Zusätzliche Oktavierungen können bei Bedarf gleich mit durchgeführt werden oder in einem
    zweiten Durchgang ohne Transposition erfolgen.
    In jedem dieser zwei Durchgänge werden zuerst die Vorzeichnungen gesetzt und daran anschließend
    die Noten transponiert. Die erste Vorzeichnung wird für die erste Noten-Transposition gespeichert. Nach jeder Note
    wird das nächste Element auf "keySign" geprüft und falls vorhanden übernommen.

    Zusätzliche Funktionen:
    - optionale Oktavierung
    - optionales Entfernen von Tonartvorzeichnungen
    - Aufhebbares Eingrenzen der Tonartvorzeichen auf maximal 6

    007.08.2007 Fehler in der Anzeigesteuerung für rote Noten beseitigt

    NEU in Version 2.2:
    - auf Wunsch werden die farbigen (roten, bzw. blauen) Noten außerhalb des Tonbereichs des Zielinstruments oktaviert

    NEU in Version 2.3:
    - 2 "Blech-Instrumente in C" sind für "klingende" Notierung hinzugefügt worden.

    NEU in Version 2.4:
    - die folgendn Instrumente sind in Abstimmung mit Frau Ninnemann und Herrn Singer entfernt worden:
      Trompete in F, Doppelhorn in B/F, Althorn, Basstrompete, Altposaune (die Basstuba in Es wollte Herr Singer behalten)
    - die folgenden Instrumente wurden neu aufgenommen: Bassposaune, Bariton in C, Tuba in B und C, Basstuba in F
    - Anpassung der Tuben-Namen an den capella-Partitur-Assistenten: Bass-Tuba -> Tuba, Kontrabass-Tuba -> Bass-Tuba
    - Unterstützung des Tenor-Schlüssels für die Tenorposaune (Wunsch von Frau Ninnemann)

    - Korrektur: Auflösezeichen führen nicht mehr zu Absturz des Skripts (18.02.08)

    NEU in Version 2.5:
    -  Implementierung des "Fagottino in G"
    -  01.07.09: +/-1 Oktave beim Fagottino für "Ziel"-Instrumente mit Violinschlüssel

    NEU in Version 2.6:
    -  Implementierung des "Fagottino in F"

    NEU in Version 2.7:
    -  Doppeltes Generieren des Elements "alter" beseitigt (Zeile 303 und 446). (Hinweis von Herrn Jungmann)
    NEU in Version 2.8 (15.11.2017):
    - Anpassung an capella 8 - Python 2.7 (Villiger)
      
                                 
"""

from caplib.capDOM import ScoreChange
import xml.dom.minidom
DOC = xml.dom.minidom.Document
import tempfile, codecs


def addNewChildNode(el,tagName):
    global doc
    #newChild = doc.createElement(tagName)
    newChild = el.ownerDocument.createElement(tagName) # lt. Prof. Ring (eMail)
    el.appendChild(newChild)
    return newChild

def nextSiblingElement(element): 
    sibling = element.nextSibling 
    while sibling and sibling.nodeType != element.ELEMENT_NODE: 
        sibling = sibling.nextSibling 
    return sibling 

def insertAfter(parent, newChild, refChild): 
    next = nextSiblingElement(refChild) 
    if next: 
        parent.insertBefore(newChild, next) 
    else: 
        parent.appendChild(newChild)
           

def transpose(score):
           
    # --------- Stimmung transponieren für 0 bis 5 Kreuze(Pitch - Oktave: 0=-1, 1=0, 2=+1, Alteration mit Kreuzen) ---------- #

    pitchTable1a = {'C':('C0','0','C0','1','D0','0','D0','1','E0','0','F0','0','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0',\
                        'C1','0','C1','1','D1','0','D1','1','E1','0','F1','0','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0'),

                   'D':('D0','0','D0','1','E0','0','F0','0','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1',\
                        'D1','0','D1','1','E1','0','F1','0','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1'),

                   'E':('E0','0','F0','0','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1',\
                        'E1','0','F1','0','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1'),                    

                   'F':('F0','0','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0',\
                        'F1','0','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0'),

                   'G':('G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','F1','0','F1','1',\
                        'G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','F2','0','F2','1'),

                   'A':('A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','F1','0','F1','1','G1','0','G1','1',\
                        'A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','F2','0','F2','1','G2','0','G2','1'),

                   'B':('B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','F1','0','F1','1','G1','0','G1','1','A1','0','A1','1',\
                        'B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','F2','0','F2','1','G2','0','G2','1','A2','0','A2','1')}


    # --------- für 6 Kreuze (eis) ------------------------------------------------------------------------------------------------- # 

    pitchTable1b = {'C':('C0','0','C0','1','D0','0','D0','1','E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0',\
                        'C1','0','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0'),

                   'D':('D0','0','D0','1','E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1',\
                        'D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1'),

                   'E':('E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1',\
                        'E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1'),                    

                   'F':('E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0',\
                        'E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0'),

                   'G':('G0','0','G0','1','A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1',\
                        'G1','0','G1','1','A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1'),

                   'A':('A0','0','A0','1','B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1',\
                        'A1','0','A1','1','B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1','G2','0','G2','1'),

                   'B':('B0','0','C1','0','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1',\
                        'B1','0','C2','0','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1','G2','0','G2','1','A2','0','A2','1')}


    # --------- für 7 Kreuze (eis und his) ----------------------------------------------------------------------------------------- #

    pitchTable1c = {'C':('B0','1','C0','1','D0','0','D0','1','E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0',\
                        'B0','1','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0'),

                   'D':('D0','0','D0','1','E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','B0','1','C1','1',\
                        'D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','B1','1','C2','1'),

                   'E':('E0','0','E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','B0','1','C1','1','D1','0','D1','1',\
                        'E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','B1','1','C2','1','D2','0','D2','1'),                    

                   'F':('E0','1','F0','1','G0','0','G0','1','A0','0','A0','1','B0','0','B0','1','C1','1','D1','0','D1','1','E1','0',\
                        'E1','1','F1','1','G1','0','G1','1','A1','0','A1','1','B1','0','B1','1','C2','1','D2','0','D2','1','E2','0'),

                   'G':('G0','0','G0','1','A0','0','A0','1','B0','0','B0','1','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1',\
                        'G1','0','G1','1','A1','0','A1','1','B1','0','B1','1','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1'),

                   'A':('A0','0','A0','1','B0','0','B0','1','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1',\
                        'A1','0','A1','1','B1','0','B1','1','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1','G2','0','G2','1'),

                   'B':('B0','0','B0','1','C1','1','D1','0','D1','1','E1','0','E1','1','F1','1','G1','0','G1','1','A1','0','A1','1',\
                        'B1','0','B1','1','C2','1','D2','0','D2','1','E2','0','E2','1','F2','1','G2','0','G2','1','A2','0','A2','1')}


    # --------- Stimmung transponieren für 1 bis 5 Bes (Pitch - Oktave, Alteration mit Bes) ---------- #

    pitchTable2a = {'C':('C0','0','D0','-1','D0','0','E0','-1','E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','B0','0',\
                        'C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','B1','0'),

                   'D':('D0','0','E0','-1','E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','B0','0','C1','0','D1','-1',\
                        'D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','B1','0','C2','0','D1','-1'),

                   'E':('E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','B0','0','C1','0','D1','-1','D1','0','E1','-1',\
                        'E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','B1','0','C2','0','D2','-1','D2','0','E2','-1'),                    

                   'F':('F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','B0','0','C1','0','D1','-1','D1','0','E1','-1','E1','0',\
                        'F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','B1','0','C2','0','D2','-1','D2','0','E2','-1','E2','0'),

                   'G':('G0','0','A0','-1','A0','0','B0','-1','B0','0','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1',\
                        'G1','0','A1','-1','A1','0','B1','-1','B1','0','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1'),

                   'A':('A0','0','B0','-1','B0','0','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1',\
                        'A1','0','B1','-1','B1','0','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1','G2','0','A2','-1'),

                   'B':('B0','0','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1',\
                        'B1','0','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1','G2','0','A2','-1','A2','0','B2','-1')}


    # --------- für 6 Bes (ces)-------------------------------------------------------------------------------------------------------- #

    pitchTable2b = {'C':('C0','0','D0','-1','D0','0','E0','-1','E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1',\
                        'C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1'),

                   'D':('D0','0','E0','-1','E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1',\
                        'D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D1','-1'),

                   'E':('E0','0','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1',\
                        'E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1'),                    

                   'F':('F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','E1','0',\
                        'F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','E2','0'),

                   'G':('G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1',\
                        'G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1'),

                   'A':('A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1',\
                        'A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1','G2','0','A2','-1'),

                   'B':('C1','-1','C1','0','D1','-1','D1','0','E1','-1','E1','0','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1',\
                        'C2','-1','C2','0','D2','-1','D2','0','E2','-1','E2','0','F2','0','G2','-1','G2','0','A2','-1','A2','0','B2','-1')}


    # --------- für 7 Bes (ces und fes) ---------------------------------------------------------------------------------------------- #

    pitchTable2c = {'C':('C0','0','D0','-1','D0','0','E0','-1','F0','-1','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1',\
                        'C1','0','D1','-1','D1','0','E1','-1','F1','-1','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1'),

                   'D':('D0','0','E0','-1','F0','-1','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1',\
                        'D1','0','E1','-1','F1','-1','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D1','-1'),

                   'E':('F0','-1','F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1',\
                        'F1','-1S','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1'),                    

                   'F':('F0','0','G0','-1','G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','F1','-1',\
                        'F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','E2','0'),

                   'G':('G0','0','A0','-1','A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','F1','-1','F1','0','G1','-1',\
                        'G1','0','A1','-1','A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','F2','-1','F2','0','G2','-1'),

                   'A':('A0','0','B0','-1','C1','-1','C1','0','D1','-1','D1','0','E1','-1','F1','-1','F1','0','G1','-1','G1','0','A1','-1',\
                        'A1','0','B1','-1','C2','-1','C2','0','D2','-1','D2','0','E2','-1','F2','-1','F2','0','G2','-1','G2','0','A2','-1'),

                   'B':('C1','-1','C1','0','D1','-1','D1','0','E1','-1','F1','-1','F1','0','G1','-1','G1','0','A1','-1','A1','0','B1','-1',\
                        'C2','-1','C2','0','D2','-1','D2','0','E2','-1','F2','-1','F2','0','G2','-1','G2','0','A2','-1','A2','0','B2','-1')}


    
    # ------ vom Ausgangsinstrument zum (fiktiven) C-Instrument ------ #
    #==================================================================#

    transposeFrom = fromInstr.value() # Position des "von-Instruments" in der Tabelle
    Instrparam = toCinstr[transposeFrom] # Instrumentenparameter aus Tabelle lesen
    keyFrInstr = Instrparam[0] # Tonartvorzeichnung für die Stimmung des "von-Instruments" (9=Instrument auswählen!)
    interval = Instrparam[1] # Transpositionsinterval in Halbtonschritten
    intOctToC = Instrparam[2] # zusätzliche interne Oktavierung zum Transpositionsinterval
    firstKey = 0 # für die Übernahmesteuerung der ersten Tonartvorzeichnung in die Transpositionsschleife für die einzelnen Töne   
    step = 0 # für die vorhandenen Alterationen
    
    for system in score.getElementsByTagName('system'):
        for staff in system.getElementsByTagName('staff'): # Aufsuchen der selektierten Notenzeile
            layout = staff.getAttribute('layout') 
            if layout != staffList[selStaff.value()]: 
                continue
            
            clefSign = staff.getElementsByTagName('clefSign')[0]
            next = nextSiblingElement(clefSign)
            if next != None: # leere Notenzeile (auch keine Taktangabe)
                next = next.tagName
                        

            # ------ Tonartvorzeichnungen für das C-Instrument setzen ------ #
         
            if next != 'keySign': # bei fehlender Tonartvorzeichnung wird "keySign" mit "fifths"='0' insertiert 
                keySign = doc.createElement('keySign')
                insertAfter(clefSign.parentNode, keySign, clefSign)
                keyCinstr = int(keyFrInstr)
                keySign.setAttribute('fifths',str('0'))
               
            for keySign in staff.getElementsByTagName('keySign'):
                fifths = keySign.getAttribute('fifths') # vorhandene Tonartvorzeichnung
                keyCinstr = int(fifths) + int(keyFrInstr) # die neue Tonartvorzeichnung
                            
                if firstKey == 0:
                    keyCinstrSave = keyCinstr # Speichern der ersten Tonartvorzeichnung für die Transpositionsschleife für die einzelnen Töne
                    firstKey = 1
                
                # ------ Begrenzung der Anzahl der Tonartvorzeichen ------ #

                if keyCinstr > maxVorz: # maximal 6#(Standard) oder 7#(auf Wunsch) Vorzeichen
                    keyCinstr = keyCinstr - 12
                if keyCinstr < -maxVorz: # maximal 6b(Standard) oder 7b(auf Wunsch) Vorzeichen
                    keyCinstr = keyCinstr + 12

                keySign.setAttribute('fifths',str(keyCinstr)) # Setzen der neuen Tonartvorzeichnung
                

            # ------ Transposition der einzelnen Töne ------ #

            keyCinstr = keyCinstrSave # Übernahme der gespeicherten ersten Tonartvorzeichnung in der Notenzeile
            firstKey = 0

            for head in staff.getElementsByTagName('head'):
                pitch = head.getAttribute('pitch')
                alter = head.getElementsByTagName('alter')
                
                if alter != []:
                    alter = head.getElementsByTagName('alter')[0]
                    step = alter.getAttribute('step')
                    if step =='': # Auflösungszeichen
                        step = 0
                else:
                    step = 0
                    alter = addNewChildNode(head,'alter')
                    
                octSave = pitch[1] # Speichern der Oktavziffer der aktuellen Note

                # ------ Begrenzung der Anzahl der Tonartvorzeichen ------ #
                
                if keyCinstr > maxVorz: # maximal 6#(Standard) oder 7#(auf Wunsch) Vorzeichen
                    keyCinstr = keyCinstr - 12
                if keyCinstr < -maxVorz: # maximal 6b(Standard) oder 7b(auf Wunsch) Vorzeichen
                    keyCinstr = keyCinstr + 12
                                      
                # ------ Selektieren der entsprechenden Tabelle und Tabellenzeile ------ #

                if 0 <= keyCinstr < 6: # Tonarten C - H
                    pitchTableX = pitchTable1a[pitch[0]]
                elif keyCinstr == 6: # Tonart Fis
                    pitchTableX = pitchTable1b[pitch[0]] # mit eis
                elif keyCinstr == 7: # Tonart Cis
                    pitchTableX = pitchTable1c[pitch[0]] # mit eis und his
                elif -1 >= keyCinstr > -6:
                    pitchTableX = pitchTable2a[pitch[0]]
                elif keyCinstr == -6: # Tonart Ges
                    pitchTableX = pitchTable2b[pitch[0]] # mit eis
                elif keyCinstr == -7: # Tonart Ces
                    pitchTableX = pitchTable2c[pitch[0]] # mit eis und his
                else:
                    messageBox('Falsche C-Instr-Tonart', str(keyCinstr))
                    
                pitch = pitchTableX[2*12 + 2*interval + 2*int(step)] # Auslesen des neuen Tones einschließlich Oktavierung
                pitchX = pitch[0] # der neue Ton
                octaveX = pitch[1] # eine möglich Oktavierung, um +/-1 Oktave 
                octaveX = int(octaveX) + int(octSave) - 1 # resultierende Oktavierung
                octaveX = str(octaveX)
                head.setAttribute('pitch',pitchX + octaveX) # Setzen des Tones mit seiner Oktave (z.B. C5 für c')
                alter.setAttribute('step',pitchTableX[2*12 + 2*interval+1 + 2*int(step)]) # Setzen der resultierenden Alteration

                parentNode = head.parentNode # heads-Ebene
                parentNode = parentNode.parentNode # chord/keySign-Ebene
                nextPointer = nextSiblingElement(parentNode) # Pointer zum nächsten Element
                                    
                if nextPointer == None: # kein weiteres Element
                    break
                next = nextPointer.tagName
                
                if next == 'keySign': # neue Tonartvorzeichnung
                    keySign = nextPointer
                    fifths = keySign.getAttribute('fifths')
                    keyCinstr = int(fifths)
                   
                continue
                                                                                                 

    # ------ vom (fiktiven) C-Instrument zum Zielinstrument (T = Target) ------ #
    #===========================================================================#
  
    transposeTo = toInstr.value() # Position des "nach-Instruments" in der Tabelle
    Instrparam = fromCinstr[transposeTo] # Instrumentenparameter aus Tabelle lesen
    keyToInstr = Instrparam[0] # Tonartvorzeichnung für die Stimmung des "nach-Instruments" (9=dummy - kein Instrument)
    interval = Instrparam[1] # Transpositionsinterval in Halbtonschritten
    intOctFrC = Instrparam[2] # zusätzliche interne Oktavierung zum Transpositionsinterval
    extOct = 0 # externe Oktavierung durch den Anwender
    firstKey = 0 # für die Übernahmesteuerung der ersten Tonartvorzeichnung in die Transpositionsschleife für die einzelnen Töne
             
    for system in score.getElementsByTagName('system'):
        for staff in system.getElementsByTagName('staff'): # Aufsuchen der selektierten Notenzeile
            layout = staff.getAttribute('layout')
            if layout != staffList[selStaff.value()]:
                continue
                                    
            # ------ Tonartvorzeichnung für das Zielinstrument setzen ------ #

            for keySign in staff.getElementsByTagName('keySign'):
                fifths = keySign.getAttribute('fifths') # vorhandene Tonartvorzeichnung
                keyTinstr = int(fifths) + int(keyToInstr) # die Zieltonart-Vorzeichnung

                if firstKey == 0:
                    keyTinstrSave = keyTinstr
                    firstKey = 1
                
                # ------ Begrenzung der Anzahl der Tonartvorzeichen ------ #

                if keyTinstr > maxVorz: # maximal 6#(Standard) oder 7#(auf Wunsch) Vorzeichen
                    keyTinstr = keyTinstr - 12
                if keyTinstr < -maxVorz: # maximal 6b(Standard) oder 7b(auf Wunsch) Vorzeichen
                    keyTinstr = keyTinstr + 12
                    
                keySign.setAttribute('fifths',str(keyTinstr)) # Zieltonart-Vorzeichnung setzen
                
                if transposeOctave == 0:
                    extOct = 2
                elif transposeOctave == 1:
                    extOct = 1
                elif transposeOctave == 3:
                    extOct = -1
                elif transposeOctave == 4:
                    extOct = -2
                
                            
            keyTinstr = keyTinstrSave # Übernahme der gespeicherten ersten Tonartvorzeichnung in der Notenzeile
            firstKey = 0
            
            for head in staff.getElementsByTagName('head'):
                pitch = head.getAttribute('pitch')
                alter = head.getElementsByTagName('alter')
                if alter != []:
                    alter = head.getElementsByTagName('alter')[0] 
                    step = alter.getAttribute('step')
                else:
                    step = 0 
                octSave = pitch[1] # maximal 6b(Standard) oder 7b(auf Wunsch) Vorzeichen

               
                # ------ Begrenzung der Anzahl der Tonartvorzeichen ------ #

                if keyTinstr > maxVorz: # maximal 6#(Standard) oder 7#(auf Wunsch) Vorzeichen
                    keyTinstr = keyTinstr - 12
                if keyTinstr < -maxVorz: # maximal 6b(Standard) oder 7b(auf Wunsch) Vorzeichen
                    keyTinstr = keyTinstr + 12
                
                # ------ Selektieren der entsprechenden Tabelle und Tabellenzeile ------ #

                if 0 <= keyTinstr < 6: # Tonarten C - H
                    pitchTableX = pitchTable1a[pitch[0]]
                elif keyTinstr == 6: # Tonart Fis
                    pitchTableX = pitchTable1b[pitch[0]] # mit eis
                elif keyTinstr == 7: # Tonart Cis
                    pitchTableX = pitchTable1c[pitch[0]] # mit eis und his
                elif -1 >= keyTinstr > -6: # Tonarten F - Des
                    pitchTableX = pitchTable2a[pitch[0]]
                elif keyTinstr == -6: # Tonart Ges
                    pitchTableX = pitchTable2b[pitch[0]] # mit eis
                elif keyTinstr == -7: # Tonart Ces
                    pitchTableX = pitchTable2c[pitch[0]] # mit eis und his
                else:
                    messageBox('Falsche Zieltonart', str(keyCinstr))    
                
                    
                pitch = pitchTableX[2*12+2*interval + 2*int(step)] # Auslesen des neuen Tones einschließlich Oktavierung
                pitchX = pitch[0] # der neue Ton
                octaveX = pitch[1] # eine möglich Oktavierung, um +/-1 Oktave
                octaveX = int(octaveX) + int(octSave) - 1 + int(extOct) + int(intOctToC) + int(intOctFrC) # resultierende Oktavierung
                octaveX = str(octaveX) 
                head.setAttribute('pitch',pitchX + octaveX) # Setzen des Tones mit seiner Oktave (z.B. C5 für c')
                #alter = addNewChildNode(head,'alter') ### war doppelt - siehe Zeile 303 
                alter.setAttribute('step',pitchTableX[2*12 + 2*interval+1 + 2*int(step)]) # Setzen der resultierenden Alteration
                
                parentNode = head.parentNode # heads-Ebene
                parentNode = parentNode.parentNode # chord/keySign-Ebene
                nextPointer = nextSiblingElement(parentNode) # Pointer zum nächsten Element
                                        
                if nextPointer == None: # kein weiteres Element
                    break
                next = nextPointer.tagName
                
                if next == 'keySign': # neue Tonartvorzeichnung
                    keySign = nextPointer
                    fifths = keySign.getAttribute('fifths')
                    
                    keyTinstr = int(fifths) # + int(Instr)

                continue

                    
           

    transposeTo = toInstr.value()
    toInstrX = fromCinstr[transposeTo]
    clefType = toInstrX[3]
            
    # Schlüssel setzen und eventuelle Vorspiel-Transposition löschen, damit die "chromatischen Pitchwerte" erhalten bleiben
    #======================================================================================================================

    for staffLayout in score.getElementsByTagName('staffLayout'): # Setzen des Schlüssels im Mustersystem #
        description = staffLayout.getAttribute('description')
        if description != staffList[selStaff.value()]:
            continue
        notation = staffLayout.getElementsByTagName('notation')[0]
        notation.setAttribute('defaultClef',['treble','bass','tenor'][clefType])

        sound = staffLayout.getElementsByTagName('sound')[0] # Sicherstellung der unveränderten "chromatischen Pitchwerte"
        sound.setAttribute('transpose', '0') # Löschen einer eventuell vorhandenen Vorspiel-Transposition
                    
    for staff in score.getElementsByTagName('staff'): # Setzen des Schlüssels in der Partitur #
        layout = staff.getAttribute('layout')
        if layout != staffList[selStaff.value()]:
            continue
        clefSign = staff.getElementsByTagName('clefSign')[0] 
        clefSign.setAttribute('clef',['treble','bass','tenor'][clefType])


def playTranspAndOct(score):
    global indOktaviert

    # ------ Setzen der Vorspiel-Transposition ------ #

    transposeTo = toInstr.value()
    toInstrX = fromCinstr[transposeTo]
    transp = toInstrX[4]

    for staffLayout in score.getElementsByTagName('staffLayout'): # Mustersystem #
        description = staffLayout.getAttribute('description')
        if description != staffList[selStaff.value()]:
            continue
        
        sound = staffLayout.getElementsByTagName('sound')[0] 
        sound.setAttribute('transpose', str(transp)) # Setzen der Vorspiel-Transposition


        # ------ Eventuelles Oktavieren der Noten außerhalb des Tonbereichs des Zielinstruments ------ #

        indOktaviert = 0
        if oktavieren: # Noten außerhalb des Tonbereichs des Zielinstruments oktavieren?
            
            if indColor:
                indOktaviert = 1
                for display in score.getElementsByTagName('display'):
                    color = display.getAttribute('color')
                    
                    head = display.parentNode.getElementsByTagName('head')
                    if head != []: # nur bei 'head' weiter ('display' kommt auch in ganzen und Ganztakt-Pausen vor)
                        head = display.parentNode.getElementsByTagName('head')[0]
                        pitch = head.getAttribute('pitch')

                        if color == 'FF0000': # rot (oben außerhalb des Tonbereichs)
                            
                            head.setAttribute('pitch', pitch[0]+str(int(pitch[1])-1))

                        if color == '0000FF': # blau (unten außerhalb des Tonbereichs)
                            
                            head.setAttribute('pitch',pitch[0]+str(int(pitch[1])+1))

        

def instrName(score): # für default-Belegung des Eingabefeldes
    global instrName

    instrument = score.getElementsByTagName('instrument')[0]
    instrName = instrument.getAttribute('name')
    instrName = str(instrName)
                  
    
class transposeClass(ScoreChange):
        def changeScore(self, score):
            global scriptAction, doc
            doc = score.parentNode
            transpose(score)

class playTranspAndOctClass(ScoreChange):
        def changeScore(self, score):
            global scriptAction, doc
            doc = score.parentNode
            playTranspAndOct(score)

class instrNameClass(ScoreChange):
        def changeScore(self, score):
            global scriptAction, doc
            doc = score.parentNode
            instrName(score)


# ------ Vorzeichnung löschen ------ # 

def deleteKey(score):
    
    for system in score.getElementsByTagName('system'): 
        for staff in system.getElementsByTagName('staff'): 
            layout = staff.getAttribute('layout') 
            if layout != staffList[selStaff.value()]: 
                continue 
            for keySign in staff.getElementsByTagName('keySign'): 
                keySign.parentNode.removeChild(keySign)
  

class deleteKeyClass(ScoreChange):
        def changeScore(self, score):
            global scriptAction, doc
            doc = score.parentNode
            deleteKey(score)


# -------- Unterstützte Instrumente --------- #

instrList = ['Instrument auswählen',                   #--00--# Default-Eintrag
             '=============================',          #--01--# 
             'KLARINETTEN:',                           #--02--# Instrumentenkategorie
             '- - - - - - - - - - - - -',              #--03--#------KLANG------#
             'Klarinette in Es',                       #--04--# kleine Terz höher
             'Klarinette in D',                        #--05--# Ganzton höher
             'Klarinette in C',                        #--06--# wie notiert
             'Klarinette in B',                        #--07--# Ganzton tiefer
             'Klarinette in A',                        #--08--# kleine Terz tiefer
             'Bassethorn in F',                        #--09--# Quinte tiefer
             'Altklarinette in F',                     #--10--# Quinte tiefer
             'Bassklarinette in B',                    #--11--# große None tiefer
             'Bassklarinette in A',                    #--12--# kleine Dezime tiefer
             '----------------------------------------------------------',#--13--#
             'OBOEN / FAGOTTE:',                       #--14--# Instrumentenkategorie
             '- - - - - - - - - - - - - - - - -',      #--15--#
             'Oboe (in C)',                            #--16--# wie notiert
             'Oboe d´amore in A',                      #--17--# kleine Terz tiefer
             'Englisch-Horn in F',                     #--18--# Quinte tiefer
             'Fagottino in G',                         #--19--# Quinte höher
             'Fagottino in F',                         #--20--# Quarte höher
             'Fagott',                                 #--21--# wie notiert
             'Kontra-Fagott',                          #--22--# Oktave tiefer
             '----------------------------------------------------------',#--23--#
             'SAXOPHONE:',                             #--24--# Instrumentenkategorie
             '- - - - - - - - - - - -',                #--25--#
             'Sopran-Saxophon in B',                   #--26--# Ganzton tiefer
             'Alt-Saxophon in Es',                     #--27--# große Sexte tiefer
             'Tenor-Saxophon in B',                    #--28--# große None tiefer
             'Bariton-Saxophon in Es',                 #--29--# Oktave plus große Sexte tiefer
             'Bass-Saxophon in B',                     #--30--# zwei Oktaven plus Ganzton tiefer
             '----------------------------------------------------------',#--31--#
             'BLECHINSTRUMENTE:',                      #--32--# Instrumentenkategorie
             '- - - - - - - - - - - - - - - - - - - -',#--33--#
             'Horn in C (V.-Schl. - klingend notiert)',#--34--# wie notiert
             'Horn in C (B.-Schl. - klingend notiert)',#--35--# wie notiert
             'Horn in B',                              #--36--# große Sekunde tiefer 
             'Horn in F',                              #--37--# Quinte tiefer 
             'Horn in Es',                             #--38--# große Sexte tiefer
             'Flügelhorn in B',                        #--39--# Ganzton tiefer
             'Tenorhorn in B',                         #--40--# große None tiefer
             'Trompete in Es',                         #--41--# kleine Terz höher
             'Trompete in C',                          #--42--# wie notiert
             'Trompete in B',                          #--43--# Ganzton tiefer
             'Posaune in C',                           #--44--# wie notiert
             'Tenorposaune in B    ( V.-Schlüssel )',  #--45--# große None tiefer (schweizer Notierung)
             'Tenorposaune (in B)  ( B.-Schlüssel )',  #--46--# wie notiert
             'Tenorposaune (in B)  (Tenor-Schlüssel)', #--47--# wie notiert
             'Bassposaune in F      ( V.-Schlüssel )', #--48--# Oktave plus Quinte tiefer (schweizer Notierung)
             'Bassposaune (in F)    ( B.-Schlüssel )', #--49--# wie notiert
             'Bariton in C           ( V.-Schlüssel )',#--50--# Oktave tiefer (schweizer Notierung)
             'Bariton (in C)         ( B.-Schlüssel )',#--51--# wie notiert
             'Bariton in B           ( V.-Schlüssel )',#--52--# große None tiefer (schweizer Notierung)
             'Bariton (in B)         ( B.-Schlüssel )',#--53--# wie notiert
             'Tuba in C              ( V.-Schlüssel )',#--54--# Oktave tiefer (schweizer Notierung)
             'Tuba (in C)            ( B.-Schlüssel )',#--55--# wie notiert
             'Tuba in F              ( V.-Schlüssel )',#--56--# Oktave plus Quinte tiefer (schweizer Notierung)
             'Tuba (in F)            ( B.-Schlüssel )',#--57--# wie notiert
             'Tuba in Es             ( V.-Schlüssel )',#--58--# Oktave plus große Sexte tiefer (schweizer Notierung)
             'Tuba (in Es)           ( B.-Schlüssel )',#--59--# wie notiert
             'Bass-Tuba in C         ( V.-Schlüssel )',#--60--# zwei Oktaven tiefer (schweizer Notierung)
             'Bass-Tuba (in C)       ( B.-Schlüssel )',#--61--# wie notiert
             'Bass-Tuba in B         ( V.-Schlüssel )',#--62--# Oktave plus große None tiefer (schweizer Notierung)
             'Bass-Tuba (in B)       ( B.-Schlüssel )',#--63--# wie notiert
             'Wagner-Tuba in B    ( B.-Schlüssel )',   #--64--# Ganzton tiefer
             'Wagner-Tuba in F    ( B.-Schlüssel )',   #--65--# Quinte tiefer
             '----------------------------------------------------------',#--66--#
             'FLÖTEN:',                                #--67--# Instrumentenkategorie
             '- - - - - - - -',                        #--68--#
             'Piccolo in Des',                         #--69--# kleine None höher
             'Piccolo in C',                           #--70--# Oktave höher 
             'Große Flöte in Des',                     #--71--# Halbton höher
             'Große Flöte in C',                       #--72--# wie notiert
             'Altflöte in G',                          #--73--# Quarte tiefer
             'Bassflöte in C',                         #--74--# Oktave tiefer
             '----------------------------------------------------------',#--75--#
             'BLOCKFLÖTEN:',                           #--76--# Instrumentenkategorie
             '- - - - - - - - - - - - -',              #--77--#
             'Sopran-Blockflöte in C',                 #--78--# Oktave höher
             'Alt-Blockflöte in F',                    #--79--# wie notiert
             'Tenor-Blockflöte in C',                  #--80--# wie notiert
             'Bass-Blockflöte in F',                   #--81--# wie notiert
             '----------------------------------------------------------']#--82--#


# -------- Transpositionstabelle zum fiktiven C-Instrument (1.Position(Vorz.): +n=#, -n=b - 2.Position: Halbtonschritte) -------- #

toCinstr = {0:[9,0,0],   # zum fiktiven C-Instrument (die ersten beiden Einträge für Transposition, der dritte Eintrag 
            1:[9,0,0],   # =========================  für die Oktavierungssteuerung; 9 = auswählen!) 
            2:[9,0,0],   # KLARINETTEN: 
            3:[9,0,0],   # - - - - - -
            4:[-3,3,0],  # 3b, kleine Terz nach oben 
            5:[2,2,0],   # 2#, Ganzton nach oben
            6:[0,0,0],   # keine Transpostion 
            7:[-2,-2,0], # 2b, Ganzton nach unten
            8:[3,-3,0],  # 3#, kleine Terz nach unten
            9:[-1,-7,0], # 1b, Quinte nach unten
           10:[-1,-7,0], # 1b, Quinte nach unten
           11:[-2,-2,0], # 2b, Ganzton nach unten
           12:[3,-3,0],  # 3#, kleine Terz nach unten
           13:[9,0,0],   # ----------------
           14:[9,0,0],   # OBOEN / FAGOTTE:
           15:[9,0,0],   # - - - - - - - - 
           16:[0,0,0],   # keine Transposition 
           17:[3,-3,0],  # 3#, kleine Terz nach unten
           18:[-1,-7,0], # 1b, Quinte nach unten
           19:[1,7,1],   # 1#, Quinte nach oben, +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           20:[-1,5,1],  # 1b, Quarte nach oben, +1 Oktave für ein "Zielinstrument" mit Violinschlüssel 
           21:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           22:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           23:[9,0,0],   # ----------------
           24:[9,0,0],   # SAXOPHONE:
           25:[9,0,0],   # - - - - -  
           26:[-2,-2,0], # 2b, Ganzton nach unten
           27:[-3,-9,0], # 3b, große Sexte nach unten
           28:[-2,-2,0], # 2b, Ganzton nach unten
           29:[-3,-9,0], # 3b, große Sexte nach unten
           30:[-2,-2,0], # 2b, Ganzton nach unten
           31:[9,0,0],   # ----------------
           32:[9,0,0],   # BLECHINSTRUMENTE:
           33:[9,0,0],   # - - - - - - - - -
           34:[0,0,0],   # keine Transposition
           35:[0,0,1],   # keine Transposition
           36:[-2,-2,0], # 2b, Ganzton nach unten 
           37:[-1,-7,0], # 1b, Quinte nach unten
           38:[-3,-9,0], # 3b, große Sexte nach unten
           39:[-2,-2,0], # 2b, Ganzton nach unten
           40:[-2,-2,0], # 2b, Ganzton nach unten
           41:[-3,3,0],  # 3b, kleine Terz nach oben 
           42:[0,0,0],   # keine Transposition 
           43:[-2,-2,0], # 2b, Ganzton nach unten
           44:[0,0,1],   # keine Transposition 
           45:[-2,-2,0], # 2b, Ganzton nach unten (schweizer Notierung)
           46:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           47:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           48:[-1,-7,0], # 1b, Quinte nach unten (schweizer Notierung) 
           49:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel 
           50:[0,0,0],   # keine Transposition
           51:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel 
           52:[-2,-2,0], # 2b, Ganzton nach unten (schweizer Notierung)
           53:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           54:[0,0,0],   # keine Transposition
           55:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel 
           56:[-1,-7,0], # 1b, Quinte nach unten (schweizer Notierung)
           57:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           58:[-3,-9,0], # 3b, große Sexte nach unten (schweizer Notierung)
           59:[0,0,1],   # +1 Oktave für ein "Zielinstrument" mit Violinschlüssel
           60:[0,0,0],   # keine Transposition 
           61:[0,0,2],   # +2 Oktaven für ein "Zielinstrument" mit Violinschlüssel
           62:[-2,-2,0], # 2b, Ganzton nach unten (schweizer Notierung)
           63:[0,0,2],   # +2 Oktaven für ein "Zielinstrument" mit Violinschlüssel
           64:[-2,-2,1], # 2b, Ganzton nach unten, +1 Oktaven für ein "Zielinstrument" mit Violinschlüssel
           65:[-1,-7,1], # 1b, Quinte nach unten, +1 Oktaven für ein "Zielinstrument" mit Violinschlüssel
           66:[9,0,0],   # ----------------
           67:[9,0,0],   # FLÖTEN:
           68:[9,0,0],   # - - - - 
           69:[-5,1,0],  # 5b, Halbton nach oben
           70:[0,0,0],   # keine Transposition 
           71:[-5,1,0],  # 5b, Halbton nach oben
           72:[0,0,0],   # keine Transposition
           73:[1,-5,0],  # 1#, Quarte nach unten
           74:[0,0,0],   # keine Transposition
           75:[9,0,0],   # ----------------
           76:[9,0,0],   # BLOCKFLÖTEN:
           77:[9,0,0],   # - - - - - - 
           78:[0,0,0],   # keine Transposition 
           79:[0,0,0],   # keine Transposition
           80:[0,0,0],   # keine Transposition
           81:[0,0,0],   # keine Transposition
           82:[9,0,0]}   # ----------------
                 

# -------- Transpositionstabelle vom fiktiven C-Instrument (+n=#, -n=b  -  in Halbtonschritten) -------- #

V = 0 # Violinschlüssel
B = 1 # Bassschlüssel
T = 2 # Tenorschlüssel
X = 0 # Dummy

               #[a,b,c,d,e]        a=9=auswählen!, a+b=capella-Transp., c=Oktavierung, d=Schlüssel, e=Vorspiel-Transp.

fromCinstr = {0:[9,0,0,X,X],    # vom fixtiven C-Instrument 
              1:[9,0,0,X,X],    # ========================= parent
              2:[9,0,0,X,X],    # KLARINETTEN:
              3:[9,0,0,X,X],    # - - - - - -
              4:[3,-3,0,V,3],   # 3#, kleine Terz nach unten
              5:[-2,-2,0,V,2],  # 2b, Ganzton nach unten
              6:[0,0,0,V,0],    # keine Transposition 
              7:[2,2,0,V,-2],   # 2#, Ganzton nach oben
              8:[-3,3,0,V,-3],  # 3b, kleine Terz nach oben
              9:[1,7,0,V,-7],   # 1#, Quinte nach oben
             10:[1,7,0,V,-7],   # 1#, Quinte nach oben
             11:[2,2,0,V,-14],  # 2#, Ganzton nach oben
             12:[-3,3,0,V,-15], # 3b, kleine Terz nach oben
             13:[9,0,0,X,X],    # ----------------
             14:[9,0,0,X,X],    # OBOEN / FAGOTTE:
             15:[9,0,0,X,X],    # - - - - - - - -
             16:[0,0,0,V,0],    # keine Transposition 
             17:[-3,3,0,V,-3],  # 3b, kleine Terz nach oben
             18:[1,7,0,V,-7],   # 1#, Quinte nach oben
             19:[-1,-7,-1,B,7], # 1b, Quinte nach unten, -1 Oktave für Bassschlüssel
             20:[1,-5,-1,B,5],  # 1#, Quarte nach unten, -1 Oktave für Bassschlüssel 
             21:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel
             22:[0,0,-1,B,-12], # -1 Oktave für Bassschlüssel
             23:[9,0,0,X,X],    # ----------------
             24:[9,0,0,X,X],    # SAXOPHONE:
             25:[9,0,0,X,X],    # - - - - -  
             26:[2,2,0,V,-2],   # 2#, Ganzton nach oben
             27:[3,9,0,V,-9],   # 3#, große Sexte nach oben 
             28:[2,2,0,V,-14],  # 2#, Ganzton nach oben
             29:[3,9,0,V,-21],  # 3#, große Sexte nach oben
             30:[2,2,0,V,-26],  # 2#, Ganzton nach oben
             31:[9,0,0,X,X],    # ----------------
             32:[9,0,0,X,X],    # BLECHINSTRUMENTE:
             33:[9,0,0,X,X],    # - - - - - - - - - 
             34:[0,0,0,V,0],    # keine Transposition
             35:[0,0,-1,B,0],   # keine Transposition
             36:[2,2,0,V,-2],   # 2#, Ganzton nach oben
             37:[1,7,0,V,-7],   # 1#, Quinte nach oben
             38:[3,9,0,V,-9],   # 3#, große Sexte nach oben
             39:[2,2,0,V,-2],   # 2#, Ganzton nach oben
             40:[2,2,0,V,-14],  # 2#, Ganzton nach oben
             41:[3,-3,0,V,3],   # 3#, kleine Terz nach unten
             42:[0,0,0,V,0],    # keine Transposition
             43:[2,2,0,V,-2],   # 2#, Ganzton nach oben
             44:[0,0,-1,B,0],   # keine Transposition 
             45:[2,2,0,V,-14],  # 2#, Ganzton nach oben (schweizer Notierung)
             46:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel
             47:[0,0,-1,T,0],   # -1 Oktave für Tenorschlüssel 
             48:[1,7,0,V,-19],  # 1#, Quinte nach oben (schweizer Notierung)
             49:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel 
             50:[0,0,0,V,-12],  # keine Transposition
             51:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel
             52:[2,2,0,V,-14],  # 2#, Ganzton nach oben (schweizer Notierung)
             53:[0,0,-1,B,0],   # -1Oktave für Bassschlüssel
             54:[0,0,0,V,-12],  # keine Transposition
             55:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel 
             56:[1,7,0,V,-19],  # 1#, Quinte nach oben (schweizer Notierung)
             57:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel
             58:[3,9,0,V,-21],  # 3#, große Sexte nach oben (schweizer Notierung)
             59:[0,0,-1,B,0],   # -1 Oktave für Bassschlüssel
             60:[0,0,0,V,-24],  # keine Transposition
             61:[0,0,-2,B,0],   # -2 Oktaven für Bassschlüssel
             62:[2,2,0,V,-26],  # 2#, Ganzton nach oben (schweizer Notierung)
             63:[0,0,-2,B,0],   # -2 Oktaven für Bassschlüssel
             64:[2,2,-1,B,-2],  # 2#, Ganzton nach oben, -1 Oktaven für Bassschlüssel
             65:[1,7,-1,B,-7],  # 1#, Quinte nach oben, -1 Oktaven für Bassschlüssel 
             66:[9,0,0,X,X],    # ----------------
             67:[9,0,0,X,X],    # FLÖTEN:
             68:[9,0,0,X,X],    # - - - -  
             69:[5,-1,0,V,13],  # 5#, Halbton nach unten
             70:[0,0,0,V,12],   # keine Transposition 
             71:[5,-1,0,V,1],   # 5#, Halbton nach unten
             72:[0,0,0,V,0],    # keine Transposition 
             73:[-1,5,0,V,-5],  # 1b, Quarte nach oben
             74:[0,0,0,V,-12],  # keine Transposition 
             75:[9,0,0,X,X],    # ----------------
             76:[9,0,0,X,X],    # BLOCKFLÖTEN:
             77:[9,0,0,X,X],    # - - - - - - 
             78:[0,0,0,V,12],   # keine Transposition 
             79:[0,0,0,V,0],    # keine Transposition
             80:[0,0,0,V,0],    # keine Transposition
             81:[0,0,0,V,0],    # keine Transposition
             82:[9,0,0,X,X]}    # ----------------


# --------- Tonumfänge der Instrumente ---------- # 

pRt = {0:(00,00), # PitchRange-Table
       1:(00,00), # ================
       2:(00,00), # KLARINETTEN:                     
       3:[9,0,0], # - - - - - - 
       4:(52,91), # Klarinette in Es
       5:(52,92), # Klarinette in D
       6:(52,96), # Klarinette in C
       7:(52,96), # Klarinette in B
       8:(52,96), # Klarinette in A
       9:(48,91), # Bassethorn in F
      10:(52,91), # Altklarinette in F
      11:(52,91), # Bassklarinette in B
      12:(52,91), # Bassklarinette in A
      13:(00,00), # ----------------
      14:(00,00), # OBOEN / FAGOTTE:
      15:[9,0,0], # - - - - - - - - 
      16:(59,89), # Oboe (in C)
      17:(59,88), # Oboe d´amore in A
      18:(59,88), # Englisch-Horn in F
      19:(34,66), # Fagottino in G (B1 - fis', mit Tenorschlüssel bis h')
      20:(34,66), # Fagottino in F (B1 - fis', mit Tenorschlüssel bis h') 
      21:(34,75), # Fagott Bassschlüssel
      22:(36,67), # Kontra-Fagott Bassschl.
      23:(00,00), # -----------------
      24:(00,00), # SAXOPHONE:
      25:[9,0,0], # - - - - -  
      26:(58,87), # Sopran-Saxophon in B  
      27:(58,90), # Alt-Saxophon in Es
      28:(58,89), # Tenor-Saxophon in B
      29:(58,89), # Bariton-Saxophon in Es
      30:(58,87), # Bass-Saxophon in B
      31:(00,00), # ----------------
      32:(00,00), # BLECHINSTRUMENTE:
      33:[9,0,0], # - - - - - - - - - 
      34:(49,93), # Horn in C (V.-Schl. - klingend notiert) - fiktiver Tonumfang für Es- unf F-Horn
      35:(49,93), # Horn in C (B.-Schl. - klingend notiert) - fiktiver Tonumfang für Es- unf F-Horn
      36:(42,84), # Horn in B 
      37:(42,84), # Horn in F
      38:(54,84), # Horn in Es
      39:(53,84), # Flügelhorn in B
      40:(54,84), # Tenorhorn in B
      41:(54,84), # Trompete in Es
      42:(54,84), # Trompete in C
      43:(54,86), # Trompete in B
      44:(35,84), # Posaune in C (fiktiver Tonumfang für alle Posaunen-Typen) 
      45:(54,84), # Tenor-Posaune in B (V.-Schl.)
      46:(40,70), # Tenor-Posaune (in B) (B.-Schl.)
      47:(40,70), # Tenor-Posaune (in B) (T.-Schl.) 
      48:(54,84), # Bass-Posaune in F
      49:(35,65), # Bassposaune (in C) (B.-Schl.)
      50:(54,84), # Bariton in C (V.-Schl.)
      51:(40,70), # Bariton (in C) (B.-Schl.) 
      52:(54,84), # Bariton in B  (V.-Schl.) 
      53:(40,70), # Bariton (in B) (B.-Schl.)
      54:(54,84), # Tuba in C (V.-Schl.)
      55:(35,65), # Tuba (in C) (B.-Schl.) 
      56:(54,84), # Tuba in F (V.-Schl.)
      57:(35,65), # Tuba in F (B.-Schl.) 
      58:(54,84), # Tuba in Es (V.-Schl.) 
      59:(33,63), # Tuba (in Es) (B.-Schl.) 
      60:(48,84), # Bass-Tuba in C (V.-Schl.)
      61:(24,60), # Bass-Tuba (in C) (B.-Schl.) 
      62:(48,84), # Bass-Tuba in B (V.-Schl.)
      63:(22,58), # Bass-Tuba (in B) (B.-Schl.)
      64:(36,79), # Bass-Tuba (in B) (B.-Schl.)
      65:(36,79), # Bass-Tuba (in B) (B.-Schl.)
      66:(00,00), # ----------------
      67:(00,00), # FLÖTEN:
      68:[9,0,0], # - - - -  
      69:(62,94), # Piccolo in Des
      70:(62,94), # Piccolo in C 
      71:(60,98), # Große Flöte in Des
      72:(60,98), # Große Flöte in C
      73:(60,96), # Altflöte in G
      74:(60,93), # Bassflöte in C
      75:(00,00), # ----------------
      76:(00,00), # BLOCKFLÖTEN:
      77:[9,0,0], # - - - - - - 
      78:(60,86), # Sopran-Blockflöte in C
      79:(65,91), # Alt-Blockflöte in F
      80:(60,86), # Tenor-Blockflöte in C
      81:(53,79), # Bass-Blockflöte in F
      82:(00,00)} # ----------------



active = 0 # zum Steuern der Schlussanzeige
actualKey = 0
staffList = activeScore().voiceList()
staffIndex = 0
sel = curSelection()


if sel <> 0:
    (sy,st,vo,no) = sel[0]
    system = activeScore().system(sy)
    staff = system.staff(st)
      
               
    # ------ Aktuellen Eintrag im Mustersystem bestimmen ------ #

    i = 0
    for descr in staffList:
        if staff.index() == system.staffIndexFromDescr(descr):
            staffIndex = i
        i += 1



# -------- Dialogbox --------- #        

labStaff1 = Label(' Notenzeile des Instruments  (durch Positionierung des Cursors in der Notenzeile \
des Instruments wird diese Notenzeile vorbestimmt)')
selStaff = ComboBox(staffList, value=staffIndex, width=20)
labStaff2 = Label('   "Beschreibung" der Notenzeile im capella-Mustersystem')

fromLab = Label(' von Instrument  --------------------------------------------------->')
fromInstr = ComboBox(instrList, value=0, width=29)

toLab = Label('nach Instrument', width=32)
toInstr = ComboBox(instrList, value=0, width=29)

optionalLab = Label('                                                                               \
                                                                              optionale Oktavierung')
octaveLab = Label('des Zielinstruments')
octave = ComboBox( ['+2 Oktaven','+1 Oktave','keine','-1 Oktave','-2 Oktaven'], value=2, width=11)

oktavieren = CheckBox('Noten außerhalb des Tonbereichs des Zielinstrumnets sollen automatisch um eine Oktave transponiert werden', value=0 )

entfVorz = CheckBox('Bei dem Zielinstrument die Tonartvorzeichnungen entfernen (z.B. bei Trompete, Horn oder Pauke in Orchesterpartituren)', value=0)

note = Label('                                 Instrument (in B, F, Es) bedeutet "Notierung in C"')

nullLab = Label('')

max6Vorz = CheckBox('Maximal 6 Tonartvorzeichen, d.h. 5# (H-Dur) anstelle von 7b (Ces-Dur), bzw. 5b (Des-Dur) anstelle von 7# (Cis-Dur)', value=1)

Hinweis = Label('HINWEIS: Bitte "Hilfe" anklicken, um detaillierte Informationen zum Skript zu erhalten')

dlg = Dialog('Transponieren von Blasinstrumenten-Stimmungen (Version 2.8)',

             VBox([
                   HBox([labStaff1]),
                   Label(''),
                   HBox([selStaff, labStaff2]),
                   HBox([optionalLab]),
                   HBox([fromLab, toLab, octaveLab], padding = 5), 
                   Label(''),
                   HBox([fromInstr,toInstr, octave],padding = 32),
                   HBox([note]),
                   Label(''),
                   HBox([nullLab, oktavieren], padding = 227),
                   HBox([nullLab, entfVorz], padding = 227),
                   HBox([nullLab, max6Vorz], padding = 227),
                   Label(''),
                   HBox([Hinweis]),
                   Label('')
                   ]
                 )
             )

      
def dlgRun():
    global active, transposeOctave, entfVorz, maxVorz, max6Vorz
    
    if dlg.run():
        
        active = 1 # nicht ganz klar - siehe unten
        transposeFrom = fromInstr.value()
        transposeTo = toInstr.value()
        transposeOctave = octave.value()
  
        Instr = toCinstr[transposeFrom]
        Instr = Instr[0]

        if Instr == 9:
            messageBox('Bitte das "von Instrument" auswählen', str('Bitte auch die entsprechende Notenzeile auswählen'))
            dlgRun()
            return # darf hier anschließend nicht weiterlaufen

        Instr = fromCinstr[transposeTo]
        Instr = Instr[0]
        
        if Instr == 9:
            messageBox('Bitte das "nach Instrument" auswählen', str('Bitte auch die entsprechende Notenzeile auswählen'))
            dlgRun()
            return # darf hier anschließend nicht weiterlaufen
                   
        activeScore().registerUndo("Instrumente transponieren") # an dieser Stelle???????????
    
                             
dlgRun()

if active == 1: # keine Schlussanzeige bei 'Abbrechen' #### nicht ganz klar !!!!!!!!!!

    oktavieren = oktavieren.value()
    entfVorz = entfVorz.value() 
    max6Vorz = max6Vorz.value()
    maxVorz = 7 - max6Vorz

    if activeScore():  
            activeScore().registerUndo("Instrumente transponieren")
            tempInput = tempfile.mktemp('.capx') # für aktuelle aktive Partitur #
            tempOutput = tempfile.mktemp('.capx')

            activeScore().write(tempInput) # Einlesen der aktiven Partitur
                                    
            transposeClass(tempInput,tempOutput) # Transposition durchführen
                       
            activeScore().read(tempOutput) # Ergebnis als aktive Partitur zurück

            if entfVorz: # Entfernen der Vorzeichnungen?

                activeScore().write(tempInput) # Partitur für Entfernen der Vorzeichnung wieder einlesen

                deleteKeyClass(tempInput, tempOutput) # Löschen der Vorzeichnung

                activeScore().read(tempOutput) # Ergebnis als aktive Partitur zurück
            
            # ------ Überprüfen des Tonumfangs ---- #

            indColor = 0
            for system in activeScore().systems():
                for staff in system.staves():
                    if staff.index() <> system.staffIndexFromDescr(staffList[selStaff.value()]):
                        continue 

                    # -------- Töne außerhalb des Tonumfangs werden rot dargestellt -------- #

                    # Alle Noten werden zuerst auf schwarz gesetzt
                
                    Bl = (Color.RGB(0,0,0)) # schwarz
                    for obj in staff.noteObjs():
                        if obj.isChord():
                            obj.setColor(Bl)

                    trTo = toInstr.value()          #transposeTo
                    
                    R = (Color.RGB(255,0,0)) # rot
                    B = (Color.RGB(0,0,255)) # blau
                    for obj in staff.noteObjs():
                        if obj.isChord():
                            head = obj.head(0)
                            chrP = head.chromaticPitch()
                            pR = pRt[trTo] # PitchRange
                            pLow = pR[0]
                            pHigh = pR[1]
                            if (chrP < pLow):# or (chrP > pHigh):
                                obj.setColor(B)
                                indColor = 1
                            elif (chrP > pHigh):# 
                                obj.setColor(R)
                                indColor = 1
                            else:
                                obj.setColor(Bl) # wenn farbige Noten durch Oktavierung wieder zu schwarzen werden müssen
                                       

            # Setzen der Vorspiel-Transposition und eventuelles Oktavieren der Noten außerhalb des Tonbereichs des Zielinstruments 
            #=====================================================================================================================
           
            activeScore().write(tempInput) # Partitur wieder einlesen

            playTranspAndOctClass(tempInput, tempOutput) # Funktions-Aufruf

            activeScore().read(tempOutput) # Ergebnis als aktive Partitur zurück           

            
            # -------- Schluss-Anzeige --------- #

            Instrument = instrList[toInstr.value()]
            staff = staffList[selStaff.value()]
            
            if indColor == 1:
                
                if indOktaviert == 0:
                    messageBox('Achtung: Der Standard-Tonumfang für  >'+str(Instrument)+'<  wurde nicht eingehalten!',
                                       '                     Die  >farbigen Noten<  liegen außerhalb des Standard-Tonbereichs von  >'+str(Instrument)+'<')
                else:
                    messageBox('Achtung: Der Standard-Tonumfang für  >'+str(Instrument)+'<  wurde nicht eingehalten!',
                            'Die  >farbigen Noten<  lagen außerhalb des Standard-Tonbereichs von  >'+str(Instrument)+'<  und wurden auf Wunsch oktaviert')
            else:
                messageBox('             Alle Noten von  >'+Instrument+'<  liegen im Standard-Tonumfang', str(
                                   'geprüft wurde in den Notenzeilen  >'+staff+'<  ("Beschreibung" der Notenzeile im capella-Mustersystem)'))
            os.remove(tempInput)
            os.remove(tempOutput)

