bugfixes in preparesite, work in progress
authorSabine Engelhardt (Becker) <frosch@atari-frosch.de>
Thu, 6 Apr 2017 23:07:20 +0000 (01:07 +0200)
committerSabine Engelhardt (Becker) <frosch@atari-frosch.de>
Thu, 6 Apr 2017 23:07:20 +0000 (01:07 +0200)
14 files changed:
.gitignore [new file with mode: 0644]
ToDo
filters/__init__.py [new file with mode: 0755]
filters/__pycache__/atarifrosch.cpython-34.pyc [new file with mode: 0644]
filters/atarifrosch.py
htmlglue.py
preparesite.py
sites/atarifrosch/DEFAULTS/__pycache__/settings.cpython-34.pyc [new file with mode: 0644]
sites/atarifrosch/DEFAULTS/settings.py
sites/atarifrosch/backup.zip [new file with mode: 0644]
sites/atarifrosch/internet/__init__.py [deleted file]
sites/atarifrosch/internet/menu.py [deleted file]
sites/atarifrosch/internet/stream-mit-linux.htm [deleted file]
sites/atarifrosch/internet/stream-mit-linux.py [deleted file]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..5ccff1a
--- /dev/null
@@ -0,0 +1 @@
+html/
diff --git a/ToDo b/ToDo
index 936c139..6f1481f 100644 (file)
--- a/ToDo
+++ b/ToDo
@@ -1,81 +1,5 @@
-get own path from sys.argv[0]
-get theme dir from sys.argv[1]
-opt: get dir or file to build from sys.argv[n]
-no additional parameter(s): (re)build whole site
--d --dir $dir 
--f --file $file
--r --recursive (with -d, ignore if -f)
+preparesite.py:
 
-does theme dir exist?
-opt: does dir/file exist?
-
-theme dir must have subdirs CSS, DEFAULT, SNIPPETS
-theme dir must have index.py, index.htm, menu.py
-subdir CSS must have at least one css file
-subdir DEFAULTS must have at least settings.py
-subdir SNIPPETS must have at least
-- bodytop.htm
-- footer.htm
-- endoffile.htm
-
-add DEFAULTS, SNIPPETS to path
-
-does theme/html exist, if not: mkdir
-
-full (re)build (no parameters given)
-or (recursive) (re)build of one folder
-
-if -d|--dir:
-- if menu.py:
-  - import menu.py
-  - if -r|--recursive (as function):
-    - read all folder names from menu.py in folderlist[]
-    - use folderlist to read menu.py from each subfolder
-    - add all found folders to folderlist[]
-      (need to remember current dir!)
-    - recursive, until all menu.py are processed
-
-    - for each folder in folderlist[]:
-      - import menu.py
-        - for each menuitem[]: function makemenuitem
-
-def makemenuitem(menuitem):
-- split into its parts (must be 4 parts) 
-- if menuitem is htm (part 0):
-  - check whether according content file (.htm) exists in currentdir
-    - if not: pass
-  - check whether according .py file exists in currentdir
-    - if not: pass
-  - call function buildpage with filename, currentdir
-
-def buildpage(filename, currentdir)
-- build page targetfile with settings, SNIPPETS, and menulist
-- Build <head> section like footer in settings.py?
-  - Reason: replacements must be placed correctly.
-- import DEFAULTS/settings.py 
-  - add currentdir to path (in order to import .py files)
-  - import menu.py from currentdir
-  - if according menuitem exists:
-    - split into its parts (must be 4 parts)
-    - check whether according content file exists in currentdir
-    - check whether according content file (.htm) exists in currentdir
-      - if not: pass
-    - check whether according .py file exists in currentdir
-      - if not: pass
-    - call function buildpage with filename, currentdir
-    - build page targetfile with settings, SNIPPETS, and menulist
-      - import DEFAULTS/settings.py 
-      - add currentdir to path (in order to import .py files)
-      - import $page.py (menuitem part 2)
-      - own menu entry without link to itself
-          
-
-if -f|--file targetfile:
-- create currentdir and contentfile from targetfile
-- buildpage(contentfile, currentdir)
-
-----------------------------------------------------------------
-
-Additional function: Get content file date from original (old) html files
-and write to DEFAULTS/modif.lst
-delete entries from modif.lst when once used
+* BUG: creation of non existing directories
+* BUG: addcssfiles adds the wrong line part
+* BUG: favicon also adds wrong line part to $file.py
diff --git a/filters/__init__.py b/filters/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/filters/__pycache__/atarifrosch.cpython-34.pyc b/filters/__pycache__/atarifrosch.cpython-34.pyc
new file mode 100644 (file)
index 0000000..53184c2
Binary files /dev/null and b/filters/__pycache__/atarifrosch.cpython-34.pyc differ
index ef71a6f..ac53bc9 100755 (executable)
@@ -2,8 +2,8 @@
 # -*- coding: utf8 -*-
 
 origpath = "/srv/atarifrosch/"
-filext = ".html"
-targetpath = "/home/frosch/projekte/htmlglue/themes/atarifrosch/"
+fileext = ".html"
+targetpath = "/home/frosch/projekte/htmlglue/sites/atarifrosch/"
 
 ignoredirs = ["bilder", "computer/hw", "computer/x100e", "depression/tagebuch"]
 ignorefiles = []
@@ -15,10 +15,10 @@ ignorehtml = []
 # Only preparesite.py changes this into a dictionary.
 # Do NOT ignore the menu here, as it needs a special 'treatment'.
 
-ignorehtml[0] = '<body>%%<!--div#logo-->'
-ignorehtml[1] = '<div id="footer">%%</html>'
-ignorehtml[2] = '<!--[if gte IE 5.5]>%%<![endif]-->'
-ignorehtml[3] = '<!-- AKVS body start v1.6 -->%%<!-- AKVS body end -->'
+ignorehtml.append('<body> == <!--div#logo-->')
+ignorehtml.append('<div id="footer"> == </html>')
+ignorehtml.append('<!--[if gte IE 5.5]> == <![endif]-->')
+ignorehtml.append('<!-- AKVS body start v1.6 --> == <!-- AKVS body end -->')
 
 menustart = '<div id="menu">'
 menuend = '<!-- div#menu -->'
