├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── mikrowelle.py ├── requirements.txt ├── settings.default.json ├── templates └── base-template │ ├── archive.tpl │ ├── head.tpl │ ├── index.tpl │ ├── meta_block.tpl │ ├── player.tpl │ ├── post.tpl │ ├── res │ └── pwp │ │ ├── css │ │ ├── pwp-blue-orange.css │ │ ├── pwp-blue-orange.min.css │ │ ├── pwp-creamy.css │ │ ├── pwp-creamy.min.css │ │ ├── pwp-dark-blaze.css │ │ ├── pwp-dark-blaze.min.css │ │ ├── pwp-dark-gray.css │ │ ├── pwp-dark-gray.min.css │ │ ├── pwp-dark-green.css │ │ ├── pwp-dark-green.min.css │ │ ├── pwp-dark.css │ │ ├── pwp-dark.min.css │ │ ├── pwp-jungle-green.css │ │ ├── pwp-jungle-green.min.css │ │ ├── pwp-light-gray.css │ │ ├── pwp-light-gray.min.css │ │ ├── pwp-light.css │ │ ├── pwp-light.min.css │ │ ├── pwp-midnightblue.css │ │ ├── pwp-midnightblue.min.css │ │ ├── pwp-silver-blaze.css │ │ ├── pwp-silver-blaze.min.css │ │ ├── pwp-silver.css │ │ ├── pwp-silver.min.css │ │ └── vendor │ │ │ ├── progress-polyfill.css │ │ │ └── style.css │ │ ├── examples │ │ ├── coverimage-blue.png │ │ ├── coverimage-green.png │ │ ├── coverimage-red.png │ │ ├── coverimage.png │ │ ├── cre-206 │ │ │ └── index.html │ │ ├── deeplinking │ │ │ └── index.html │ │ ├── examples.css │ │ ├── folder-30c3.png │ │ ├── index.html │ │ ├── injected │ │ │ └── index.html │ │ ├── minimal │ │ │ └── index.html │ │ ├── picture-stream │ │ │ ├── Kapitel-Demo.m4a │ │ │ └── index.html │ │ ├── themes │ │ │ ├── index.html │ │ │ └── themed.html │ │ ├── video │ │ │ └── index.html │ │ └── which-format │ │ │ ├── index.html │ │ │ ├── podlove-test-track.mp3 │ │ │ ├── podlove-test-track.mp4 │ │ │ ├── podlove-test-track.ogg │ │ │ └── podlove-test-track.opus │ │ ├── font │ │ ├── podlove.eot │ │ ├── podlove.svg │ │ ├── podlove.ttf │ │ └── podlove.woff │ │ ├── img │ │ ├── arrow-down-black.png │ │ ├── arrow-down-white.png │ │ ├── download-overlay.png │ │ └── icon-podlove-subscribe-600.png │ │ ├── index.html │ │ ├── js │ │ ├── podlove-web-moderator.js │ │ ├── podlove-web-moderator.min.js │ │ ├── podlove-web-player.js │ │ ├── podlove-web-player.min.js │ │ └── vendor │ │ │ ├── html5shiv-printshiv.js │ │ │ ├── html5shiv-printshiv.min.js │ │ │ ├── html5shiv.js │ │ │ ├── html5shiv.min.js │ │ │ ├── jquery.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.min.map │ │ │ ├── progress-polyfill.js │ │ │ ├── progress-polyfill.min.js │ │ │ ├── tests.js │ │ │ └── user-interaction.js │ │ └── static.html │ └── single.tpl ├── test ├── audio │ ├── 001.json │ ├── 001.m4a │ ├── 001.mp3 │ ├── 001.opus │ ├── 002.json │ ├── 002.m4a │ ├── 002.mp3 │ └── 002.opus └── test_workflow.py └── util ├── __init__.py ├── install.sh ├── mime_types.py ├── rssgen.py └── search.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | 37 | # Additional 38 | .DS_Store 39 | 40 | pub/ 41 | audio/ 42 | test/tmp/ 43 | posts/ 44 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.3" 5 | - "3.4" 6 | - "pypy" 7 | install: "pip install -r requirements.txt" 8 | script: py.test -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2013-2016, Thomas Skowron and others 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list 10 | of conditions and the following disclaimer. 11 | Redistributions in binary form must reproduce the above copyright notice, this 12 | list of conditions and the following disclaimer in the documentation and/or 13 | other materials provided with the distribution. 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mikrowelle OS [![Build Status](https://secure.travis-ci.org/thomersch/Mikrowelle-OS.png)](http://travis-ci.org/thomersch/Mikrowelle-OS) 2 | 3 | Mikrowelle OS is a static page generator for podcast websites and feeds. 4 | 5 | Tested on Python 2.7, 3.3, 3.4 and PyPy 2.5. Will not work under Python 2.6, please update in this case. If possible, prefer Python 3. 6 | 7 | ## Feature List 8 | 9 | * Generating podcast feeds 10 | * iTunes compatible 11 | * Payment tag (Flattr) 12 | * with TTL-support (reduces traffic by setting a sane default interval for feed-refreshing in podcast clients) 13 | * Full text search in the browser 14 | * Flattr support 15 | * New item for every episode, no manual generation needed. 16 | * Modern player 17 | * Podlove Web Player included 18 | * Chapter mark support 19 | * Auphonic support 20 | * Podlove Simple Chapters 21 | * Suitable for heavy load situations 22 | * no CGI/PHP/runtime bloat 23 | 24 | ## What does "static page generator" mean? 25 | 26 | You won't need a special webserver to serve the application. You can simply throw in all podcast data into this application and it will generate all necessary files. Those files can be uploaded to any hosting without any need for CGI, PHP or so. 27 | 28 | ## Is it working? 29 | 30 | Yep, we are using it actively in our podcast: [Mikrowelle](http://mikrowelle.me/). Though, there may be some issues. If you need assistance, feel free to contact me ([Twitter](http://twitter.com/thomersch)) or create an issue. 31 | 32 | ## Dependencies 33 | 34 | * Python 35 | * lxml (for feed generation) 36 | * jinja2 (templating engine) 37 | * markdown (easy markdown language) 38 | * JavaScript _(those are already included in the repository)_ 39 | * jQuery 40 | * Podlove Web Player 41 | 42 | ## Installation Instructions 43 | 44 | * Clone git repository. 45 | * `git clone https://github.com/thomersch/Mikrowelle-OS.git` 46 | * Install Python dependencies. 47 | * on Debian based systems: `sudo apt-get install python3-lxml` 48 | * `pip install -r requirements.txt` 49 | * Customize your podcast settings. 50 | * Rename `settings.default.json` to `settings.json` and change the values the way you need it. 51 | * For the best expierence, use Auphonic. For instructions see section *"Working with Auphonic"*. 52 | * Run `mikrowelle.py`. 53 | * Publish the `audio` folder and the `pub` folder on the interwebz. 54 | 55 | 56 | ## Working with [Auphonic](http://auphonic.com/) 57 | 58 | Auphonic is a fully automatic audio post-production service, that converts all your podcast data into well sounding audio files. 59 | 60 | This application is build for best use with Auphonic: All meta tags should be put into the webinterface of Auphonic. Description is automatically converted with markdown as well as the summary. Put into the "track" file the number of the podcast episode. 61 | 62 | As output files you should select all of the desired audio data types. Plus you must add the "Production description" as json file. 63 | 64 | You may as well add chapter marks, they will be automatically processed and put into the web player. 65 | 66 | The output of auphonic has to be put where the settings.json `filefolder` is configured. The generator will automatically pick up the right files and do the rest. 67 | 68 | ## Working without Auphonic 69 | 70 | You can run _Mikrowelle OS_ without Auphonic as well. In order to do that, you will need to create a json file per episode and put it into your `posts` folder. 71 | 72 | The file name doesn't really matter, but your episode order will depend on it. 73 | 74 | ### Example: Post file 75 | 76 | { 77 | "chapters": [ 78 | { 79 | "image": null, 80 | "start": "00:22:46.190", 81 | "title": "Chapter 1", 82 | "url": "http://example.com/1/" 83 | }, 84 | { 85 | "image": null, 86 | "start": "01:21:33.010", 87 | "title": "Chapter 2", 88 | "url": "http://example.com/2/" 89 | }, 90 | { 91 | "image": null, 92 | "start": "01:17:00.130", 93 | "title": "Chapter 3", 94 | "url": "http://example.com/3/" 95 | } 96 | ], 97 | "content": "

