diff --git a/sotm2020/__init__.py b/sotm2020/__init__.py
new file mode 100644
index 0000000..df64e9a
--- /dev/null
+++ b/sotm2020/__init__.py
@@ -0,0 +1,200 @@
+#!/usr/bin/python3
+
+import subprocess
+from renderlib import *
+from easing import *
+
+# URL to Schedule-XML
+scheduleUrl = 'https://pretalx.com/fossgis2020/schedule/export/schedule.xml'
+
+# For (really) too long titles
+titlemap = {
+ #708: "Neue WEB-Anwendungen des LGRB Baden-Württemberg im Überblick"
+}
+
+
+def outroFrames(params):
+ # 8 Sekunden
+
+ # 2 Sekunden Fadein Text
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('banderole', 'style', 'opacity', "%.4f" % easeOutCubic(i, 0, 1, frames) ),
+ ('license', 'style', 'opacity', 0)
+ )
+
+ # 2 Sekunde Fadein Lizenz-Logo
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('banderole', 'style', 'opacity', 1),
+ ('license', 'style', 'opacity', "%.4f" % (float(i)/frames))
+ )
+
+ # 4 Sekunde stehen bleiben
+ frames = 4*fps
+ for i in range(0, frames):
+ yield (
+ ('banderole', 'style', 'opacity', 1),
+ ('license', 'style', 'opacity', 1)
+ )
+
+def introFrames(params):
+ # 7 Sekunden
+
+ # 2 Sekunden Text 1
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('box-und-text1', 'style', 'opacity', "%.4f" % easeOutCubic(i, 0, 1, frames)),
+ ('url', 'style', 'opacity', "%.4f" % easeOutCubic(i, 0, 1, frames)),
+ ('text1', 'style', 'opacity', "%.4f" % 1),
+ ('text2', 'style', 'opacity', 0)
+ )
+
+ # 1 Sekunde Fadeout Text 1
+ frames = 1*fps
+ for i in range(0, frames):
+ yield (
+ ('box-und-text1', 'style', 'opacity', 1),
+ ('url', 'style', 'opacity', 1),
+ ('text1', 'style', 'opacity', "%.4f" % (1-(float(i)/frames))),
+ ('text2', 'style', 'opacity', 0)
+ )
+
+ # 2 Sekunden Text 2
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('box-und-text1', 'style', 'opacity', 1),
+ ('url', 'style', 'opacity', 1),
+ ('text1', 'style', 'opacity', 0),
+ ('text2', 'style', 'opacity', "%.4f" % easeOutCubic(i, 0, 1, frames))
+ )
+
+ # 2 Sekunden stehen bleiben
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('box-und-text1', 'style', 'opacity', 1),
+ ('url', 'style', 'opacity', 1),
+ ('text1', 'style', 'opacity', 0),
+ ('text2', 'style', 'opacity', 1)
+ )
+
+def pauseFrames(params):
+ # 12 Sekunden
+
+ # 2 Sekunden Text1 stehen
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', 1),
+ ('text2', 'style', 'opacity', 0)
+ )
+
+ # 2 Sekunden Fadeout Text1
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', "%.4f" % (1-easeOutCubic(i, 0, 1, frames))),
+ ('text2', 'style', 'opacity', 0)
+ )
+
+ # 2 Sekunden Fadein Text2
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', 0),
+ ('text2', 'style', 'opacity', "%.4f" % easeOutCubic(i, 0, 1, frames))
+ )
+
+ # 2 Sekunden Text2 stehen
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', 0),
+ ('text2', 'style', 'opacity', 1)
+ )
+
+ # 2 Sekunden Fadeout Text2
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', 0),
+ ('text2', 'style', 'opacity', "%.4f" % (1-easeOutCubic(i, 0, 1, frames)))
+ )
+
+ # 2 Sekunden Fadein Text1
+ frames = 2*fps
+ for i in range(0, frames):
+ yield (
+ ('text1', 'style', 'opacity', "%.4f" % (easeOutCubic(i, 0, 1, frames))),
+ ('text2', 'style', 'opacity', 0)
+ )
+
+def debug():
+ render(
+ 'intro.svg',
+ '../intro.ts',
+ introFrames,
+ {
+ '$id': 904,
+ '$title': 'Was ist Open Source, wie funktioniert das?',
+ '$subtitle': 'Die Organisation der Open Geo- und GIS-Welt. Worauf man achten sollte.',
+ '$personnames': 'Arnulf Christl, Astrid Emde, Dominik Helle, Till Adams'
+ }
+ )
+
+ render(
+ 'outro.svg',
+ '../outro.ts',
+ outroFrames
+ )
+
+ render('pause.svg',
+ '../pause.ts',
+ pauseFrames
+ )
+
+def tasks(queue, args, idlist, skiplist):
+ # iterate over all events extracted from the schedule xml-export
+ for event in events(scheduleUrl):
+ if event['room'] not in ('HS Anatomie', 'HS Rundbau', 'HS Weismannhaus'):
+ print("skipping room %s (%s)" % (event['room'], event['title']))
+ continue
+
+
+ if (event['id'] in idlist or not idlist) and not 'intro' in skiplist:
+ # generate a task description and put them into the queue
+ queue.put(Rendertask(
+ infile = 'intro.svg',
+ outfile = str(event['id'])+".ts",
+ sequence = introFrames,
+ parameters = {
+ '$id': event['id'],
+ '$title': event['title'],
+ '$url': event['url'],
+ #'$subtitle': event['subtitle'],
+ '$personnames': event['personnames']
+ }
+ ))
+
+ if not 'outro' in skiplist:
+ # place a task for the outro into the queue
+ queue.put(Rendertask(
+ infile = 'outro.svg',
+ outfile = 'outro.ts',
+ sequence = outroFrames
+ ))
+
+ if not 'pause' in skiplist:
+ # place the pause-sequence into the queue
+ queue.put(Rendertask(
+ infile = 'pause.svg',
+ outfile = 'pause.ts',
+ sequence = pauseFrames
+ ))
+
+
diff --git a/sotm2020/artwork/by-sa.svg b/sotm2020/artwork/by-sa.svg
new file mode 100644
index 0000000..f850297
--- /dev/null
+++ b/sotm2020/artwork/by-sa.svg
@@ -0,0 +1,199 @@
+
+
+
diff --git a/sotm2020/artwork/intro.svg b/sotm2020/artwork/intro.svg
new file mode 100644
index 0000000..e0ad092
--- /dev/null
+++ b/sotm2020/artwork/intro.svg
@@ -0,0 +1,262 @@
+
+
+
+
diff --git a/sotm2020/artwork/outro.svg b/sotm2020/artwork/outro.svg
new file mode 100644
index 0000000..6370785
--- /dev/null
+++ b/sotm2020/artwork/outro.svg
@@ -0,0 +1,354 @@
+
+
+
+
diff --git a/sotm2020/artwork/pause.svg b/sotm2020/artwork/pause.svg
new file mode 100644
index 0000000..d1342ee
--- /dev/null
+++ b/sotm2020/artwork/pause.svg
@@ -0,0 +1,199 @@
+
+
+
+
diff --git a/sotm2020/artwork/sotm2020logo.png b/sotm2020/artwork/sotm2020logo.png
new file mode 100644
index 0000000..917b20f
Binary files /dev/null and b/sotm2020/artwork/sotm2020logo.png differ
diff --git a/sotm2020/artwork/uct.jpg b/sotm2020/artwork/uct.jpg
new file mode 100644
index 0000000..f00da7a
Binary files /dev/null and b/sotm2020/artwork/uct.jpg differ