index 932afce..db716c5 100755 (executable)
@@ -1,6 +1,85 @@
 #!/usr/bin/env python3
 # -*- coding: utf8 -*-
 
+'''
+get own path from sys.argv[0]
+get theme dir from sys.argv[1]
+opt: get dir or file to build from sys.argv[n]
+no additional parameter(s): (re)build whole site
+-d --dir $dir 
+-f --file $file
+-r --recursive (with -d, ignore if -f)
+
+does theme dir exist?
+opt: does dir/file exist?
+
+theme dir must have subdirs CSS, DEFAULT, SNIPPETS
+theme dir must have index.py, index.htm, menu.py
+subdir CSS must have at least one css file
+subdir DEFAULTS must have at least settings.py
+subdir SNIPPETS must have at least
+- bodytop.htm
+- footer.htm
+- endoffile.htm
+
+add DEFAULTS, SNIPPETS to path
+
+does theme/html exist, if not: mkdir
+
+full (re)build (no parameters given)
+or (recursive) (re)build of one folder
+
+if -d|--dir:
+- if menu.py:
+  - import menu.py
+  - if -r|--recursive (as function):
+    - read all folder names from menu.py in folderlist[]
+    - use folderlist to read menu.py from each subfolder
+    - add all found folders to folderlist[]
+      (need to remember current dir!)
+    - recursive, until all menu.py are processed
+
+    - for each folder in folderlist[]:
+      - import menu.py
+        - for each menuitem[]: function makemenuitem
+
+def makemenuitem(menuitem):
+- split into its parts (must be 4 parts) 
+- if menuitem is htm (part 0):
+  - check whether according content file (.htm) exists in currentdir
+    - if not: pass
+  - check whether according .py file exists in currentdir
+    - if not: pass
+  - call function buildpage with filename, currentdir
+
+def buildpage(filename, currentdir)
+- build page targetfile with settings, SNIPPETS, and menulist
+- Build <head> section like footer in settings.py?
+  - Reason: replacements must be placed correctly.
+- import DEFAULTS/settings.py 
+  - add currentdir to path (in order to import .py files)
+  - import menu.py from currentdir
+  - if according menuitem exists:
+    - split into its parts (must be 4 parts)
+    - check whether according content file exists in currentdir
+    - check whether according content file (.htm) exists in currentdir
+      - if not: pass
+    - check whether according .py file exists in currentdir
+      - if not: pass
+    - call function buildpage with filename, currentdir
+    - build page targetfile with settings, SNIPPETS, and menulist
+      - import DEFAULTS/settings.py 
+      - add currentdir to path (in order to import .py files)
+      - import $page.py (menuitem part 2)
+      - own menu entry without link to itself
+          
+
+if -f|--file targetfile:
+- create currentdir and contentfile from targetfile
+- buildpage(contentfile, currentdir)
+
+'''
+
 import sys, os
 from time import strftime
 from datetime import datetime
index 15f88e0..76ac5a8 100755 (executable)
@@ -6,10 +6,10 @@ from time import strftime, gmtime
 from datetime import datetime
 from subprocess import call
 
-mypath = sys.argv[0]
-theme = sys.argv[1]
-sys.path.insert(0, mypath)
-flt = __import__(theme)
+sitename = sys.argv[1]
+filterpath = "filters/"
+sys.path.insert(0, filterpath)
+flt = __import__(sitename)
 
 if not flt.origpath.startswith("/"):
     print("This is no full path. Stop.")
@@ -39,7 +39,7 @@ if not os.path.exists(targetpath):
     newdir = targetpath + "/SNIPPETS"
     os.mkdir(newdir, "0755")
     print("Please create at least DEFAULTS/settings.py.")
-    print("Without that file the site cannot be prepared for htmlglue.")
+    print("Without a filter the site cannot be prepared for htmlglue.")
     exit()
 
 settingpath = targetpath + "DEFAULTS/"
@@ -48,8 +48,9 @@ import settings
 
 
 if len(flt.ignorehtml) > 0:
+    ignorehtml = {}
     for i in range(len(flt.ignorehtml)):
-        ignorehtmlparts = flt.ignoreparts[i].split("%%")
+        ignorehtmlparts = flt.ignorehtml[i].split(" == ")
         ignorehtml[ignorehtmlparts[0]] = ignorehtmlparts[1]
 
 for dirpath, dirs, files in os.walk(origpath):
@@ -61,13 +62,22 @@ for dirpath, dirs, files in os.walk(origpath):
             htmlfile.close()
             htmllines = html.split("\n")
 
-            targethtm = targetpath + dirpath + "/" + filename.replace(".html", ".htm")
-            targetpy = targetpath + dirpath + "/" + filename.replace(".html", ".py")
+            curpath = dirpath.replace(origpath, "/")
+
+            if curpath != "/":
+                targetpath += curpath
+                if not os.path.exists(targetpath):
+                    os.mkdir(targetpath)
+
+            targethtm = targetpath + filename.replace(".html", ".htm")
+            targetpy = targetpath + filename.replace(".html", ".py")
 
             htm = open(targethtm, "w")
             pyfile = open(targetpy, "w")
 
-            curtime = strftime("%Y-%m-%d %H:%M", datetime.now())
+            curtime = datetime.now()
+            curtimestamp = curtime.strftime("%Y-%m-%d %H:%M")
+
             pyfile = open(targetpy, "w")
             pyhead = "#!/usr/bin/env python3\n"
             pyhead += "# -*- coding: utf8 -*-\n\n"
@@ -75,7 +85,7 @@ for dirpath, dirs, files in os.walk(origpath):
             pyhead += "# THIS FILE WAS GENERATED AUTMATICALLY FROM\n"
             pyhead += "# " + curfile + "\n"
             pyhead += "# BY preparesite.py FROM htmlglue WITH FILTER AND SETTINGS FROM\n"
-            pyhead += "# " + theme + ", " + curtime + "\n"
+            pyhead += "# " + sitename + ", " + curtimestamp + "\n"
             pyhead += "######################################################################\n\n\n"
             pyfile.write(pyhead)
 
@@ -115,7 +125,7 @@ for dirpath, dirs, files in os.walk(origpath):
                 if contentread:
                     for item in flt.replacement:
                         if item in curline:
