Created "video" and "media" TALES extensions
authorThierry Florac <thierry.florac@onf.fr>
Thu, 20 Dec 2018 08:42:49 +0100
changeset 118 0ebdb35ceaed
parent 117 a498a17a34c4
child 119 4cdacd1e34c7
Created "video" and "media" TALES extensions
src/pyams_media/skin/__init__.py
src/pyams_media/skin/templates/video.pt
src/pyams_media/skin/video.py
--- a/src/pyams_media/skin/__init__.py	Fri Nov 16 15:17:08 2018 +0100
+++ b/src/pyams_media/skin/__init__.py	Thu Dec 20 08:42:49 2018 +0100
@@ -12,12 +12,6 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-
-# import packages
 from fanstatic import Library, Resource
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_media/skin/templates/video.pt	Thu Dec 20 08:42:49 2018 +0100
@@ -0,0 +1,18 @@
+<video tal:define="href tales:absolute_url(video);
+				   conversions tales:conversions(video);
+				   thumbnails tales:thumbnails(video);
+				   size thumbnails.get_image_size();
+				   thumbnail thumbnails.get_thumbnail('{0}x{1}'.format(size[0], size[1]), 'png');
+				   timestamp tales:timestamp(thumbnail);"
+	   controls
+	   poster="${href}/++thumb++${size[0]}x${size[1]}.png?_=${timestamp}">
+	<tal:loop repeat="conversion conversions.get_conversions(order=('video/webm','video/mp4','video/x-flv'))">
+		<source tal:define="media_width conversions.get_conversion_width(conversion.__name__);
+							media_src tales:absolute_url(conversion);
+							video_type tales:video_type(conversion);"
+				tal:condition="video_type"
+				type="${video_type}"
+				src="${media_src.replace('+', '%2b')}"
+				media="${'all and (max-width: {0}px)'.format(media_width) if media_width else None}" />
+	</tal:loop>
+</video>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_media/skin/video.py	Thu Dec 20 08:42:49 2018 +0100
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+from pyramid.renderers import render
+from zope.interface import Interface
+
+from pyams_file.interfaces import IFile
+from pyams_template.template import get_view_template
+from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
+from pyams_utils.interfaces.tales import ITALESExtension
+
+
+@adapter_config(name='video',
+                context=(Interface, Interface, Interface),
+                provides=ITALESExtension)
+class VideoTALESExtension(ContextRequestViewAdapter):
+    """Video TALES adapter
+
+    This TALES adapter can be used to create a 'video' HTML tag
+    embedding all video attributes.
+    """
+
+    _render = get_view_template()
+
+    def render(self, context=None, *args, **kwargs):
+        """Video renderer
+
+        Method signature accepts unused *args and **kwargs to match 'picture' TALES extension.
+        """
+        if context is None:
+            context = self.context
+        return render('templates/video.pt', {
+            'video': context
+        }, request=self.request)
+
+
+@adapter_config(name='media',
+                context=(Interface, Interface, Interface),
+                provides=ITALESExtension)
+class MediaTALESExtension(ContextRequestViewAdapter):
+    """Media TALES adapter
+
+    This TALES adapter can be used to create any media HTML tag.
+    Actually images and videos are supported, and the right renderer will be used according
+    to context content type.
+    """
+
+    def render(self, context=None, lg_thumb='lg', lg_width=12, md_thumb='md', md_width=12,
+               sm_thumb='sm', sm_width=12, xs_thumb='xs', xs_width=12, alt='', css_class=''):
+        if context is None:
+            context = self.context
+        if not IFile.providedBy(context):
+            return ''
+        registry = self.request.registry
+        if context.content_type.startswith('video/'):
+            extension = registry.queryMultiAdapter((context, self.request, self.view), ITALESExtension, name='video')
+        elif context.content_type.startswith('image/'):
+            extension = registry.queryMultiAdapter((context, self.request, self.view), ITALESExtension, name='picture')
+        else:
+            extension = None
+        if extension is not None:
+            return extension.render(context, lg_thumb, lg_width, md_thumb, md_width, sm_thumb, sm_width, xs_thumb,
+                                    xs_width, alt, css_class)
+        else:
+            return ''