Summary

", 98 | "date": "2013-06-09T22:55:48.500Z", 99 | "duration": "01:35:29.914", 100 | "episode": "001", 101 | "filename": "001", 102 | "humandate": "09.06.2013", 103 | "subtitle": "

It is just the beginning.

", 104 | "title": "001 Title" 105 | } 106 | 107 | ## Templating 108 | ### Changing the looks of your podcast page. 109 | 110 | If you want to start a new style, I recommend to duplicate the `templates/base-template` folder and start editing in the duplicate. Remember to change the `tplfolder` path in `settings.json`. 111 | 112 | Adding a stylesheet is nice as well, give it a try. The directory `res` in the template path will be linked in the pub-path, so you can place all your assets in `$templatename/res` and those will be available at `res` on your main publishing path, e.g. `podcast.example.com/res`. 113 | 114 | ## Feature requests 115 | 116 | Give 'em to me. Create a GitHub issue or contact me. 117 | 118 | ## Other Questions? 119 | 120 | Ask me. 121 | 122 | ## License 123 | 124 | BSD License. No bullshit. See `LICENSE` file. 125 | 126 | ## Contributors 127 | 128 | * Thomas Skowron 129 | * Thomas Sänger (HorayNarea) 130 | * Andreas Hubel (saerdnaer) 131 | -------------------------------------------------------------------------------- /mikrowelle.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | __version__ = (2, 0, 0) 4 | __author__ = "Thomas Skowron" 5 | 6 | import util.rssgen as rssgen 7 | import util.search as search 8 | from util.mime_types import mimetypes 9 | 10 | import sys 11 | import os 12 | import json 13 | import shutil 14 | import math 15 | from datetime import datetime 16 | import distutils.dir_util as du 17 | 18 | import markdown 19 | from jinja2 import FileSystemLoader, Environment 20 | 21 | if sys.version_info < (3, 0, 0): 22 | from codecs import open 23 | 24 | POST_PATH = "posts" 25 | TMP_PATH = "tmp_output" 26 | 27 | def get_settings(): 28 | with open("settings.json", "r", encoding="utf-8") as f: 29 | settings = json.loads(f.read()) 30 | return settings 31 | 32 | 33 | def get_posts(): 34 | posts = [] 35 | if not os.path.exists(POST_PATH): 36 | print("[INFO] No posts found.") 37 | os.mkdir(POST_PATH) 38 | 39 | for filename in sorted(os.listdir(POST_PATH), reverse=True): 40 | with open(os.path.join(POST_PATH, filename), "r", encoding="utf-8") as f: 41 | # read data from json 42 | try: 43 | p = json.loads(f.read()) 44 | posts.append(p) 45 | except ValueError: 46 | print("[INFO] Ignored non-json file in posts-folder:", filename) 47 | return posts 48 | 49 | 50 | def write_post(post, settings, single_template, player_template): 51 | format_mimes = {} 52 | for fmt in settings["feeds"]: 53 | format_mimes[fmt] = mimetypes[fmt] 54 | 55 | # write individual page for post 56 | with open(os.path.join(TMP_PATH, "%s.html" % post["episode"]), 57 | "a+", encoding="utf-8") as w: 58 | w.write(single_template.render(post=post, settings=settings, formats=format_mimes, index_page=False)) 59 | 60 | # write player page 61 | with open(os.path.join(TMP_PATH, "player_%s.html" % post["episode"]), "a+", encoding="utf-8") as w: 62 | w.write(player_template.render(post=post, settings=settings, formats=format_mimes)) 63 | 64 | 65 | def _write_json_data(filefolder, fn): 66 | with open("{}{}".format(filefolder, fn), encoding="utf-8") as f: 67 | h = json.loads(f.read()) 68 | 69 | # get all the metadata! 70 | o = { 71 | "episode": h["metadata"]["track"], 72 | "title": h["metadata"]["title"], 73 | "content": markdown.markdown(h["metadata"]["summary"]), 74 | "subtitle": markdown.markdown(h["metadata"]["subtitle"]), 75 | "date": h["change_time"], 76 | #TODO: make date format string configurable 77 | "humandate": datetime.strptime(h["change_time"], "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%d.%m.%Y"), 78 | "humanduration": datetime.strptime(h["length_timestring"], "%H:%M:%S.%f").strftime("%H:%M"), 79 | "filename": h["output_basename"], 80 | "duration": h["length_timestring"], 81 | "chapters": h["chapters"] 82 | } 83 | j = json.dumps(o, sort_keys=True, indent=4, separators=(',', ': ')) 84 | 85 | # write converted file to post storage folder 86 | if not os.path.exists(POST_PATH): 87 | os.mkdir(POST_PATH) 88 | episode_file_name = os.path.join(POST_PATH, "%s" % format(fn)) 89 | with open(episode_file_name, "a+", encoding="utf-8") as e: 90 | e.write(j) 91 | 92 | 93 | def _get_json_file_list(filefolder): 94 | def filterFile(fn): 95 | if fn.endswith(".json") and not os.path.exists(os.path.join(POST_PATH, fn)): 96 | return True 97 | 98 | return [fn for fn in os.listdir(filefolder) if filterFile(fn)] 99 | 100 | 101 | def _get_elements(posts, settings, format): 102 | filefolder = settings["filefolder"] 103 | baseurl = settings["baseurl"] 104 | 105 | elements = [] 106 | for post in posts: 107 | filesize = os.path.getsize("{}{}.{}".format(filefolder, post["filename"], format)) 108 | mime = mimetypes[format] 109 | episode_link = "{}{}.html".format(baseurl, post["episode"]) 110 | guid = "{}{}.html.{}".format(baseurl, post["episode"], post["date"]) 111 | 112 | elements.append( 113 | { 114 | "title": post["title"], 115 | "link": episode_link, 116 | "description": post["content"], 117 | "guid": guid, 118 | "pubdate": datetime.strptime(post["date"], "%Y-%m-%dT%H:%M:%S.%fZ"), 119 | "enclosure": { 120 | "url": "{}{}.{}".format(settings["audio_base_url"], post["filename"], format), 121 | "length": filesize, 122 | "type": mime 123 | }, 124 | "chapters": post["chapters"] 125 | } 126 | ) 127 | 128 | return elements 129 | 130 | 131 | def _generate_index_pages(posts, settings, formats, index_template): 132 | format_mimes = {} 133 | for fmt in settings["feeds"]: 134 | format_mimes[fmt] = mimetypes[fmt] 135 | 136 | posts_on_page = settings.get("posts_on_page", None) 137 | cur_page = 0 138 | if posts_on_page is not None: 139 | while cur_page*posts_on_page < len(posts): 140 | page_posts = posts[posts_on_page*cur_page:posts_on_page*(cur_page+1)] 141 | if cur_page == 0: 142 | filename = os.path.join(TMP_PATH, "index.html") 143 | else: 144 | filename = os.path.join(TMP_PATH, "index.%i.html" % cur_page) 145 | 146 | with open(filename, "a+", encoding="utf-8") as f: 147 | if (cur_page + 1)*posts_on_page >= len(posts): 148 | next = None 149 | else: 150 | next = cur_page+1 151 | if cur_page > 0: 152 | prev = cur_page-1 153 | else: 154 | prev = None 155 | f.write(index_template.render(posts=page_posts, settings=settings, formats=format_mimes, index_page=True, prev=prev, next=next)) 156 | cur_page += 1 157 | 158 | else: 159 | # write index.html with all posts 160 | with open(os.path.join(TMP_PATH, "index.html"), "a+", encoding="utf-8") as f: 161 | f.write(index_template.render(posts=posts, settings=settings, formats=format_mimes, index_page=True)) 162 | 163 | def _generate_archive_page(posts, settings, formats, archive_template): 164 | format_mimes = {} 165 | for fmt in settings["feeds"]: 166 | format_mimes[fmt] = mimetypes[fmt] 167 | 168 | with open(os.path.join(TMP_PATH, "archive.html"), "a+", encoding="utf-8") as f: 169 | f.write(archive_template.render(posts=posts, settings=settings, formats=format_mimes)) 170 | 171 | def json_transform(settings): 172 | """ 173 | json_transform() transforms auphonic input files into post files 174 | that can be read by the generate() method 175 | """ 176 | 177 | filefolder = settings["filefolder"] 178 | 179 | if not os.path.exists(filefolder): 180 | print("[INFO] No media in %s found." % filefolder) 181 | os.mkdir(filefolder) 182 | 183 | for fn in _get_json_file_list(filefolder): 184 | _write_json_data(filefolder, fn) 185 | 186 | 187 | def generate(settings): 188 | # settings mapping 189 | tplfolder = settings["tplfolder"] 190 | publish = settings["publish"] 191 | formats = settings["feeds"] 192 | 193 | # create output folder 194 | if os.path.exists(TMP_PATH): 195 | shutil.rmtree(TMP_PATH) 196 | os.mkdir(TMP_PATH) 197 | 198 | # load template files 199 | jenv = Environment(loader=FileSystemLoader(tplfolder)) 200 | index_template = jenv.get_template("index.tpl") 201 | single_template = jenv.get_template("single.tpl") 202 | player_template = jenv.get_template("player.tpl") 203 | archive_template = jenv.get_template("archive.tpl") 204 | if os.path.exists(os.path.join(tplfolder, "style.css")): 205 | shutil.copy(os.path.join(tplfolder, "style.css"), os.path.join(TMP_PATH, "style.css")) 206 | 207 | # get posts from files 208 | posts = get_posts() 209 | 210 | # write posts with templates 211 | for post in posts: 212 | write_post(post, settings, single_template, player_template) 213 | 214 | _generate_index_pages(posts, settings, formats, index_template) 215 | _generate_archive_page(posts, settings, formats, archive_template) 216 | 217 | # generate feed_description 218 | for fmt in formats: 219 | elements = _get_elements(posts, settings, fmt) 220 | 221 | channel = { 222 | "title": settings["feed_title"].format(fmt), 223 | "link": settings["baseurl"], 224 | "feedinterval": settings["feedinterval"], 225 | "description": settings["feed_description"], 226 | "author": settings["author"] 227 | } 228 | 229 | if "artwork_url" in settings: 230 | channel["artwork"] = settings["artwork_url"] 231 | 232 | if "explicit" in settings: 233 | channel["explicit"] = settings["explicit"] 234 | 235 | with open(os.path.join(TMP_PATH, "{}.xml".format(fmt)), "wb") as f: 236 | f.write(rssgen.generate(channel=channel, elements=elements, settings=settings)) 237 | 238 | # build search 239 | search.build_index(posts, os.path.join(TMP_PATH, "episode_index.json")) 240 | 241 | # copy from temp to production and remove tmp 242 | du.copy_tree(TMP_PATH, publish) 243 | shutil.rmtree(TMP_PATH) 244 | 245 | # link resources to pub 246 | src = os.path.join(publish, "res") 247 | dst = os.path.join(tplfolder, "res") 248 | if not os.path.exists(src): 249 | os.symlink(os.path.abspath(dst), src) 250 | 251 | 252 | def run(): 253 | settings = get_settings() 254 | json_transform(settings) 255 | generate(settings) 256 | 257 | 258 | if __name__ == "__main__": 259 | if sys.version_info >= (2, 7, 0): 260 | print("Running Mikrowelle OS {}.{}.{}".format(__version__[0], __version__[1], __version__[2])) 261 | run() 262 | else: 263 | print("[ERROR] Your python interpreter version is too old. Required: 2.7") 264 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2>=2.6 2 | Markdown>=2.2.1 3 | lxml>=3.2.3 -------------------------------------------------------------------------------- /settings.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "tplfolder": "./templates/base-template/", 3 | "baseurl": "http://example.com/", 4 | "filefolder": "./audio/", 5 | "publish": "./pub/", 6 | "feeds": [ 7 | "mp3", 8 | "m4a", 9 | "opus" 10 | ], 11 | "feedinterval": "1440", 12 | "web_title": "Podcastname", 13 | "feed_title": "Podcastname ({} Feed)", 14 | "feed_description": "Feedbeschreibung/Podcastbeschreibung", 15 | "author": "Podcastautor", 16 | "artwork_url": "http://example.com/logo.png", 17 | "audio_base_url": "http://audio.example.com/", 18 | "flattrlink": "https://flattr.com/submit/auto?url={}&title={}&user_id=FLATTRNAME&language=de_DE&category=audio", 19 | "category": "Technology & Education", 20 | "language": "de-de", 21 | "posts_on_page": 5, 22 | "explicit": false 23 | } 24 | -------------------------------------------------------------------------------- /templates/base-template/archive.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ settings.web_title }} 6 | 7 | {% include 'head.tpl' %} 8 | 9 | 10 | 11 |
12 | {{ settings.web_title }} 13 |
14 | 15 |
16 | {% include 'meta_block.tpl' %} 17 | 18 | {% for post in posts %} 19 |
20 |

{{ post.title }}

21 | {{ post.subtitle }} 22 | Duration: {{ post.humanduration }} h 23 |
24 | Published on: {{ post.humandate }}, 25 | Direct Episode Link 26 | Download: 27 | {% for extension, mime in formats.items() %} 28 | {{ extension }} 29 | {% endfor %} 30 |
31 |
32 | {% endfor %} 33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /templates/base-template/head.tpl: -------------------------------------------------------------------------------- 1 | {% for feed in feeds %} 2 | {% endfor %} 3 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /templates/base-template/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ settings.web_title }} 6 | 7 | {% include 'head.tpl' %} 8 | 9 | 10 | 11 |
12 | {{ settings.web_title }} 13 |
14 | 15 |
16 | {% include 'meta_block.tpl' %} 17 | 18 | {% for post in posts %} 19 | {% include 'post.tpl' %} 20 | {% endfor %} 21 | 22 | {% if prev == 0 %} 23 |
24 | newer episodes 25 |
26 | {% elif prev and prev > 0 %} 27 |
28 | newer episodes 29 |
30 | {% endif %} 31 | {% if next %} 32 |
33 | older episodes 34 |
35 | {% endif %} 36 |
37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /templates/base-template/meta_block.tpl: -------------------------------------------------------------------------------- 1 |
2 |

Feeds: {% for feed in settings.feeds %}{{ feed }} | {% endfor %}Bitlove

3 |

All episodes: Archive

4 |

Powered by Mikrowelle OS

5 |
6 | -------------------------------------------------------------------------------- /templates/base-template/player.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 28 | 29 | -------------------------------------------------------------------------------- /templates/base-template/post.tpl: -------------------------------------------------------------------------------- 1 |
2 |

{{ post.title }}

3 | 4 | 9 | 10 | {{ post.content }} 11 | 12 |
13 | Published on: {{ post.humandate }}, 14 | Direct Episode Link 15 | Download: 16 | {% for extension, mime in formats.items() %} 17 | {{ extension }} 18 | {% endfor %} 19 |
20 |
-------------------------------------------------------------------------------- /templates/base-template/res/pwp/css/vendor/progress-polyfill.css: -------------------------------------------------------------------------------- 1 | progress[role] { 2 | display: inline-block; 3 | position: relative; 4 | width: 10em; 5 | height: 1em; 6 | vertical-align: -.2em; 7 | background-image: url('data:image/gif;base64,R0lGODlhIAAQAIAAAP///////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJBwABACwAAAAAIAAQAAACLISPF8vtkWJ8lMlrasVXb554FBiKDomYJ5qpFgu4LysvcFzfNQTvet4D0hgFACH5BAkHAAEALAAAAAAgABAAAAIshH+hyx0Io3F0yTsrxVdvHnkOGIoMCZknmqgWC7gvKytwXN/1A+963gPSKAUAIfkECQcAAQAsAAAAACAAEAAAAi2EHanLcQ9hmyraR+ndee7bNZ8VMmNULqeUJivWOi8Sz3RrA7E77/LrswV7oQIAIfkECQcAAQAsAAAAACAAEAAAAixEjqkB7Q/bmijaR+ndee7bLZ8VKmNUJieUVqvTHi8cz1Jtx0yOz7pt6L10BQAh+QQJBwABACwAAAAAIAAQAAACLIyPB8vtkGJ8lMlrasVXb554FBiKDomYJ5qpFhu4LysvcFzfNQTvet4D0hgFACH5BAkHAAEALAAAAAAgABAAAAIsjH+gyw0Io3F0yTsrxVdvHnkOGIoMCZknmqgWG7gvKytwXN/1A+963gPSKAUAIfkECQcAAQAsAAAAACAAEAAAAi2MDanLcA9hmyraR+ndee7bNZ8VMmNULqeUJivWOi8Sz3RrB7E77/LrswV7oQIAIfkEAQcAAQAsAAAAACAAEAAAAiwMjqkQ7Q/bmijaR+ndee7bLZ8VKmNUJieUVqvTHi8cz1Jtx0yOz7pt6L10BQA7'); 8 | 9 | -moz-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | progress[role], 14 | progress[aria-valuenow]:before { 15 | background-color: #5af; 16 | } 17 | 18 | progress[role], 19 | progress[role]:after { 20 | background-repeat:repeat-x; 21 | background-position: 0 0; 22 | -moz-background-size: auto 100%; 23 | -webkit-background-size: auto 100%; 24 | background-size: auto 100%; 25 | } 26 | 27 | /* Determinate only overrides */ 28 | progress[aria-valuenow] { 29 | background: #eee; 30 | } 31 | 32 | progress[aria-valuenow]:before { 33 | content: ""; 34 | display: block; 35 | height: 100%; 36 | } 37 | 38 | /* Overlay */ 39 | progress[role]:after { 40 | content: ""; 41 | position: absolute; 42 | top: 0; 43 | right: 0; 44 | bottom: 0; 45 | left: 0; 46 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQBAMAAAAlsQiEAAAABGdBTUEAALGPC/xhBQAAAC1QTFRF////////gYGA+/v7////3NzcQUFCkZGQWFlZAAAAAAAA////WFhY////r6+w5vktvgAAAA90Uk5TZB4sW3ZODgMEJgBVHDY+cmAeZAAAACZJREFUeNpjmMBQwHCBAQQMGAIYHjAoMBxgSGBoYFjAIMCwgcEBAGgwBpG64ZoMAAAAAElFTkSuQmCC'); 47 | } 48 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/css/vendor/style.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Sniglet:800&v2); 2 | 3 | body { 4 | max-width: 800px; 5 | margin: 10px auto; 6 | font:16px/1.4 sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | h1, h2, h3 { 15 | font-family: 'Sniglet', sans-serif; 16 | } 17 | 18 | h1 { 19 | font-size: 340%; 20 | margin-bottom: 0; 21 | } 22 | 23 | h2 { 24 | font-size: 240%; 25 | color: deeppink; 26 | margin: 1em 0 0; 27 | } 28 | 29 | h1+h2 { 30 | margin-top: 0; 31 | color: gray; 32 | } 33 | 34 | hgroup { 35 | text-align: center; 36 | } 37 | 38 | h3 { 39 | font-size: 150%; 40 | color: gray; 41 | } 42 | 43 | ul { 44 | margin: 0; 45 | padding-left:0; 46 | } 47 | 48 | h2+p, h3+p { 49 | margin-top: 0; 50 | } 51 | 52 | /* Unit tests styling */ 53 | .unit-tests { 54 | padding: 0; 55 | margin: 0; 56 | } 57 | 58 | .unit-tests > li { 59 | margin: 5px 0; 60 | padding: 5px 10px; 61 | list-style: none; 62 | color: white; 63 | text-shadow: 1px 1px 2px rgba(0,0,0,.4); 64 | } 65 | 66 | .unit-tests > li.pass { 67 | background: green; 68 | } 69 | 70 | .unit-tests > li.fail { 71 | background: red; 72 | } -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/coverimage-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/coverimage-blue.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/coverimage-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/coverimage-green.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/coverimage-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/coverimage-red.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/coverimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/coverimage.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/cre-206/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CRE 206 - media is loaded from source server 8 | 9 | 10 | 11 | 12 | 13 |
14 | 24 |
25 | 26 | 27 | 28 | 29 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/deeplinking/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Audio Tag Decoration Test Page 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Start Player at position 00:01.000

22 | 23 |
24 | 30 |
31 |
32 |
33 |

Start Player at position 00:01.000 and stop at 00:02.000

34 | 35 |
36 | 42 |
43 |
44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/examples.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #ffffff; 3 | font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', sans-serif; 4 | } 5 | 6 | /* player */ 7 | 8 | .podlove-player-wrapper { 9 | overflow: auto; 10 | -webkit-overflow-scrolling: touch; 11 | } 12 | 13 | .podlove-player-wrapper iframe { 14 | width: 1px; 15 | min-width: 100%; 16 | } 17 | 18 | h1 { 19 | color: #0E116C; 20 | font-size: 29px; 21 | width: 85%; 22 | } 23 | 24 | a { 25 | text-decoration: none; 26 | } 27 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/folder-30c3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/folder-30c3.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Audio Tag Decoration Test Page 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

1st embedded player

27 | 28 |
29 | 35 |
36 |
37 |
38 |

2nd embedded player

39 | 40 |
41 | 48 |
49 |
50 | 51 | 52 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/injected/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Inject data test page 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

Injected Data

23 |

Media and Metadata are injected into the iframe

24 |
25 | 31 |
32 | 138 |
139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/minimal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | MINIMAL 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

Minimal Example

23 |

The absolute minimal data set is handed over

24 |
25 | 31 |
32 | 91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/picture-stream/Kapitel-Demo.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/picture-stream/Kapitel-Demo.m4a -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/picture-stream/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Picture Stream 8 | 9 | 10 | 11 | 12 | 13 |
14 | 21 |
22 | 23 | 24 | 25 | 26 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/themes/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Audio Tag Decoration Test Page 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

Light

27 | 28 |
29 |
30 |
31 |
32 | 33 |
34 |

Light Gray

35 | 36 |
37 |
38 |
39 |
40 | 41 |
42 |

Silver

43 | 44 |
45 |
46 |
47 |
48 | 49 |
50 |

Silver Blaze

51 | 52 |
53 |
54 |
55 |
56 | 57 |
58 |

Creamy

59 | 60 |
61 |
62 |
63 |
64 | 65 |
66 |

Dark

67 | 68 |
69 |
70 |
71 |
72 | 73 |
74 |

Dark Green

75 | 76 |
77 |
78 |
79 | 80 |
81 |

Dark Blaze

82 | 83 |
84 |
85 |
86 | 87 |
88 |

Dark Gray

89 | 90 |
91 |
92 |
93 | 94 |
95 |

Blue Orange

96 | 97 |
98 |
99 |
100 | 101 |
102 |

Midnightblue

103 | 104 |
105 |
106 |
107 | 108 |
109 |

Jungle Green

110 | 111 |
112 |
113 |
114 |
115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/themes/themed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Silver Blaze Theme Test Page 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 30 |
31 | 32 | 33 | 34 | 35 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/video/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Video 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Video Test Page

15 |
16 | 25 |
26 | 27 | 28 | 29 | 30 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/which-format/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Which format plays? 8 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | 25 | 26 | 27 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/which-format/podlove-test-track.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/which-format/podlove-test-track.mp3 -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/which-format/podlove-test-track.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/which-format/podlove-test-track.mp4 -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/which-format/podlove-test-track.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/which-format/podlove-test-track.ogg -------------------------------------------------------------------------------- /templates/base-template/res/pwp/examples/which-format/podlove-test-track.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/examples/which-format/podlove-test-track.opus -------------------------------------------------------------------------------- /templates/base-template/res/pwp/font/podlove.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/font/podlove.eot -------------------------------------------------------------------------------- /templates/base-template/res/pwp/font/podlove.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/font/podlove.ttf -------------------------------------------------------------------------------- /templates/base-template/res/pwp/font/podlove.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/font/podlove.woff -------------------------------------------------------------------------------- /templates/base-template/res/pwp/img/arrow-down-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/img/arrow-down-black.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/img/arrow-down-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/img/arrow-down-white.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/img/download-overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/img/download-overlay.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/img/icon-podlove-subscribe-600.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomersch/Mikrowelle-OS/b68617c005f22dce49624336928ad1619635da7a/templates/base-template/res/pwp/img/icon-podlove-subscribe-600.png -------------------------------------------------------------------------------- /templates/base-template/res/pwp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Podlove Web Player Documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

Podlove Webplayer

27 |
28 | 43 |
44 |

This is an embedded player

45 | 46 |
47 | 53 |
54 |
55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /templates/base-template/res/pwp/js/podlove-web-moderator.min.js: -------------------------------------------------------------------------------- 1 | !function e(t,n,r){function o(a,u){if(!n[a]){if(!t[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);throw new Error("Cannot find module '"+a+"'")}var f=n[a]={exports:{}};t[a][0].call(f.exports,function(e){var n=t[a][1][e];return o(n?n:e)},f,f.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;au;u++)a[u]=o.isBuffer(e)?e.readUInt8(u):e[u];else if("string"===r)a.write(e,0,t);else if("number"===r&&!o._useTypedArrays&&!n)for(u=0;i>u;u++)a[u]=0;return a}function i(e,t,n,r){n=Number(n)||0;var i=e.length-n;r?(r=Number(r),r>i&&(r=i)):r=i;var a=t.length;R(a%2===0,"Invalid hex string"),r>a/2&&(r=a/2);for(var u=0;r>u;u++){var s=parseInt(t.substr(2*u,2),16);R(!isNaN(s),"Invalid hex string"),e[n+u]=s}return o._charsWritten=2*u,u}function a(e,t,n,r){var i=o._charsWritten=W(F(t),e,n,r);return i}function u(e,t,n,r){var i=o._charsWritten=W(j(t),e,n,r);return i}function s(e,t,n,r){return u(e,t,n,r)}function f(e,t,n,r){var i=o._charsWritten=W(O(t),e,n,r);return i}function l(e,t,n,r){var i=o._charsWritten=W(D(t),e,n,r);return i}function d(e,t,n){return 0===t&&n===e.length?X.fromByteArray(e):X.fromByteArray(e.slice(t,n))}function c(e,t,n){var r="",o="";n=Math.min(e.length,n);for(var i=t;n>i;i++)e[i]<=127?(r+=P(o)+String.fromCharCode(e[i]),o=""):o+="%"+e[i].toString(16);return r+P(o)}function h(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;n>o;o++)r+=String.fromCharCode(e[o]);return r}function g(e,t,n){return h(e,t,n)}function p(e,t,n){var r=e.length;(!t||0>t)&&(t=0),(!n||0>n||n>r)&&(n=r);for(var o="",i=t;n>i;i++)o+=N(e[i]);return o}function w(e,t,n){for(var r=e.slice(t,n),o="",i=0;i=o)){var i;return n?(i=e[t],o>t+1&&(i|=e[t+1]<<8)):(i=e[t]<<8,o>t+1&&(i|=e[t+1])),i}}function m(e,t,n,r){r||(R("boolean"==typeof n,"missing or invalid endian"),R(void 0!==t&&null!==t,"missing offset"),R(t+3=o)){var i;return n?(o>t+2&&(i=e[t+2]<<16),o>t+1&&(i|=e[t+1]<<8),i|=e[t],o>t+3&&(i+=e[t+3]<<24>>>0)):(o>t+1&&(i=e[t+1]<<16),o>t+2&&(i|=e[t+2]<<8),o>t+3&&(i|=e[t+3]),i+=e[t]<<24>>>0),i}}function b(e,t,n,r){r||(R("boolean"==typeof n,"missing or invalid endian"),R(void 0!==t&&null!==t,"missing offset"),R(t+1=o)){var i=y(e,t,n,!0),a=32768&i;return a?-1*(65535-i+1):i}}function v(e,t,n,r){r||(R("boolean"==typeof n,"missing or invalid endian"),R(void 0!==t&&null!==t,"missing offset"),R(t+3=o)){var i=m(e,t,n,!0),a=2147483648&i;return a?-1*(4294967295-i+1):i}}function E(e,t,n,r){return r||(R("boolean"==typeof n,"missing or invalid endian"),R(t+3=i))for(var a=0,u=Math.min(i-n,2);u>a;a++)e[n+a]=(t&255<<8*(r?a:1-a))>>>8*(r?a:1-a)}function B(e,t,n,r,o){o||(R(void 0!==t&&null!==t,"missing value"),R("boolean"==typeof r,"missing or invalid endian"),R(void 0!==n&&null!==n,"missing offset"),R(n+3=i))for(var a=0,u=Math.min(i-n,4);u>a;a++)e[n+a]=t>>>8*(r?a:3-a)&255}function _(e,t,n,r,o){o||(R(void 0!==t&&null!==t,"missing value"),R("boolean"==typeof r,"missing or invalid endian"),R(void 0!==n&&null!==n,"missing offset"),R(n+1=i||(t>=0?A(e,t,n,r,o):A(e,65535+t+1,n,r,o))}function L(e,t,n,r,o){o||(R(void 0!==t&&null!==t,"missing value"),R("boolean"==typeof r,"missing or invalid endian"),R(void 0!==n&&null!==n,"missing offset"),R(n+3=i||(t>=0?B(e,t,n,r,o):B(e,4294967295+t+1,n,r,o))}function M(e,t,n,r,o){o||(R(void 0!==t&&null!==t,"missing value"),R("boolean"==typeof r,"missing or invalid endian"),R(void 0!==n&&null!==n,"missing offset"),R(n+3=i||Y.write(e,t,n,r,23,4)}function U(e,t,n,r,o){o||(R(void 0!==t&&null!==t,"missing value"),R("boolean"==typeof r,"missing or invalid endian"),R(void 0!==n&&null!==n,"missing offset"),R(n+7=i||Y.write(e,t,n,r,52,8)}function C(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function S(e,t,n){return"number"!=typeof e?n:(e=~~e,e>=t?t:e>=0?e:(e+=t,e>=0?e:0))}function k(e){return e=~~Math.ceil(+e),0>e?0:e}function x(e){return(Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)})(e)}function T(e){return x(e)||o.isBuffer(e)||e&&"object"==typeof e&&"number"==typeof e.length}function N(e){return 16>e?"0"+e.toString(16):e.toString(16)}function F(e){for(var t=[],n=0;n=r)t.push(e.charCodeAt(n));else{var o=n;r>=55296&&57343>=r&&n++;for(var i=encodeURIComponent(e.slice(o,n+1)).substr(1).split("%"),a=0;a>8,r=t%256,o.push(r),o.push(n);return o}function O(e){return X.toByteArray(e)}function W(e,t,n,r){for(var o=0;r>o&&!(o+n>=t.length||o>=e.length);o++)t[o+n]=e[o];return o}function P(e){try{return decodeURIComponent(e)}catch(t){return String.fromCharCode(65533)}}function q(e,t){R("number"==typeof e,"cannot write a non-number as a number"),R(e>=0,"specified a negative value for writing an unsigned value"),R(t>=e,"value is larger than maximum value for type"),R(Math.floor(e)===e,"value has a fractional component")}function z(e,t,n){R("number"==typeof e,"cannot write a non-number as a number"),R(t>=e,"value larger than maximum allowed value"),R(e>=n,"value smaller than minimum allowed value"),R(Math.floor(e)===e,"value has a fractional component")}function J(e,t,n){R("number"==typeof e,"cannot write a non-number as a number"),R(t>=e,"value larger than maximum allowed value"),R(e>=n,"value smaller than minimum allowed value")}function R(e,t){if(!e)throw new Error(t||"Failed assertion")}var X=e("base64-js"),Y=e("ieee754");n.Buffer=o,n.SlowBuffer=o,n.INSPECT_MAX_BYTES=50,o.poolSize=8192,o._useTypedArrays=function(){try{var e=new ArrayBuffer(0),t=new Uint8Array(e);return t.foo=function(){return 42},42===t.foo()&&"function"==typeof t.subarray}catch(n){return!1}}(),o.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"raw":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},o.isBuffer=function(e){return!(null===e||void 0===e||!e._isBuffer)},o.byteLength=function(e,t){var n;switch(e+="",t||"utf8"){case"hex":n=e.length/2;break;case"utf8":case"utf-8":n=F(e).length;break;case"ascii":case"binary":case"raw":n=e.length;break;case"base64":n=O(e).length;break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":n=2*e.length;break;default:throw new Error("Unknown encoding")}return n},o.concat=function(e,t){if(R(x(e),"Usage: Buffer.concat(list, [totalLength])\nlist should be an Array."),0===e.length)return new o(0);if(1===e.length)return e[0];var n;if("number"!=typeof t)for(t=0,n=0;nd&&(n=d)):n=d,r=String(r||"utf8").toLowerCase();var c;switch(r){case"hex":c=i(this,e,t,n);break;case"utf8":case"utf-8":c=a(this,e,t,n);break;case"ascii":c=u(this,e,t,n);break;case"binary":c=s(this,e,t,n);break;case"base64":c=f(this,e,t,n);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":c=l(this,e,t,n);break;default:throw new Error("Unknown encoding")}return c},o.prototype.toString=function(e,t,n){var r=this;if(e=String(e||"utf8").toLowerCase(),t=Number(t)||0,n=void 0!==n?Number(n):n=r.length,n===t)return"";var o;switch(e){case"hex":o=p(r,t,n);break;case"utf8":case"utf-8":o=c(r,t,n);break;case"ascii":o=h(r,t,n);break;case"binary":o=g(r,t,n);break;case"base64":o=d(r,t,n);break;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":o=w(r,t,n);break;default:throw new Error("Unknown encoding")}return o},o.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}},o.prototype.copy=function(e,t,n,r){var i=this;if(n||(n=0),r||0===r||(r=this.length),t||(t=0),r!==n&&0!==e.length&&0!==i.length){R(r>=n,"sourceEnd < sourceStart"),R(t>=0&&t=0&&n=0&&r<=i.length,"sourceEnd out of bounds"),r>this.length&&(r=this.length),e.length-ta||!o._useTypedArrays)for(var u=0;a>u;u++)e[u+t]=this[u+n];else e._set(this.subarray(n,n+a),t)}},o.prototype.slice=function(e,t){var n=this.length;if(e=S(e,n,0),t=S(t,n,n),o._useTypedArrays)return o._augment(this.subarray(e,t));for(var r=t-e,i=new o(r,void 0,!0),a=0;r>a;a++)i[a]=this[a+e];return i},o.prototype.get=function(e){return console.log(".get() is deprecated. Access using array indexes instead."),this.readUInt8(e)},o.prototype.set=function(e,t){return console.log(".set() is deprecated. Access using array indexes instead."),this.writeUInt8(e,t)},o.prototype.readUInt8=function(e,t){return t||(R(void 0!==e&&null!==e,"missing offset"),R(e=this.length?void 0:this[e]},o.prototype.readUInt16LE=function(e,t){return y(this,e,!0,t)},o.prototype.readUInt16BE=function(e,t){return y(this,e,!1,t)},o.prototype.readUInt32LE=function(e,t){return m(this,e,!0,t)},o.prototype.readUInt32BE=function(e,t){return m(this,e,!1,t)},o.prototype.readInt8=function(e,t){if(t||(R(void 0!==e&&null!==e,"missing offset"),R(e=this.length)){var n=128&this[e];return n?-1*(255-this[e]+1):this[e]}},o.prototype.readInt16LE=function(e,t){return b(this,e,!0,t)},o.prototype.readInt16BE=function(e,t){return b(this,e,!1,t)},o.prototype.readInt32LE=function(e,t){return v(this,e,!0,t)},o.prototype.readInt32BE=function(e,t){return v(this,e,!1,t)},o.prototype.readFloatLE=function(e,t){return E(this,e,!0,t)},o.prototype.readFloatBE=function(e,t){return E(this,e,!1,t)},o.prototype.readDoubleLE=function(e,t){return I(this,e,!0,t)},o.prototype.readDoubleBE=function(e,t){return I(this,e,!1,t)},o.prototype.writeUInt8=function(e,t,n){n||(R(void 0!==e&&null!==e,"missing value"),R(void 0!==t&&null!==t,"missing offset"),R(t=this.length||(this[t]=e)},o.prototype.writeUInt16LE=function(e,t,n){A(this,e,t,!0,n)},o.prototype.writeUInt16BE=function(e,t,n){A(this,e,t,!1,n)},o.prototype.writeUInt32LE=function(e,t,n){B(this,e,t,!0,n)},o.prototype.writeUInt32BE=function(e,t,n){B(this,e,t,!1,n)},o.prototype.writeInt8=function(e,t,n){n||(R(void 0!==e&&null!==e,"missing value"),R(void 0!==t&&null!==t,"missing offset"),R(t=this.length||(e>=0?this.writeUInt8(e,t,n):this.writeUInt8(255+e+1,t,n))},o.prototype.writeInt16LE=function(e,t,n){_(this,e,t,!0,n)},o.prototype.writeInt16BE=function(e,t,n){_(this,e,t,!1,n)},o.prototype.writeInt32LE=function(e,t,n){L(this,e,t,!0,n)},o.prototype.writeInt32BE=function(e,t,n){L(this,e,t,!1,n)},o.prototype.writeFloatLE=function(e,t,n){M(this,e,t,!0,n)},o.prototype.writeFloatBE=function(e,t,n){M(this,e,t,!1,n)},o.prototype.writeDoubleLE=function(e,t,n){U(this,e,t,!0,n)},o.prototype.writeDoubleBE=function(e,t,n){U(this,e,t,!1,n)},o.prototype.fill=function(e,t,n){if(e||(e=0),t||(t=0),n||(n=this.length),"string"==typeof e&&(e=e.charCodeAt(0)),R("number"==typeof e&&!isNaN(e),"value is not a number"),R(n>=t,"end < start"),n!==t&&0!==this.length){R(t>=0&&t=0&&n<=this.length,"end out of bounds");for(var r=t;n>r;r++)this[r]=e}},o.prototype.inspect=function(){for(var e=[],t=this.length,r=0;t>r;r++)if(e[r]=N(this[r]),r===n.INSPECT_MAX_BYTES){e[r+1]="...";break}return""},o.prototype.toArrayBuffer=function(){if("undefined"!=typeof Uint8Array){if(o._useTypedArrays)return new o(this).buffer;for(var e=new Uint8Array(this.length),t=0,n=e.length;n>t;t+=1)e[t]=this[t];return e.buffer}throw new Error("Buffer.toArrayBuffer not supported in this browser")};var Q=o.prototype;o._augment=function(e){return e._isBuffer=!0,e._get=e.get,e._set=e.set,e.get=Q.get,e.set=Q.set,e.write=Q.write,e.toString=Q.toString,e.toLocaleString=Q.toString,e.toJSON=Q.toJSON,e.copy=Q.copy,e.slice=Q.slice,e.readUInt8=Q.readUInt8,e.readUInt16LE=Q.readUInt16LE,e.readUInt16BE=Q.readUInt16BE,e.readUInt32LE=Q.readUInt32LE,e.readUInt32BE=Q.readUInt32BE,e.readInt8=Q.readInt8,e.readInt16LE=Q.readInt16LE,e.readInt16BE=Q.readInt16BE,e.readInt32LE=Q.readInt32LE,e.readInt32BE=Q.readInt32BE,e.readFloatLE=Q.readFloatLE,e.readFloatBE=Q.readFloatBE,e.readDoubleLE=Q.readDoubleLE,e.readDoubleBE=Q.readDoubleBE,e.writeUInt8=Q.writeUInt8,e.writeUInt16LE=Q.writeUInt16LE,e.writeUInt16BE=Q.writeUInt16BE,e.writeUInt32LE=Q.writeUInt32LE,e.writeUInt32BE=Q.writeUInt32BE,e.writeInt8=Q.writeInt8,e.writeInt16LE=Q.writeInt16LE,e.writeInt16BE=Q.writeInt16BE,e.writeInt32LE=Q.writeInt32LE,e.writeInt32BE=Q.writeInt32BE,e.writeFloatLE=Q.writeFloatLE,e.writeFloatBE=Q.writeFloatBE,e.writeDoubleLE=Q.writeDoubleLE,e.writeDoubleBE=Q.writeDoubleBE,e.fill=Q.fill,e.inspect=Q.inspect,e.toArrayBuffer=Q.toArrayBuffer,e}}).call(this,e("oMfpAn"),"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer/index.js","/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer")},{"base64-js":2,buffer:1,ieee754:3,oMfpAn:4}],2:[function(e,t,n){(function(){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";!function(t){"use strict";function n(e){var t=e.charCodeAt(0);return t===a||t===d?62:t===u||t===c?63:s>t?-1:s+10>t?t-s+26+26:l+26>t?t-l:f+26>t?t-f+26:void 0}function r(e){function t(e){f[d++]=e}var r,o,a,u,s,f;if(e.length%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var l=e.length;s="="===e.charAt(l-2)?2:"="===e.charAt(l-1)?1:0,f=new i(3*e.length/4-s),a=s>0?e.length-4:e.length;var d=0;for(r=0,o=0;a>r;r+=4,o+=3)u=n(e.charAt(r))<<18|n(e.charAt(r+1))<<12|n(e.charAt(r+2))<<6|n(e.charAt(r+3)),t((16711680&u)>>16),t((65280&u)>>8),t(255&u);return 2===s?(u=n(e.charAt(r))<<2|n(e.charAt(r+1))>>4,t(255&u)):1===s&&(u=n(e.charAt(r))<<10|n(e.charAt(r+1))<<4|n(e.charAt(r+2))>>2,t(u>>8&255),t(255&u)),f}function o(t){function n(t){return e.charAt(t)}function r(e){return n(e>>18&63)+n(e>>12&63)+n(e>>6&63)+n(63&e)}var o,i,a,u=t.length%3,s="";for(o=0,a=t.length-u;a>o;o+=3)i=(t[o]<<16)+(t[o+1]<<8)+t[o+2],s+=r(i);switch(u){case 1:i=t[t.length-1],s+=n(i>>2),s+=n(i<<4&63),s+="==";break;case 2:i=(t[t.length-2]<<8)+t[t.length-1],s+=n(i>>10),s+=n(i>>4&63),s+=n(i<<2&63),s+="="}return s}var i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="+".charCodeAt(0),u="/".charCodeAt(0),s="0".charCodeAt(0),f="a".charCodeAt(0),l="A".charCodeAt(0),d="-".charCodeAt(0),c="_".charCodeAt(0);t.toByteArray=r,t.fromByteArray=o}("undefined"==typeof n?this.base64js={}:n)}).call(this,e("oMfpAn"),"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer/node_modules/base64-js/lib/b64.js","/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer/node_modules/base64-js/lib")},{buffer:1,oMfpAn:4}],3:[function(e,t,n){(function(){n.read=function(e,t,n,r,o){var i,a,u=8*o-r-1,s=(1<>1,l=-7,d=n?o-1:0,c=n?-1:1,h=e[t+d];for(d+=c,i=h&(1<<-l)-1,h>>=-l,l+=u;l>0;i=256*i+e[t+d],d+=c,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+d],d+=c,l-=8);if(0===i)i=1-f;else{if(i===s)return a?0/0:1/0*(h?-1:1);a+=Math.pow(2,r),i-=f}return(h?-1:1)*a*Math.pow(2,i-r)},n.write=function(e,t,n,r,o,i){var a,u,s,f=8*i-o-1,l=(1<>1,c=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:i-1,g=r?1:-1,p=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||1/0===t?(u=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(s=Math.pow(2,-a))<1&&(a--,s*=2),t+=a+d>=1?c/s:c*Math.pow(2,1-d),t*s>=2&&(a++,s/=2),a+d>=l?(u=0,a=l):a+d>=1?(u=(t*s-1)*Math.pow(2,o),a+=d):(u=t*Math.pow(2,d-1)*Math.pow(2,o),a=0));o>=8;e[n+h]=255&u,h+=g,u/=256,o-=8);for(a=a<0;e[n+h]=255&a,h+=g,a/=256,f-=8);e[n+h-g]|=128*p}}).call(this,e("oMfpAn"),"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer/node_modules/ieee754/index.js","/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/buffer/node_modules/ieee754")},{buffer:1,oMfpAn:4}],4:[function(e,t){(function(e){function n(){}var e=t.exports={};e.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var n=[];return window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(e){n.push(e),window.postMessage("process-tick","*")}}return function(e){setTimeout(e,0)}}(),e.title="browser",e.browser=!0,e.env={},e.argv=[],e.on=n,e.addListener=n,e.once=n,e.off=n,e.removeListener=n,e.removeAllListeners=n,e.emit=n,e.binding=function(){throw new Error("process.binding is not supported")},e.cwd=function(){return"/"},e.chdir=function(){throw new Error("process.chdir is not supported")}}).call(this,e("oMfpAn"),"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/process/browser.js","/../../node_modules/gulp-browserify/node_modules/browserify/node_modules/process")},{buffer:1,oMfpAn:4}],5:[function(e){(function(){"use strict";function t(e,t,n){return t>e||e>n}function n(e){return!e||isNaN(e)?(console.warn("Set frame height to default"),h):(t(e,g,p)||console.warn("Frame height",e,"out of bounds."),d(e,g,p))}function r(){return"100%"}function o(e){var t=e.href,n=t.indexOf("#"),r=t.length;return n>=0&&(r=n),t.substring(0,r)}function i(e){if(!f.staticEmbedPage)throw new Error('"staticEmbedPage" parameter missing.');return f.staticEmbedPage+"?"+e}function a(){var e,t,o,a=c(this),u=a.data("podlove-web-player-source");if(!u){var s=a.get(0).id;if(!s)throw new Error("Element without source set needs an ID");if(u=i(s),o=window[m][s],!o)throw new Error('No data found for "'+s+'"')}return y&&b[0]&&(y=!1,u+="#t="+l.getFragment("t")),e=c("