-                            curline = curline.replace(item, ftl.replacement[item])
+                            curline = curline.replace(item, flt.replacement[item])
                     htm.write(curline + "\n")
                     if flt.contentend in curline:
                         contentread = False
@@ -145,8 +155,9 @@ for dirpath, dirs, files in os.walk(origpath):
                         pyfile.write(outline)
                 elif "<meta" in curline:
                     curline = curline.replace(" = ", "=")
-                    lineparts = curline.split('content="')
-                    contentpart = contentpart.replace("/>", "")
+                    lineparts = curline.split('content="')[1]
+                    contentpart = lineparts.replace("/>", "")
+                    contentpart = contentpart.replace('"', '')
                     contentpart = contentpart.strip()
                     if 'name="robots"' in curline:
                         if contentpart != settings.robots:
@@ -165,7 +176,7 @@ for dirpath, dirs, files in os.walk(origpath):
                         if contentpart != settings.dctitle:
                             pyfile.write("dctitle = '" + contentpart + ln)
                     elif "DC.Creator" in curline:
-                        if contentpart != settings.dcreator:
+                        if contentpart != settings.dccreator:
                             pyfile.write("dcreator = '" + contentpart + ln)
                     elif "DC.Publisher" in curline:
                         if contentpart != settings.dcpublisher:
@@ -181,11 +192,11 @@ for dirpath, dirs, files in os.walk(origpath):
                         filetime = gmtime(os.path.getmtime(curfile))
                         fileday = strftime('%Y-%m-%d', filetime)
                         # this is needed later for touching the .htm file
-                        # after it was closed
+                        # after closing it
                         if contentpart == fileday:
                             htmtouchtime = strftime("%Y%m%d%H%M.%S", filetime)
                         else:
-                            htmtouchtime = dcdate.replace("-", "") + "000000"
+                            htmtouchtime = contentpart.replace("-", "") + "0000"
                 elif '<link rel=' in curline:
                     lineparts = curline.split('href="')
                     contentpart = lineparts[0].split('"', 1)[0]
@@ -198,7 +209,8 @@ for dirpath, dirs, files in os.walk(origpath):
                             media = curline.split('media="')[0]
                             media = media.split('"', 1)[0]
                             addcss = contentpart + " " + media
-                            addcssfile += addcss
+                            addcssfile.append(addcss)
+
                 elif flt.headlinekey in curline:
                     headline = curline.split(flt.headlinekey)[1]
                     headlineend = flt.headlinekey.replace("<h", "</h")
@@ -206,13 +218,51 @@ for dirpath, dirs, files in os.walk(origpath):
                     headline = headline.strip()
                     pyfile.write("headline = '" + headline + ln)
 
-            pyfile.write("addcssfile = " + addcssfile)
+            addcssitems = '['
+            for i in range(len(addcssfile)):
+                addcssitems += '"' + addcssfile[i]
+                if i < len(addcssfile):
+                    addcssitems += '", '
+                else:
+                    addcssitems += '"]'
+            pyfile.write("addcssfile = " + addcssitems + ln)
             pyfile.close()
 
             if curfile.endswith("index.html"):
-                # build menu.py using origmenu and os.dirlist(dir)
-                pass
-
+                # this tells us the order of the menu items
+                origmenuparts = origmenu.split("\n")
+                # curfilelist = os.dirlist(dirpath)
+                menufile = dirpath + "/menu.py"
+                menu = open(menufile, "w")
+                menu.write("#!/usr/bin/env python3\n")
+                menu.write("# -*- coding: utf8 -*-\n\n\n")
+                menu.write("# Created automatically with htmlglue/preparesite\n\n")
+                menucounter = 0
+                for item in range(len(origmenuparts)):
+                    curitem = origmenuparts[item].strip()
+                    if curitem.startswith("<li"):
+                        if curitem.startswith("<li class="):
+                            menuclass = curitem.split("class=")[1]
+                            menuclass = menuclass.split(">")[0]
+                            menuclass = menuclass.replace('"', '')
+                        if "href" in curitem:
+                            menuhref = curitem.split("href=")[1]
+                            menuhref = menuhref.split(">")
+                            filename = menuhref[0]
+                            menuitemname = menuhref[1].replace("</a", "")
+                            menuitemname = menuitemname.replace('"', '')
+                            if filename.endswith("/"):
+                                filetype = "dir"
+                            elif filename.endswith(".htm") or filename.endswith(".html"):
+                                filetype = "htm"
+                            else:
+                                filetype = "???"
+                            menufilename = filename.replace("/", "")
+                            outline = 'menuitem[' + str(menucounter) + '] = "'
+                            outline += filetype + ', ' + menuclass + ', '
+                            outline += menufilename + ', ' + menuitemname + '"\n'
+                            menu.write(outline)
+                            menucounter += 1
 
-# with dirlisting of current dir (file/dirnames) and the menu structure of
-# the index.html of current dir build menu.py for current output path
+                menu.close()
+                call(["/bin/chmod", "755", menufile])
diff --git a/sites/atarifrosch/DEFAULTS/__pycache__/settings.cpython-34.pyc b/sites/atarifrosch/DEFAULTS/__pycache__/settings.cpython-34.pyc
new file mode 100644 (file)
index 0000000..810e92a
Binary files /dev/null and b/sites/atarifrosch/DEFAULTS/__pycache__/settings.cpython-34.pyc differ
index 91e4931..d55eec8 100755 (executable)
@@ -23,13 +23,14 @@ def makefooter(contentfile, targetfile, myurl):
     return footer
 
 
-theme = atarifrosch
+theme = "atarifrosch"
 proto = "https"
 domain = "www.atari-frosch.de"
 myurl = proto + "://" + domain + "/"
 
 doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
 htmlver = '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">'
+title = "Atari-Frosch"
 robots = 'index,follow'
 # language will also be used for DC.Language
 language = 'de'
@@ -52,7 +53,6 @@ metakeywords = "atari-frosch, atari, computer, depression, autismus"
 # dictionary of variables within content files which need to be replaced
 # can be extended in $file.py files
 
+replacement = {}
 replacement["[FLATTRBUTTON]"] = "flattrbutton.htm"
 replacement["[FLATTRSCRIPT]"] = "flattrscript.htm"
