# -*- coding: ISO-8859-1 -*- """ capellaScript -- Copyright (c) 2003 Peter Becker >>> Pausen zusammenfassen Dieses Script fasst Ganztakt Pausen zu Balken- oder Kirchenpausen zusammen.|| Da bei mehrzeiligen Systemen die Pausenverteilung meist unregelmäßig ist, lassen sich diese nur systemweise zusammenfassen || Einzeiliges Zusammenfassen führt zu ungeplanten Ergebnissen !|| Bei Problemen bitte eine Mail an peter_becker@freenet.de <<< """ # 2.12.2003 Erste Version # 10.08.2007 Code Cleanup # 19.09.2007 Dialog auf Standart Capella geändert wg. 6.0 # 04.03.2008 Support für Doppelganze im 4/2 Takt # 16.06.2009 Fehlernachricht wenn keine Taktangabe am Anfang steht # 17.06.2009 Leere Zeilen entfernen # 19.06.2010 Fehler bei einfachem festen Taktstrich beseitigt import xml.dom, tempfile from caplib.capDOM import ScoreChange def removeEmptyLines(score): firstVoice = 1 eV = 0 if score.getElementsByTagName('chord').length == 0 and score.getElementsByTagName('rest').length == 0: return # damit nicht die letzte Zeile gelöscht wird for voice in score.getElementsByTagName('voice'): if voice.getElementsByTagName('chord').length == 0 and voice.getElementsByTagName('rest').length == 0: if voice.getElementsByTagName('barline').length == 0: # testen ob noch ein fester zusammenTyp da ist voice.parentNode.removeChild(voice) # falls nicht, weg mit der Zeile else: if not firstVoice: # falls doch Zeile mir der oberen verbinden no = voice.getElementsByTagName('noteObjects') bl = no[0].getElementsByTagName('barline') bln = bl[0].cloneNode('deep') no2 = emptyVoice.getElementsByTagName('noteObjects') fc2 = no2[0].firstChild fc2.parentNode.appendChild(bln) voice.parentNode.removeChild(voice) # und dann erst löschen else: eV = 0 if eV == 0: emptyVoice = voice # falls mehrere Pausenzeilen hintereinander eV = 1 firstVoice = 0 for staff in score.getElementsByTagName('staff'): if staff.getElementsByTagName('voice').length == 0: staff.parentNode.removeChild(staff) for system in score.getElementsByTagName('system'): if system.getElementsByTagName('staff').length == 0: system.parentNode.removeChild(system) class PausenQuetscher(ScoreChange): def changeScore(self, score): changeDoc(score) def addDrawObj(score,chord,drawObj): drawObjects = chord.getElementsByTagName('drawObjects') if drawObjects.length == 0: # noch kein drawObjects vorhanden drawObjects = score.parentNode.createElement('drawObjects') chord.appendChild(drawObjects) else: # drawObjects ist bereits vorhanden drawObjects=drawObjects[0] drawObjects.appendChild(drawObj) def changeDoc(score): global pausenTyp, zifferPos, zusammenTyp, useMulti, taktstrich, doppelganze restCnt = 0 actKey = '0' dispNum = 0 takt = 'no' fehler = 0 barlineEx = 0 if doppelganze == 1: # Default Takt initialisieren time = '4/4' else: time = '4/2' for voice in score.getElementsByTagName('voice'): if fehler == 1: break if zusammenTyp == 1: # wenn mehrstimmig restCnt = 0 # systemweise zusammenfassen noteObjects = voice.getElementsByTagName('noteObjects') zeilenAnfang = True skiprest = False for child in noteObjects[0].childNodes: if fehler == 1: break if child.nodeType == child.ELEMENT_NODE: if child.tagName == 'rest' or child.tagName == 'chord': if takt == 'no': messageBox('Partiturfehler','Achtung : keine Taktangabe am Anfang') fehler = 1 break if child.tagName == 'rest' and not skiprest: # ist ein Taktwiederholungszeichen an der Pause verankert? faulenzer = False skiprest = False for text in child.getElementsByTagName('text'): if 'capella' in text.getElementsByTagName('font')[0].getAttribute('face'): cnt=text.getElementsByTagName('content')[0] t = cnt.firstChild.nodeValue if t=='W': # Taktwiederholung faulenzer = True # diese Pause überspringen break if t=='X': # Doppeltaktwiederholung faulenzer = True # diese Pause überspringen skiprest = True # wenn unmittelbar noch eine Pause folgt, dann auch diese überspringen break if faulenzer: continue zeilenAnfang = False for volta in child.getElementsByTagName('volta'): # Unterbrechung bei Voltenklammern restCnt = 0 continue duration = child.getElementsByTagName('duration')[0] if duration.getAttribute('base') == '1/1' and time <> '4/2': # Pausenstil korrigieren duration.setAttribute('base','1') display = score.parentNode.createElement('display') child.appendChild(display) display.setAttribute('churchStyle','true') if duration.getAttribute('base') == '2/1': # Doppelganze vereinheitlichen duration.setAttribute('base','2') display = score.parentNode.createElement('display') child.appendChild(display) display.setAttribute('churchStyle','true') duration = child.getElementsByTagName('duration')[0] wert = duration.getAttribute('base') display = child.getElementsByTagName('display') dispNum = 0 if wert <> '1/2' and wert <> '1/4' and wert <> '1/8' and wert <> '1/16' and wert <> '1/32' and wert <> '1/64' and doppelganze == 0: if display: dispNum = child.getElementsByTagName('display')[0] elif wert >= '1' and doppelganze == 1: if display: dispNum = child.getElementsByTagName('display')[0] count = 0 mRest = 'no' if dispNum <> 0 and useMulti == 1: number = dispNum.getAttribute('number') if number == 'up' or number == 'down': # Mehrtaktpause gefunden count = duration.getAttribute('base') mRest = 'yes' if (duration.getAttribute('base') == '1' or duration.getAttribute('base') == '1/1' or mRest == 'yes') and (doppelganze == 0 and time <> '4/2'): if restCnt == 0: barlineEx = 1 firstRest = child # Die erste Pause zum Umwandeln merken if useMulti == 1 and mRest == 'yes': restCnt += int(count) else: restCnt += 1 else: # Grafikobjekte von Folgepausen an erste Pause hängen drawObjects=child.getElementsByTagName('drawObjects') if drawObjects.length: for drawObj in drawObjects[0].getElementsByTagName('drawObj'): addDrawObj(score,firstRest,drawObj.cloneNode(True)) child.parentNode.removeChild(child) if useMulti == 1 and mRest == 'yes': restCnt += int(count) else: restCnt += 1 firstDuration = firstRest.getElementsByTagName('duration')[0] firstDuration.setAttribute('base', str(restCnt)) #Pausenwert hochzählen disps = firstRest.getElementsByTagName('display') if disps.length == 0: disp = score.parentNode.createElement('display') firstRest.appendChild(disp) disps[0] = disp if pausenTyp == 1: disps[0].setAttribute('churchStyle','false') else: disps[0].setAttribute('churchStyle','true') if zifferPos == 1: disps[0].setAttribute('number','up') else: disps[0].setAttribute('number','down') elif (duration.getAttribute('base') == '2' or duration.getAttribute('base') == '2/1' or mRest == 'yes') and (doppelganze == 1 and time == '4/2'): if restCnt == 0: barlineEx = 1 firstRest = child # Die erste Pause zum Umwandeln merken if useMulti == 1 and mRest == 'yes': restCnt += int(count) else: restCnt += 1 else: # Grafikobjekte von Folgepausen an erste Pause hängen drawObjects=child.getElementsByTagName('drawObjects') if drawObjects.length: for drawObj in drawObjects[0].getElementsByTagName('drawObj'): addDrawObj(score,firstRest,drawObj.cloneNode(True)) child.parentNode.removeChild(child) if useMulti == 1 and mRest == 'yes': restCnt += int(count) else: restCnt += 1 firstDuration = firstRest.getElementsByTagName('duration')[0] firstDuration.setAttribute('base', str(restCnt)) #Pausenwert hochzählen disps = firstRest.getElementsByTagName('display') if disps.length == 0: disp = score.parentNode.createElement('display') firstRest.appendChild(disp) disps[0] = disp if pausenTyp == 1: disps[0].setAttribute('churchStyle','false') else: disps[0].setAttribute('churchStyle','true') if zifferPos == 1: disps[0].setAttribute('number','up') else: disps[0].setAttribute('number','down') else: # alle übrigen Pausen barlineEx = 0 restCnt = 0 if child.tagName in ['barline','timeSign','chord']: if child.tagName == 'barline' and not child.hasAttribute('type') and taktstrich == 1 and barlineEx == 1: child.parentNode.removeChild(child) # überflüssige feste Taktstriche löschen else: zeilenAnfang = False restCnt = 0 if child.tagName == 'timeSign': time = child.getAttribute('time') takt = "gefunden" if child.tagName == 'clefSign': # Bei einem Schlüssel am Zeilenanfang wird der Zähler nicht zurückgesetzt if not zeilenAnfang: restCnt = 0 if child.tagName == 'keySign': # Bei einer Tonartänderung an Zeilenanfang wird der Zähler zurückgesetzt if child.getAttribute('fifth') <> actKey: restCnt = 0 actKey = child.getAttribute('fifth') if not zeilenAnfang: restCnt = 0 skiprest = False removeEmptyLines(score) def pqDialog(): global pausenTyp, zifferPos, zusammenTyp, useMulti, taktstrich, doppelganze radPausenTyp = Radio(['Kirchenpause','Balkenpause'],text='Pausentyp',value=0) radZifferPos = Radio(['unten','oben'],text='Ziffernposition',value=0) radZusammenTyp = Radio(['einzeilig ( alle Zeilen zusammenfassen )','mehrzeilig oder systemweise zusammenfassen'],text='Optionen',value=0) radUseMulti = Radio(['Mehrtaktpausen nicht zusammenfassen','Mehrtaktpausen zusammenfassen'],text='Mehrtaktpausen',value=0) radTaktstrich = Radio(['unterbrechen bei einfachen festen Taktstrichen','einfache feste Taktstriche ignorieren'],text='feste Taktstriche',value=0) checkdoppelGz = CheckBox('Doppelganze statt Ganze Pausen ( nur 4/2 Takt )') placeholder1 = Label(' ',width=1) placeholder2 = Label(' ',width=1) placeholder3 = Label(' ',width=1) placeholder4 = Label(' ',width=1) box = VBox([radPausenTyp,radZifferPos,radZusammenTyp,radUseMulti,radTaktstrich,checkdoppelGz,placeholder1],padding=1) dlg = Dialog('Pausen zusammenfassen', box) if dlg.run(): pausenTyp = radPausenTyp.value() zifferPos = radZifferPos.value() zusammenTyp = radZusammenTyp.value() useMulti = radUseMulti.value() taktstrich = radTaktstrich.value() doppelganze = checkdoppelGz.value() return True else: return False # Hauptprogramm: if activeScore(): if pqDialog(): activeScore().registerUndo("Pausenquetscher") tempInput = tempfile.mktemp('.capx') tempOutput = tempfile.mktemp('.capx') activeScore().write(tempInput) PausenQuetscher(tempInput, tempOutput) activeScore().read(tempOutput) os.remove(tempInput) os.remove(tempOutput)