From 779991754aedbc26b71d1410d258e44bf754ac23 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 25 Nov 2014 19:55:20 -0500 Subject: Add screenshot gallery to main page. --- content/images/screenshots/calf_equalizer.jpg | Bin 0 -> 122074 bytes content/images/screenshots/calf_monosynth.jpg | Bin 0 -> 122363 bytes .../screenshots/calf_multiband_compressor.jpg | Bin 0 -> 171202 bytes content/images/screenshots/calf_organ.jpg | Bin 0 -> 185336 bytes content/images/screenshots/casynth.png | Bin 0 -> 243090 bytes content/images/screenshots/distrho_easyssp.png | Bin 0 -> 166899 bytes content/images/screenshots/distrho_obxd.png | Bin 0 -> 140338 bytes .../images/screenshots/distrho_tal_noisemaker.png | Bin 0 -> 184281 bytes content/images/screenshots/envfollower.png | Bin 0 -> 212071 bytes content/images/screenshots/hip2b.png | Bin 0 -> 118929 bytes content/images/screenshots/mod.png | Bin 0 -> 387240 bytes content/images/screenshots/powercut.png | Bin 0 -> 145432 bytes content/images/screenshots/stuck.png | Bin 0 -> 57833 bytes content/pages/index.md | 1 + extra_plugins/gallery.py | 184 +++++++++++++++++++++ pelicanconf.py | 20 ++- themes/lv2/static/css/slideshow.css | 38 +++++ themes/lv2/static/js/slideshow.js | 40 +++++ themes/lv2/templates/base.html | 18 +- themes/lv2/templates/page.html | 12 ++ 20 files changed, 304 insertions(+), 9 deletions(-) create mode 100644 content/images/screenshots/calf_equalizer.jpg create mode 100644 content/images/screenshots/calf_monosynth.jpg create mode 100644 content/images/screenshots/calf_multiband_compressor.jpg create mode 100644 content/images/screenshots/calf_organ.jpg create mode 100644 content/images/screenshots/casynth.png create mode 100644 content/images/screenshots/distrho_easyssp.png create mode 100644 content/images/screenshots/distrho_obxd.png create mode 100644 content/images/screenshots/distrho_tal_noisemaker.png create mode 100644 content/images/screenshots/envfollower.png create mode 100644 content/images/screenshots/hip2b.png create mode 100644 content/images/screenshots/mod.png create mode 100644 content/images/screenshots/powercut.png create mode 100644 content/images/screenshots/stuck.png create mode 100644 extra_plugins/gallery.py create mode 100644 themes/lv2/static/css/slideshow.css create mode 100644 themes/lv2/static/js/slideshow.js diff --git a/content/images/screenshots/calf_equalizer.jpg b/content/images/screenshots/calf_equalizer.jpg new file mode 100644 index 0000000..64e1b07 Binary files /dev/null and b/content/images/screenshots/calf_equalizer.jpg differ diff --git a/content/images/screenshots/calf_monosynth.jpg b/content/images/screenshots/calf_monosynth.jpg new file mode 100644 index 0000000..f137350 Binary files /dev/null and b/content/images/screenshots/calf_monosynth.jpg differ diff --git a/content/images/screenshots/calf_multiband_compressor.jpg b/content/images/screenshots/calf_multiband_compressor.jpg new file mode 100644 index 0000000..9e3d2a7 Binary files /dev/null and b/content/images/screenshots/calf_multiband_compressor.jpg differ diff --git a/content/images/screenshots/calf_organ.jpg b/content/images/screenshots/calf_organ.jpg new file mode 100644 index 0000000..e5d492c Binary files /dev/null and b/content/images/screenshots/calf_organ.jpg differ diff --git a/content/images/screenshots/casynth.png b/content/images/screenshots/casynth.png new file mode 100644 index 0000000..ce25a99 Binary files /dev/null and b/content/images/screenshots/casynth.png differ diff --git a/content/images/screenshots/distrho_easyssp.png b/content/images/screenshots/distrho_easyssp.png new file mode 100644 index 0000000..3363937 Binary files /dev/null and b/content/images/screenshots/distrho_easyssp.png differ diff --git a/content/images/screenshots/distrho_obxd.png b/content/images/screenshots/distrho_obxd.png new file mode 100644 index 0000000..b6082bb Binary files /dev/null and b/content/images/screenshots/distrho_obxd.png differ diff --git a/content/images/screenshots/distrho_tal_noisemaker.png b/content/images/screenshots/distrho_tal_noisemaker.png new file mode 100644 index 0000000..f54198d Binary files /dev/null and b/content/images/screenshots/distrho_tal_noisemaker.png differ diff --git a/content/images/screenshots/envfollower.png b/content/images/screenshots/envfollower.png new file mode 100644 index 0000000..8182db3 Binary files /dev/null and b/content/images/screenshots/envfollower.png differ diff --git a/content/images/screenshots/hip2b.png b/content/images/screenshots/hip2b.png new file mode 100644 index 0000000..6c4b5d4 Binary files /dev/null and b/content/images/screenshots/hip2b.png differ diff --git a/content/images/screenshots/mod.png b/content/images/screenshots/mod.png new file mode 100644 index 0000000..1245e77 Binary files /dev/null and b/content/images/screenshots/mod.png differ diff --git a/content/images/screenshots/powercut.png b/content/images/screenshots/powercut.png new file mode 100644 index 0000000..d9715e0 Binary files /dev/null and b/content/images/screenshots/powercut.png differ diff --git a/content/images/screenshots/stuck.png b/content/images/screenshots/stuck.png new file mode 100644 index 0000000..3f0e5df Binary files /dev/null and b/content/images/screenshots/stuck.png differ diff --git a/content/pages/index.md b/content/pages/index.md index c1adb9f..5968f45 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -1,5 +1,6 @@ Title: save_as: index.html +Gallery: . LV2 is a [free](http://www.gnu.org/philosophy/free-sw.html) standard for audio plugins, used by hundreds of plugins and other projects. At its core, LV2 is a diff --git a/extra_plugins/gallery.py b/extra_plugins/gallery.py new file mode 100644 index 0000000..3c5011d --- /dev/null +++ b/extra_plugins/gallery.py @@ -0,0 +1,184 @@ +import logging, json, os, sys, time, Image +from pelican import signals +from PIL import ImageOps + +""" + +Gallery plugin for Pelican +========================== + +This plugin creates a gallery attribute on content (article.gallery) you want to create. You +will define named presets which can be referenced in your templates. It will attempt to be smart +about regenerating photos once they exist. + +- Resizes images respective of aspect ratio +- Allows for multiple presets e.g. -> article.gallery.photos[0]['thumb'] + +Settings: +--------- + +Example configuration: + +GALLERY_FOLDER = "galleries" +GALLERY_SRC_PATH = "%s%s" % (BASE_PATH, "gallery_src") +GALLERY_OUTPUT_PATH = "%s%s%s" % (BASE_PATH, OUTPUT_PATH, GALLERY_FOLDER) +GALLERY_REGENERATE_EXISTING = False +GALLERY_PRESETS = [ + {"name": "thumb", "actions": [{"type": "fit", "height": 100, "width": 100, "from": (0.5, 0.5) }]}, + {"name": "slider", "actions": [{"type": "fit", "height": 300, "width": 900, "from": (0.5, 0.5) }]}, + {"name": "large", "actions": [{"type": "resize", "height": 640, "width": 850, "from": (0.5, 0.5) }]}, + {"name": "thumb_greyscale", + "actions": [ + {"type": "fit", "height": 100, "width": 100, "from": (0.5, 0.5) }, + {"type": "greyscale"} + ]}, + ] + +# This setting is optional, used for thumbnails in bootstrap +THUMBNAIL_GALLERY_CLASS = "span2" + +Article metadata example: +------------------------- +Gallery: + +{% if article.gallery %} +

Gallery

+ +{% endif %} + +""" + + +class Photo(): + + """ Class to represent a Photo, also handles applying presets to itself""" + def __init__(self, gallery, filename, output_path, preset): + self.gallery = gallery + self.filename = filename + self.input_file = "%s%s%s" % (self.gallery.absolute_src_path, os.sep, self.filename) + self.output_path = output_path + self.output_file = "%s%s%s" % (output_path, os.sep, self.filename) + self.preset = preset + self.image = None + self.width = None + self.height = None + self.image = Image.open(self.input_file) + self.process_image() + self.image = Image.open(self.output_file) + self.width, self.height = self.image.size + self.src = "%s%s%s%s%s%s%s" %(self.gallery.generator.settings["GALLERY_FOLDER"], + os.sep, + self.gallery.gallery_name, + os.sep, + self.preset["name"], + os.sep, + self.filename) + + + def process_image(self): + """Responsible for applying presets to the Image obj""" + if not os.path.isfile(self.output_file) or self.gallery.generator.settings["GALLERY_REGENERATE_EXISTING"]: + + # Actions should be processed in order of appearance in actions array + for i in range(len(self.preset["actions"])): + a = self.preset["actions"][i] + + if a["type"] == "fit": + if not "from" in a: + a["from"] = (0.5, 0.5) # crop from middle by default + + self.image = ImageOps.fit(self.image, (a["width"], a["height"],), method=Image.ANTIALIAS, centering=a["from"]) + + if a["type"] == "greyscale": + self.image = ImageOps.grayscale(self.image) + + if a["type"] == "resize": + self.image.thumbnail((a["width"], a["height"]), Image.NEAREST) + + # TODO: Write other useful transforms here! + + + self.image.save(self.output_file, "JPEG") + + + +class Gallery(): + """Represents a Gallery, iterate of gallery.photos in your Template""" + def __init__(self, generator, metadata): + self.generator = generator + self.gallery_name = None + self.files = [] + self.photos = [] + self.absolute_src_path = None + self.absolute_output_path = None + self.metadata = metadata + self.preset_dir = [] + + if "gallery" in self.metadata: + self.gallery_name = self.metadata["gallery"] + self.absolute_src_path = "%s%s%s" % (self.generator.settings["GALLERY_SRC_PATH"], + os.sep, + self.gallery_name) + + self.absolute_output_path = "%s%s%s" % (self.generator.settings["GALLERY_OUTPUT_PATH"], + os.sep, + self.gallery_name) + + self.create_preset_folders() + self.create_preset_images() + + def create_preset_images(self): + """Creates the image assets for each preset and returns a PhotoSet object""" + for f in self.get_files_from_data(): + photoInstances = {} + for preset in self.generator.settings["GALLERY_PRESETS"]: + preset_dir = "%s%s%s" % (self.absolute_output_path, + os.sep, + preset["name"]) + photoInstances[preset["name"]] = Photo(self, f, preset_dir, preset) + + self.photos.append(photoInstances) + + def create_preset_folders(self): + """Creates the folder structure for a gallery""" + + if not os.path.exists(self.absolute_output_path): + os.makedirs(self.absolute_output_path) + + # Create gallery preset folders for this gallery + if "GALLERY_PRESETS" in self.generator.settings: + for preset in self.generator.settings["GALLERY_PRESETS"]: + preset_dir = "%s%s%s" % (self.absolute_output_path, + os.sep, + preset["name"]) + self.preset_dir.append(preset_dir) + if not os.path.exists(preset_dir): + os.makedirs(preset_dir) + else: + print "You have no presets defined, please add GALLERY_PRESETS array to settings file, with at least one preset defined, see docs." + + def get_files_from_data(self): + print "getting files for %s" % self.absolute_src_path + from os import listdir + from os.path import isfile, join + return [ f for f in listdir(self.absolute_src_path) if isfile(join(self.absolute_src_path,f)) and f != ".DS_Store" ] + + + + +def get_galleries(generator, metadata): + if "gallery" in metadata.keys(): + metadata["gallery"] = Gallery(generator, metadata) + +def register(): + #signals.article_generator_init.connect(init_gallery_plugin) + #signals.article_generator_context.connect(get_galleries) + signals.page_generator_context.connect(get_galleries) diff --git a/pelicanconf.py b/pelicanconf.py index 653afb6..7b4b178 100644 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -7,7 +7,7 @@ SITENAME = u'LV2' SITELOGO = 'images/logo.svg' SITELOGO_WIDTH = '75' SITELOGO_HEIGHT = '48' -SITEURL = '' +SITEURL = 'http://lv2plug.in' PATH = 'content' @@ -54,3 +54,21 @@ DISPLAY_TAGS_ON_SIDEBAR = False DISPLAY_RECENT_POSTS_ON_SIDEBAR = False DISPLAY_SERIES_ON_SIDEBAR = False DISPLAY_CATEGORIES_ON_SIDEBAR = False + +PLUGIN_PATHS = ["extra_plugins"] +PLUGINS = ["gallery"] + +GALLERY_FOLDER = "galleries" +GALLERY_SRC_PATH = "%s%s" % (PATH, "/images/screenshots") +GALLERY_OUTPUT_PATH = "%s%s" % ("output/", GALLERY_FOLDER) +GALLERY_REGENERATE_EXISTING = True +GALLERY_PRESETS = [ + {"name": "thumb", + "actions": [{"type": "fit", "height": 100, "width": 100, "from": (0.5, 0.5)}]}, + {"name": "slider", + "actions" : []}, + {"name": "large", + "actions": [{"type": "resize", "height": 640, "width": 850, "from": (0.5, 0.5)}]}, + {"name": "thumb_greyscale", + "actions": [{"type": "fit", "height": 100, "width": 100, "from": (0.5, 0.5)}, + {"type": "greyscale"} ]}] diff --git a/themes/lv2/static/css/slideshow.css b/themes/lv2/static/css/slideshow.css new file mode 100644 index 0000000..7fe664d --- /dev/null +++ b/themes/lv2/static/css/slideshow.css @@ -0,0 +1,38 @@ +#slideshow { + background-color: #000; + border: 3px solid #000; + border-radius: 6px; + display: inline-block; + height: 20em; + line-height: 20em; + margin: 1em; + margin-left: auto; + margin-right: auto; + position: relative; + text-align: right; + vertical-align: middle; + width: 20em; +} + +#slideshow img { + left: 0; + width: 100%; + height: auto; + max-height: 100%; + opacity: 0; + position: absolute; + text-align: center; + transition-duration: 1s; + transition-property: opacity; + vertical-align: middle; +} + +#slideshow .fadein { + opacity: 1.0; + transform-origin: bottom left; +} + +#slideshow .fadeout { + opacity: 0.0; + transform-origin: bottom left; +} diff --git a/themes/lv2/static/js/slideshow.js b/themes/lv2/static/js/slideshow.js new file mode 100644 index 0000000..d9fb9c5 --- /dev/null +++ b/themes/lv2/static/js/slideshow.js @@ -0,0 +1,40 @@ +function getPreviousNode(n) { + var p = n.previousSibling; + while (p && p.nodeType !== 1) { + p = p.previousSibling; + } + return p; +} + +function startSlideShow() { + var slideshow = document.getElementById("slideshow"), + imgs = slideshow.getElementsByTagName("img"), + n = imgs.length, + m = Math.floor((Math.random() * n)), + pred = getPreviousNode(slideshow); + + // Shrink width of predecessor so gallery fits beside it + if (pred) { + pred.style.width = "50%"; + pred.style.display = "inline-block"; + } + + // Start transition of initial image + imgs[m].className = "fadein"; + m = (m + 1) % n; + + function tick() { + // Fade out the previous image, and fade in the next + var prev = (m + n - 1) % n, + next = (m + 1) % n; + + imgs[prev].className = ""; + imgs[m].className = "fadeout"; + imgs[next].className = "fadein"; + + m = (m + 1) % n; + } + window.setInterval(tick, 4000); +} + +startSlideShow(); diff --git a/themes/lv2/templates/base.html b/themes/lv2/templates/base.html index a3ca785..00f066d 100644 --- a/themes/lv2/templates/base.html +++ b/themes/lv2/templates/base.html @@ -1,13 +1,15 @@ - {% block title %}{{ SITENAME }}{%endblock%} - - - - {% if FEED_RSS %} - - {% endif %} + {% block head %} + {% block title %}{{ SITENAME }}{%endblock%} + + + + {% if FEED_RSS %} + + {% endif %} + {% endblock %} @@ -23,7 +25,7 @@ {% endif %} - + {% for title, link in MENUITEMS %}
  • {{ title }}
  • {% endfor %} diff --git a/themes/lv2/templates/page.html b/themes/lv2/templates/page.html index 33f6aca..762dd27 100644 --- a/themes/lv2/templates/page.html +++ b/themes/lv2/templates/page.html @@ -1,4 +1,8 @@ {% extends "base.html" %} +{% block head %} + {{ super() }} + +{% endblock %} {% block title %} {% if page.title %} {{ page.title }} @@ -13,4 +17,12 @@ {% endif %} {{ page.content }} + {% if page.gallery %} +
    + {% for photo_set in page.gallery.photos %} + {{ photo_set['slider'].src }} + {% endfor %} +
    + + {% endif %} {% endblock %} -- cgit v1.2.1