-
-pagefoot = makefoot(contentfile, targetfile, myurl)
diff --git a/sites/atarifrosch/backup.zip b/sites/atarifrosch/backup.zip
new file mode 100644 (file)
index 0000000..9ce0ffd
Binary files /dev/null and b/sites/atarifrosch/backup.zip differ
diff --git a/sites/atarifrosch/internet/__init__.py b/sites/atarifrosch/internet/__init__.py
deleted file mode 100755 (executable)
index e69de29..0000000
diff --git a/sites/atarifrosch/internet/menu.py b/sites/atarifrosch/internet/menu.py
deleted file mode 100755 (executable)
index f21965e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf8 -*-
-
-menuitem[0]  = "htm, file, index.html, Startseite"
-menuitem[1]  = "dir, close, vorstellung, Vorstellung"
-menuitem[2]  = "dir, close, https://blog.atari-frosch.de/, Blog"
-menuitem[3]  = "dir, close, computer, Computer"
-menuitem[4]  = "dir, open, internet, Internet"
-menuitem[5]  = "htm, file1, iptables, IPtables"
-menuitem[6]  = "htm, file1, spammail, Spammail-Stats"
-menuitem[7]  = "htm, file1, internetsperren, Internetsperren"
-menuitem[8]  = "htm, file1, pgp, PGP"
-menuitem[9]  = "htm, file1, stream-mit-linux, Internet-Radio"
-menuitem[10] = "htm, file1, usenet, Usenet"
-menuitem[11] = "htm, file1, zcheaderfaq, ZC-Header-FAQ"
-menuitem[12] = "htm, file1, netzserie, Netz-Serie"
-menuitem[13] = "htm, file1, webseiten, Webseiten"
-menuitem[14] = "htm, file1, html-richtig, Richtiges HTML"
-menuitem[15] = "htm, file1, dsl, DSL-Erlebnis"
-menuitem[16] = "htm, file1, telekom-post, Anschluß-Sperre"
-menuitem[17] = "htm, file1, weihnachtsmail, Weihnachtsmails"
-menuitem[18] = "htm, file1, dmmv, DMMV und Spam"
-menuitem[19] = "htm, file1, hommingberger, SEO Gepardenforelle"
-menuitem[20] = "dir, close, politik, Politik"
-menuitem[21] = "dir, close, depression, Depression"
-menuitem[22] = "dir, close, hobby, Hobbies"
-menuitem[23] = "dir, close, musik, Musik"
-menuitem[24] = "dir, close, fotografie, Fotografie"
-menuitem[25] = "dir, close, pretender, Pretender"
-menuitem[26] = "dir, close, flohmarkt, Flohmarkt"
-menuitem[27] = "dir, close, misc, Vermischtes"
-menuitem[28] = "htm, file, impressum.html, Impressum"
diff --git a/sites/atarifrosch/internet/stream-mit-linux.htm b/sites/atarifrosch/internet/stream-mit-linux.htm
deleted file mode 100644 (file)
index 808d3d5..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-      <div id="content">
-        <p>Auf dieser Seite möchte ich darüber berichten, wie ich ein
-            Internet-Radio ausschließlich mit Linux-Rechnern betreibe. Der
-            Aufbau ist etwas kompliziert; ich hatte einiges zu lesen, zu
-            basteln und zu suchen, bis alles funktionierte. Hier zeige ich,
-            was ich herausgefunden habe, und vor allem auch, mit welchen
-            Tücken ich zu kämpfen hatte.</p>
-        <p>Die Tücken entstanden vor allem deshalb, weil ich nicht einfach
-            Musik irgendwohin streamen, sondern „richtiges“ Radio
-            mit Moderation machen möchte. Wenn man einfach nur eine Playlist
-            laufen lassen will, die im LAN oder im Internet empfangen werden
-            kann, ist alles viel einfacher.</p>
-        <blockquote>
-          <strong> Update 2011-12-29</strong> Komplette Überarbeitung:
-            Anweisungen für Debian sarge, etch und lenny raus, alles auf
-            Debian squeeze abgestimmt, und alles gelöscht, was mit jackd zu
-            tun hat, weil der nun wirklich nicht mehr gebraucht wird.
-        </blockquote>
-        <h2>Streaming-Vorgang</h2>
-        <p>Um die folgenden Erklärungen besser zu verstehen, ist es
-            sinnvoll, ein bißchen was darüber zu wissen, was beim Streamen
-            eigentlich so alles passiert.</p>
-        <p>Klangdaten (Sprache, Musik) aus verschiedenen Quellen (zum
-            Beispiel Musikdateien, CD, Mikrofon) werden, teils mit Hilfe
-            entsprechender Software, von der Soundkarte wiedergegeben. 
-            Währenddessen werden sie von einer weiteren Software sofort
-            wieder als Rohdaten abgegriffen und in ein einheitliches Format
-            gebracht („encoded“; das kann MP3 sein, aber auch
-            OggVorbis, AAC oder FLAC).  Daraus wird ein Datenstrom erzeugt,
-            der an einen Server geschickt wird.  Dieser Server fungiert als
-            Verteiler; von dort aus können Hörer sich mit einem Player
-            einklinken und den erzeugten Datenstrom (engl: data stream oder
-            einfach stream) empfangen.  Für den Player sieht das dann so
-            aus, als ob er eine einzige Musikdatei abspielt, deren Größe er
-            nicht kennt. </p>
-        <h2>Hardware</h2>
-        <h3>Stream-PC</h3>
-        <p>Beim streamenden Rechner sind zwei Komponenten entscheidend: CPU
-            und Soundkarte. Bei aktuelleren Rechnern ist das meist kein
-            Thema; wer aber wie ich auf überwiegend ältere Hardware
-            zurückgreifen muss, könnte hier schnell an Grenzen stoßen.</p>
-        <h4>CPU</h4>
-        <p>Der Prozessor des streamenden Rechners sollte nicht weniger als
-            500&nbsp;MHz haben. Der Grund ist das rechenaufwendige Encoden
-            der Klangdaten von der Soundkarte in das Zielformat des Streams. 
-            Mit seinen 500&nbsp;MHz hatte mein
-          <a href="/computer/pc/seerose-piii500.html">PIII</a> schon teils
-            heftig zu kämpfen; die CPU-Auslastung lag zwischen 80 und
-            90&nbsp;%. Mit meinem
-          <a href="/computer/pc/seerose-athlon.html">Athlon XP1800+</a>
-            komme ich immer noch auf 30 - 35&nbsp;% Auslastung.</p>
-        <p>Höhere Taktraten sind insbesondere dann angeraten, wenn</p>
-        <ul>
-          <li>die abgespielten Musikdateien variable Bitraten haben;</li>
-          <li class="text"> nicht MP3, sondern OggVorbis erzeugt werden
-               soll. Der Rechenaufwand ist dafür erheblich höher als für MP3
-               (den für AAC kenne ich nicht, habe ich nicht getestet).</li>
-          <li class="text"> bereits das Abspielen eines Soundformats
-               rechenaufwendig ist. So lastet eine .sid-Datei (Klangdatei
-               vom C64) die CPU selbst schon ordentlich aus; ich habe es gar
-               nicht erst versucht, mit dem PIII eine solche Datei auf
-               meinen MP3-Stream zu bringen.</li></ul>
-        <p>Was passiert, wenn die CPU nicht leistungsfähig genug ist? Nun,
-            dann können die Ausgangsdaten nicht schnell genug encoded
-            werden, und es entstehen „buffer underruns“. Das
-            heißt, der Server bekommt weniger Daten, als er senden will. Das
-            kann soweit gehen, daß die Player der Hörer ins timeout laufen
-            und vom Stream getrennt werden.</p>
-        <p>Wenn kein schnellerer Rechner zur Verfügung steht, kann man wohl
-            dadurch Abhilfe schaffen, daß man zwei PCs miteinander verbindet
-            und die Aufgaben verteilt. PC&nbsp;#1 spielt dann die Daten auf
-            seiner Soundkarte ab. Ein Kabel verbindet Line-Out dieser
-            Soundkarte mit Line-In der Soundkarte in PC&nbsp;#2. Dieser
-            kümmert sich um das Encoden und sendet an den Server. Auf diese
-            Weise sollen pro PC 350 bis 400&nbsp;MHz genügen; ich habe das
-            allerdings selbst noch nicht ausprobiert.</p>
-        <h4>Soundkarte</h4>
-        <p>Nicht jede Soundkarte ist auch zum Streamen geeignet! Bei mir
-            funktionieren folgende Karten:</p>
-        <ul><li>Creative SoundBlaster mit Chip Emu10K1</li>
-          <li>C-Media CMI87 (8738)</li></ul>
-        <p>Ich hatte es bei dem PIII tagelang mit der onboard-Soundkarte,
-            einer ESS Solo1 1938, probiert, um dann bei einer
-            Google-Recherche zu erfahren, daß das alles keinen Zweck hat.</p>
-        <p>Eine Soundkarte zum Streamen muß nämlich unbedingt Vollduplex
-            können. Der Grund ist wieder das Abgreifen der Klangdaten von
-            der Karte: Dafür wird ein „Rückkanal“ benötigt. Die
-            ESS Solo1 hat sowas einfach nicht. Egal ob man also eine der
-            oben genannten Karten benutzt oder eine andere: Sie muß
-            Vollduplex beherrschen, sonst kann man sie nicht einsetzen. Ich
-            habe eine C-Media 8738 bekommen, das funktioniert einwandfrei.
-            Und so nebenbei klingt sie auch wesentlich besser als die ESS
-            Solo1.</p>
-        <p>Allerdings gibt es mit der C-Media wieder ein anderes Problem:
-            Ein Mono-Mikrofon hört man lokal zwar auf beiden Kanälen, aber
-            die encodeten und gestreamten Klangdaten vom Mikrofon kommen bei
-            den Hörern nur noch auf einem Kanal an. Das kann bei Sendungen
-            mit größerem Redeanteil sehr störend sein.</p>
-        <h4>Mikrofon bzw. Headset</h4>
-        <p>Ein richtig gutes Mikrofon ist natürlich schick; allein, ich
-            kann mir keines leisten. Ich habe derzeit ein billiges
-            Logitech-Mikrofon in Betrieb. Das tut es zumindest für den
-            Anfang auch; Hörer bemängelten nur, daß das Mikrofon auch bei
-            höchster Sendeleistung, und obwohl ich es sehr dicht vorm Mund
-            hatte, etwas zu leise sei. Mittlerweile bin ich bei einem
-            einfachen Logitech-Mikrofon, das die gleichen Probleme zeigt;
-            billig ist halt billig.</p><hr />
-        <h3>Server</h3>
-        <p>Der Server, der wie gesagt einfach nur ein Verteiler ist,
-            braucht vor allem eine „dicke“ Leitung. Er muß die
-            Daten vom Stream-Rechner entgegennehmen und an die gewünschte
-            Anzahl Hörer wieder parallel raussenden können. Bei zwei Hörern
-            mag das vielleicht noch über eine DSL-Leitung gehen; wenn es
-            mehr sind, sollte es schon ein Rechner mit Standleitung sein.</p>
-        <p>Ansonsten vermute ich, daß der Server nicht zu wenig RAM haben
-            sollte, um die Daten zwischenspeichern zu können. Meinem alten
-          <a href="/computer/pc/seeadler.html">Rootserver</a> schienen seine
-            256&nbsp;MB RAM aber wohl bereits zu genügen.</p>
-        <h4>Vorsicht bei Traffic-Limits!</h4>
-        <p>Das einzige ernsthafte Problem, das hier auftauchen könnte, ist
-            ein Traffic-Limit des Server-Providers. Wenn man eines hat und
-            dieses überschreitet, kann es schnell teuer werden.</p>
-        <p>Ich habe ausgerechnet, daß man bei einer Bitrate
-            von 64&nbsp;kBit/s pro Hörer und Stunde mit ca. 30&nbsp;MB Traffic
-            rechnen muß. Dazu kommt der eingehende Datenstrom, also die
-            Datenmenge, die der Stream-PC an den Server sendet.
-            Rechenbeispiel:</p>
-        <p>Angenommen, ich sende täglich 10 Stunden lang. Dann entstehen
-            pro Hörer (plus Stream-PC) je 10 x 30&nbsp;MB Traffic pro Tag. 
-            Damit würden in einem Monat 30 x 300&nbsp;MB = 9.000&nbsp;MB
-            oder 9&nbsp;GB Traffic erzeugt.  Rein rechnerisch und rein auf
-            den Traffic bezogen könnte ich so mit einem Limit von
-            500&nbsp;GB locker 50&nbsp;Hörer versorgen (500&nbsp;GB / 9 =
-            55,55) – davon ausgehend, daß auf dem Server sonst keine
-            traffic-relevanten Dienste laufen. </p><hr />
-        <h2>Software</h2>
-        <p>Zum Streamen unter Linux ist, wenn man moderiertes
-            Internet-Radio machen möchte, ein kleines Konglomerat an
-            Software erforderlich.  Es gibt zwar auch fertige Pakete, aber
-            dabei lernt man ja nichts.&nbsp;;-) – abgesehen davon, daß
-            sich diese Pakete bei mir größtenteils gar nicht zum
-            Installieren überreden lassen wollten und das einzige, das ich
-            installiert bekommen habe, eine für mich völlig unverständliche
-            Oberfläche mitbringt.</p>
-        <h3>Stream-PC</h3>
-        <p>Derzeit installiert ist 
-          <a href="http://www.debian.org/">Debian</a> GNU/Linux 6.0 Squeeze.
-            Im Gegensatz zu früheren Installationen baue ich den Kernel
-            mittlerweile nicht mehr selbst, weil der Distributionskernel
-            alles mitbringt, was ich brauche.</p>
-        <h4>Was wird benötigt?</h4>
-        <ul><li><em> Mixer:</em> Es werden zwei Mixer benötigt, und zwar der
-               alsamixer für Grundeinstellungen und ein
-               zusätzlicher, der die „Aussteuerung“ zum Senden
-               regelt. Das kann der alsamixer nämlich nicht. Ich habe dafür
-               aumix-gtk genommen.</p>
-          <li class="text"><em> Player:</em> Um Musik abzuspielen, können
-               beliebige Player genommen werden; er sollte der Einfachheit
-               halber mal mindestens Playlisten kennen. Ich bevorzuge
-               mittlerweile audacious.</p>
-          <li class="text"> CDs spiele ich nicht direkt ab; die rippe ich
-               vorher und packe sie auf meine Musik-Partition. Allerdings
-               kann audacious über ein Plugin auch CDs abspielen.</li>
-          <li class="text"><em> Streamer:</em> Dieses Programm übernimmt die
-               wieder eingesammelten Klang-Rohdaten von der Soundkarte
-               und kümmert sich sowohl um das Encoding als auch darum,
-               daß der Datenstrom zum Server gelangt. Hier habe ich darkice
-               gewählt, und zur besseren Bedienung die grafische Oberfläche
-               darksnow.</li></ul>
-        <p>So, und jetzt dröseln wir das mal in die nötigen Pakete auf.
-          <em>Für die nächsten Schritte muß man root sein!</em>
-            Zuerst ist es notwendig, in
-          <em class="unprop">/etc/apt/sources.list</em> eine zusätzliche
-            Paketquelle einzutragen:</p>
-        <div class="console">
-          <p>deb http://www.debian-multimedia.org $distri main</p></div>
-        <p>In diesem Fall steht $distri für squeeze oder stable. Nach
-            diesem Eintrag kann man einen Teil der benötigten Pakete direkt
-            mit apt-get ziehen, und zwar:</p>
-        <div class="console">
-          <p>$ apt-get install alsa-utils aumix-gtk lame audacious darksnow</p></div>
-        <p>Die nötigen Libs werden nachgezogen und sind hier nicht extra
-            aufgeführt; statt audacious kann, wie erwähnt, ein beliebiger
-            anderer Player gewählt werden. Wer einen Teil der Pakete schon
-            installiert hat, kann diese natürlich hier rauslassen.</p>
-        <p>darksnow zieht automatisch das (nur OGG-fähige) Paket darkice
-            nach; daher ist es für einen MP3-Stream immer noch sinnvoll,
-            darkice zusätzlich selbst zu bauen. Das liegt daran, daß MP3
-            kein freies Format ist und daher von Software in Debian nicht
-            erzeugt werden darf. Wer nur in OGG Vorbis streamen will, kann
-            sich diese Zusatzarbeit natürlich sparen.</p>
-        <h4>darkice compilieren</h4>
-        <p>Wenn man sich den Tarball für darkice heruntergeladen hat, kann
-            man die Sourcen noch lange nicht compilieren. Zunächst werden
-            nämlich einige development files von libraries benötigt, ohne die
-            darkice nicht gebaut werden kann.</p>
-        <p>Ich war hier insbesondere über einen Bug in der Version 0.17.1
-            von darkice gestolpert, die mir beim ./configure bestätigte, daß
-            alle benötigten Dateien vorhanden seien. Tatsächlich fehlte aber
-            eine Datei, die darkice zur Kommunikation mit jackd benötigt. In
-            der Version 0.18.1 war dieser Bug dann behoben.</p>
-        <p>Also, erstmal devel-files „nachladen“:</p>
-        <div class="console">
-          <p>$ apt-get install libasound2-dev libmp3lame-dev</p></div>
-        <p>Jetzt kann es losgehen: Erst noch in das Verzeichnis wechseln, in
-            welchem der Tarball steht (ich nehme dafür meist
-          <em class="unprop">/usr/src/</em> bzw. verschiebe Tarballs
-            dorthin). Dann:</p>
-        <div class="console">
-          <p>$ tar -xzf darkice-0.18.1.tar.gz</p>
-          <p>$ cd darkice-0.18.1</p>
-          <p>$ ./configure --with-alsa --with-lame</p>
-          <p>$ make</p>
-          <p>$ make install</p></div>
-        <p>Die Versionsnummer ist natürlich nur ein Beispiel, die 0.18.1
-            ist nicht mehr aktuell.</p>
-        <p>Wenn beim ./configure Warnhinweise auftauchen, fehlt was. Am
-            besten findet man das entsprechende Paket mit apt-cache search
-            auf das, was er als fehlend bemängelt, und dev. Wird also
-            beispielsweise lame als fehlend angezeigt, hilft wahrscheinlich
-            ein</p>
-        <div class="console">
-          <p>$ apt-cache search lame dev</p></div>
-        <p>Es fehlt also dann nicht das eigentliche Paket, sondern
-            die dazugehörigen development files.</p><hr />
-        <h3>Server</h3>
-        <p>Hier ist alles viel einfacher:</p>
-        <div class="console">
-          <p>$ apt-get install icecast2</p></div>
-        <p>… und die Installation ist gegessen.</p>
-        <hr /> 
-        <h3>Konfiguration</h3>
-        <p>Zur Konfiguration sämtlicher Programme habe ich überwiegend das
-          <a href="http://de.gentoo-wiki.com/XBox360">XBox360-HowTo</a> aus
-            dem Gentoo-Wiki genutzt, vielen Dank an den Autor!</p>
-        <p>(Die Bilder sind aus den Sarge-Versionen; die Fenster
-            unterscheiden sich manchmal in neueren Versionen, aber
-            eigentlich nur in der Anordnung, und auch nur minimal.)</p>
-        <h4>darkice mit darksnow konfigurieren</h4>
-        <p>Der erste Kandidat ist <em>darkice.</em> Dazu startet man
-            darksnow und trägt dort ein paar Angaben ein (anklicken zum
-            vergrößern):</p>
-        <div class="picleft">
-          <a class="graflink" href="/bilder/darksnow-screen.jpg">
-            <img src="/bilder/darksnow-screen-preview.jpg" width="300"
-                 height="323" alt=" " />
-          </a></div>
-        <p>„radio.meinserver.de“ muss natürlich durch den
-            echten Namen (oder die IP) des Stream-Servers ersetzt werden.</p>
-        <p>Am meisten zu schaffen machte mir der Begriff <em>Mount
-            Point</em>. Denn eigentlich verstehe ich darunter ein
-            Verzeichnis in meinem Verzeichnisbaum, in welches ich ein Medium
-            (bzw. ein Filesystem) einklinken (mounten) kann. Schließlich kam
-            ich auf den Trichter: Das ist einfach ein Dateiname, den der
-            Server den Playern anbieten kann, weil die einen benötigen. Denn
-            den Playern wird ja der Stream wie eine Datei übergeben. Das
-            wird aber nirgendwo erklärt oder auch nur erwähnt!</p>
-        <p>Das Paßwort muß natürlich mit dem in der icecast2-Konfiguration
-            auf dem Server (siehe weiter unten) übereinstimmen.</p>
-        <p>Wenn der Stream-PC und/oder der Server genügend Plattenplatz
-            anbieten, kann man sich von den Sendungen einen Dump
-            (Mitschnitt) anlegen lassen. Dann wird die gesamte Sendung in
-            eine Datei im Zielformat des Streams gespeichert. Auf dem PIII
-            hatte das bei mir nie funktioniert, der Athlon packt es
-            inzwischen (vermutlich auch deshalb, weil die Musikdateien
-            mittlerweile auf einer SATA- und nicht mehr auf einer IDE-Platte
-            liegen). Auf dem Server tut es bei mir nicht; möglicherwiese
-            kann icecast2 das nicht, oder es fehlt noch etwas.</p>
-        <div class="picleft">
-          <a class="graflink" href="/bilder/darksnow-screen1.jpg">
-            <img src="/bilder/darksnow-screen1-preview.jpg" width="300"
-                 height="319" alt="Textaufarbeitung des Screenshots folgt noch!" />
-          </a></div>
-        <p>Im zweiten Reiter wird unter anderem die Bitrate festgelegt. Sie
-            bestimmt primär über die Qualität des Streams, aber auch über
-            die benötigte Bandbreite auf den Leitungen.</p>
-        <p>Der letzte Eintrag in diesem Reiter, „Device input“,
-            muß nur für jackd wie abgebildet „jack_auto“ heißen. 
-            Wenn ohne jackd gearbeitet wird, wird hier „hw0,0“
-            eingetragen (davon ausgehend, daß bei mehreren vorhandenen
-            Soundkarten die erste zum Streamen gewählt wird).</p>
-        <p>Bei der Stream-Beschreibung im dritten Reiter ist man recht frei
-            (der Servername muß nur stimmen). Ein rechtlich relevanter
-            Eintrag ist aber der letzte: Ich habe meinen Stream auf nicht
-            öffentlich gesetzt, weil ich sonst GEMA-Gebühren bezahlen und
-            mich nach deren ziemlich kruden Regeln richten müßte. Statt
-            dessen gebe ich die Adresse für den Stream nur gezielt an
-            Freunde, die ich mithören lassen möchte.</p>
-        <p>Am Ende nicht vergessen, die Config abzuspeichern, darksnow
-            macht das nicht von allein. Etwas störend ist auch, daß darksnow
-            diese Config auch beim Start nicht wieder automatisch lädt, das
-            muß man jedesmal von Hand machen.</p>
-        <h4>icecast2 konfigurieren</h4>
-        <p>Ich sollte vielleicht erwähnen, daß der icecast2 nicht nur ein
-            reiner Streamserver ist. Er bringt auch noch einen kleinen
-            Webserver mit, der ebenfalls auf Port 8000 läuft (sofern das
-            nicht geändert wird).</p>
-        <p>icecast2 wird komplett über die Datei
-          <em class="unprop">/etc/icecast2/icecast.xml</em> gesteuert. Darin
-            sind die folgenden Einträge relevant:</p>
-        <div class="console">
-          <p>&lt;limits&gt;</p>
-          <p>&lt;clients&gt;20&lt;/clients&gt;</p>
-          <p>&lt;!-- Legt die Höchstzahl der Hörer fest --&gt;</p>
-          <p>&lt;/limits&gt;</p>
-          <p>&nbsp;</p>
-          <p>&lt;authentication&gt;</p>
-          <p>&lt;source-password&gt;xxxxxxxxxxxx&lt;/source-password&gt;</p>
-          <p>&lt;!-- Muss mit dem in darkice/darksnow übereinstimmen! --&gt;</p>
-          <p>&lt;/authentication&gt;</p>
-          <p>&nbsp;</p>
-          <p>&lt;hostname&gt;radio.meinserver.de&lt;/hostname&gt;</p>
-          <p>&nbsp;</p>
-          <p>&lt;listen-socket&gt;</p>
-          <p>&lt;port&gt;8000&lt;/port&gt;</p>
-          <p>&lt;!--  &lt;bind-address&gt;127.0.0.1&lt;/bind-address&gt; --&gt;</p>
-          <p>&lt;/listen-socket&gt;</p>
-          <p>&nbsp;</p>
-          <p>&lt;fileserve&gt;1&lt;/fileserve&gt;</p>
-          <p>&nbsp;</p>
-          <p>&lt;security&gt;</p>
-          <p>&lt;chroot&gt;0&lt;/chroot&gt;</p>
-          <p>&lt;changeowner&gt;</p>
-          <p>&lt;user&gt;icecast2&lt;/user&gt;</p>
-          <p>&lt;group&gt;icecast&lt;/group&gt;</p>
-          <p>&lt;/changeowner&gt;</p>
-          <p>&lt;/security&gt;</p>
-        </div>
-        <p>Der Eintrag unter ChangeOwner bewirkt, daß der icecast2 nur mit
-            den Rechten eines normalen Users läuft und eben nicht mit
-            root-Rechten. Trotzdem kann er seine Logs nach /var/log
-            schreiben. – Eine komplette
-          <span class="strike">icecast.xml</span>
-            (die aber auch angepaßt werden muß) findet sich (leider nicht
-            mehr, 2011-02-01) im XBox360-HowTo.</p>
-        <p>Auch beim icecast2 gibt es eine kleine Stolperfalle: Die Rechte
-            der Dateien in <em class="unprop">/etc/icecast2/web/</em> müssen
-            auf 755 geändert werden, sonst bekommen Seitenbesucher einen
-            404.</p>
-        <hr />
-        <h2>Stream ab!</h2>
-        <p>… oder der kürzeste Computerwitz aller Zeiten: „Müßte
-            laufen“ …</p>
-        <p>Als erstes muß natürlich der icecast2 auf dem Server laufen. Er
-            wird – von root – gestartet mit</p>
-        <div class="console">
-          <p>$ icecast2 -c /etc/icecast2/icecast.xml -b</p></div>
-        <p>Das -b bewirkt, daß icecast2 in den Hintergrund geht und die
-            Konsole wieder freiräumt.</p><hr />
-        <h3>Stream-PC startklar machen</h3>
-        <p>Als erstes spreche ich hier nochmal die CPU-Leistung an. Ich
-            hatte beim PIII alles, was nicht direkt zum Streamen gehört (vor
-            allem XChat und Browser) kurzerhand aufs Notebook verlegt, denn
-            obwohl sie nicht direkt zum Streamen gehören, brauche ich sie
-            doch gleichzeitig. Der Grund für die Verlegung war, daß jeder
-            Fensterwechsel, jede Mausbewegung und auch schnelles Tippen im
-            Stream als Störungen zu hören sind, und das nervt auf Dauer doch
-            sehr. Auch ein zwischendurch eingesetzter Duron mit
-            850&nbsp;MHz hatte das Problem noch; erst ab dem Athlon mit 1533
-            MHz ist das Problem Geschichte.</p>
-        <p>Als erstes startet man audacious, aumix und darksnow und ordnet
-            die Fenster so an, daß man möglichst alles sehen kann (incl. 
-            Playliste). Den alsamixer braucht man nur anfangs, um
-            die Soundkarte, falls nötig, vorzukonfigurieren.</p>
-        <p>Als nächstes aumix richtig einstellen: Dabei nehme ich immer
-            erstmal alle Anzeigen raus, die ich nicht benötige; leider merkt
-            der sich das nicht (auch nicht durch save). Dann drehe ich PCM
-            bzw. Master auf 70 bis 80 und Mic auf 100&nbsp;% und regle die
-            Lautstärke (das ist die des eigenen Kopfhörers bzw. 
-            Lautsprechers) auf einen mir angenehmen Wert. Im alsamixer
-            schalte ich ggf. noch den Mic-Booster ein.  Vorsicht, wenn mit
-            Lautsprecherboxen statt Kopfhörer am Stream-PC gearbeitet wird! 
-            Den Booster dann nicht <em>zu</em> hoch drehen, sonst gibt es
-            eine Rückkopplung, und das pfeift ganz eklig :-)</p>
-            
-        <p>Ja, und schließlich im darksnow auf Start Streaming klicken.</p>
-        <p>Erste Kontrolle: Mit einem Browser auf die Webseite des Servers
-            gehen (http://radio.meinserver.de:8000). Dort sollte die
-            „status page“ des icecast2 zu finden sein. Wenn im
-            grauen Bereich die Angaben zu finden sind, die man vorher im
-            darksnow bei „Server Description“ eingetragen hat,
-            ist die Verbindung zum Server aufgebaut.</p>
-        <p>Das heißt aber noch nicht, daß aufgeschaltete Hörer etwas hören
-            können. Um etwas auf den Stream abzuspielen, muß im aumix bei
-            PCM (oder Master) der Rec-Knopf gedrückt (rot) sein. Wenn man
-            sprechen möchte, muß der Rec-Knopf vor Mic rot sein. Bei
-            manchen (nicht allen) Soundkarten geht auch beides gleichzeitig,
-            wobei es empfehlenswert ist, beim Abspielen von Musik das Mikro
-            auszuschalten (Rec auf grün) – vor allem, wenn man nicht
-            beim Mitsingen erwischt werden will&nbsp;;-)</p>
-
-[FLATTRBUTTON]
-        <p>Noch Fragen? Frag
-          <a href="mailto:frosch@atari-frosch.de">mich</a> doch!</p>
-      </div><!-- div#content -->
diff --git a/sites/atarifrosch/internet/stream-mit-linux.py b/sites/atarifrosch/internet/stream-mit-linux.py
deleted file mode 100755 (executable)
index 5eae347..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf8 -*-
-
-targetfile = "/internet/stream-mit-linux.html"
-title = "Internet-Radio streamen mit Linux HowTo"
-description = "Internet-Radio streamen mit Debian Linux HowTo"
-dctitle = "Internet-Radio streamen mit Debian GNU/Linux"
-dcsubject = dctitle
-
-headline = "Streamen mit Linux"
-
-contentfile = "stream-mit-linux.htm"
-myurl = proto + "://" + domain + "/" + targetfile
-
-replacement["[FLATTRTHING]"] = "457983"
-replacement["[FLATTRNAME]"] = "Internet-Radio-streamen-mit-Debian-GNULinux"