-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcreate_song.py
183 lines (170 loc) · 8.29 KB
/
create_song.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/python
# -*- coding: utf-8 -*-
def convert(path, f, target=None):
import re #für Regular Expressions (google es ;))
from collections import OrderedDict #andernfalls würde sich Vers1, Chorus usw immer alphabetisch sortieren
from pandas import read_csv, Index
#alle Imports für die PDF Generierung (unbedingt für nächster Zelle mit pyth ausführen)
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.pdfbase.pdfmetrics import stringWidth
from reportlab.lib import styles, colors
from reportlab.platypus import Paragraph
#RTF einlese Package
from pyth.plugins.rtf15.reader import Rtf15Reader
from pyth.plugins.plaintext.writer import PlaintextWriter
#RTF einlesen
doc = Rtf15Reader.read(f)
raw = PlaintextWriter.write(doc).getvalue()
pattern="(^[\xc3\x9f\xc3\x84\xc3\x96\xc3\x9c\xc3\xa4\xc3\xbc\xc3\xb6\xe2\x80\x99,\w\s]+\n+)(key:[\w#]+\n+)?(bpm:[\d]+\n+)?(.+)(CCLI Song # (\d+)\\n+(.+)\\n+\\xc2\\xa9 (.+))"
match = re.search(pattern,raw,re.DOTALL)
info_dict = {}
info_dict['title'] = match.group(1).replace('\n','')
if match.group(2):
info_dict['key'] = match.group(2).replace('\n','').replace('key:','')
else:
print "No key found"
if match.group(3):
info_dict['bpm'] = match.group(3).replace('\n','').replace('bpm:','')
else:
print "No bpm found"
info_dict['song'] = match.group(4)
info_dict['ccli_nr'] = match.group(6)
info_dict['composer'] = match.group(7).replace('\n','')
info_dict['copyright'] = match.group(8)
akkorde = read_csv("Akkorde.csv",sep=";")
def getTransformedKey (source, target, chord):
return(akkorde[target][Index(akkorde[source]).get_loc(chord)])
def replChords (matchObj):
return ('['+getTransformedKey(source = info_dict['key'], target = target, chord = matchObj.group(1))+']')
def transform():
info_dict['song'] = re.sub('\[([\w\d#/]+)\]', replChords, info_dict['song'])
info_dict['key'] = target
#target = request.form['trans_key']
if (target and target != info_dict['key']):
transform()
#Einzelne Zeilen aus dem RTF in Liste laden
line_list = info_dict.get('song').split('\n\n')
line_list
pattern = '^(Verse\s?\d*|Chorus\s?\d*|Instrumental|Bridge|Pre-Chorus|Intro)$' #Dieses Pattern funktioniert auf alles VersX und Chorus in eckiger Klammer (porbier regexr.com)
song_dict = OrderedDict() #Das oben erwähnte Ordered Dict
in_element = False #mit diesem Flag könnte man sich später noch title: composer: key: usw holen (so weit bin ich noch nicht)
element = None #hier wird gleich drin gespeichert, in welcher Untergruppe wir jeweils sind
for i in range(len(line_list)):
if in_element: #wenn wir in einem Element sind, werden alle folgenden Zeilen zu diesem Eintrag hinzugefügt
if not re.search(pattern,line_list[i]):
song_dict[element].extend([line_list[i]])
match = re.search(pattern,line_list[i]) #Bis wir den ersten Match haben (zB VersX oder Chorus), gibt es auch kein Element
if match: #Wenn wir jedoch ein Match haben, sind wir in einem Element. Dieses wird neu im Dictonary angelegt.
in_element = True
element = match.group(1)
song_dict[element] = [] #Wir geben an, dass hinter diesem Dictonary Eintrag eine neue Liste steht.
def createPDF(fontSize = 13):
width, height = A4 #keep for later
font = 'Helvetica'
lineHeight = fontSize + .75 * fontSize
wordSpace = 3
boarder = inch
topBoarder = .75*boarder
instrSpaces = 5
chordstyle = styles.ParagraphStyle('chord')
chordstyle.fontSize = fontSize
hstyle = styles.ParagraphStyle('heading')
hstyle.fontSize = fontSize +1
tstyle = styles.ParagraphStyle('title')
tstyle.fontSize = fontSize +5
copyrightstyle = styles.ParagraphStyle('copyright')
copyrightstyle.fontSize = 8
pattern = '\[([\w\d#/]+)\]'
y = height - topBoarder - fontSize
x = boarder
realWidth = width - 2*boarder
c = canvas.Canvas(path+info_dict['title']+'-'+info_dict['key']+'.pdf', pagesize=A4)
c.setFont(font, fontSize-1)
P1 = Paragraph("<u><b>"+info_dict['title']+"</b></u>",tstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,x,y)
if info_dict.has_key('key'):
P1 = Paragraph("<b>"+info_dict['key']+"</b>",chordstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,width-boarder-stringWidth(info_dict['key'], font, chordstyle.fontSize),y)
if info_dict.has_key('bpm'):
c.drawRightString(width-boarder,y-lineHeight,'%s'%info_dict['bpm'])
P1 = Paragraph(info_dict['composer'],copyrightstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,x,y-lineHeight)
c.setFont(font, fontSize)
y -= hstyle.fontSize + 2*lineHeight
for key in song_dict:
P1 = Paragraph("<b><i>"+key+"</i></b>",hstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,x,y)
xOfLast = boarder
lineCount = 0
if re.search(pattern, song_dict.get(key)[0]):
y -= 1.8 * (lineHeight) #Abstand von Überschrift zu erster Zeile wenn Akkorde
else:
y -= 1.2 * (lineHeight) #Abstand von Überschrift zu erster Zeile wenn keine Akkorde
if (key in ["Instrumental", "Intro"]):
for line in song_dict.get(key):
line = line.replace('[','').replace(']','').replace(' ',' '*(instrSpaces))
P1 = Paragraph("<b>"+line+"</b>",chordstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,x,y)
y -= 1.5 * lineHeight #Abstand nach jedem Abschnitt
else:
for line in song_dict.get(key):
if ((xOfLast + stringWidth(line, font, fontSize)) < (width - boarder)) and (lineCount < 2):
x = xOfLast
lineCount += 1
elif not re.search(pattern, line):
y -= 1 * lineHeight
else:
y -= 1.5 * lineHeight
lineCount = 1
line = line.decode('utf-8')
last_was_chord = False
x_min = 0
cursor = 0
while cursor < len(line):
l = line[cursor]
if l == ' ':
if last_was_chord:
x += last_cord_length
last_was_chord = False
else:
x += wordSpace
elif l == '[':
end = line.find(']', cursor)
chord = line[cursor+1:end]
P1 = Paragraph("<b>"+chord+"</b>",chordstyle)
P1.wrap(realWidth, height)
if x < x_min:
x = x_min
P1.drawOn(c,x,y+fontSize+0.01*fontSize**2)
cursor = end
last_was_chord = True
last_cord_length = stringWidth(chord, font, fontSize)
x_min = x + last_cord_length + wordSpace*7
else:
last_was_chord = False
c.drawString(x,y,l)
x += stringWidth(l, font, fontSize)
cursor += 1
xOfLast = x + wordSpace
x = boarder
y -= 1.5 * lineHeight #Abstand nach jedem Abschnitt
P1 = Paragraph(('© ')+
info_dict['copyright']+
'<br/>Gebrauch nur zur Nutzung im Rahmen von Veranstaltungen der City Chapel Stuttgart',copyrightstyle)
P1.wrap(realWidth, height)
P1.drawOn(c,x,boarder-P1.height)# + lineHeight)
c.showPage()
c.save()
return(y < boarder)
nochmal = True
fontSize = 13
while (nochmal):
nochmal = createPDF(fontSize)
fontSize -= .5