# -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Samalyse SARL
+# Copyright (C) 2003-2005 Edgewall Software
+# Copyright (C) 2003-2004 Jonas Borgström <jonas@edgewall.com>
+# Copyright (C) 2004-2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.
#
-# Author: Olivier Guilyardi <olivier@samalyse.com>
+# Author: Jonas Borgström <jonas@edgewall.com>
+# Christopher Lenz <cmlenz@gmx.de>
+# Olivier Guilyardi <olivier@samalyse.com>
-__all__ = ['TelemetaError']
+__all__ = ['Component', 'ExtensionPoint', 'implements', 'Interface',
+ 'TelemetaError']
class TelemetaError(Exception):
# self.title = title
# self.show_traceback = show_traceback
+class Interface(object):
+ """Marker base class for extension point interfaces."""
+
+
+class ExtensionPoint(property):
+ """Marker class for extension points in components."""
+
+ def __init__(self, interface):
+ """Create the extension point.
+
+ @param interface: the `Interface` subclass that defines the protocol
+ for the extension point
+ """
+ property.__init__(self, self.extensions)
+ self.interface = interface
+ self.__doc__ = 'List of components that implement `%s`' % \
+ self.interface.__name__
+
+ def extensions(self, component):
+ """Return a list of components that declare to implement the extension
+ point interface."""
+ extensions = ComponentMeta._registry.get(self.interface, [])
+ return filter(None, [component.compmgr[cls] for cls in extensions])
+
+ def __repr__(self):
+ """Return a textual representation of the extension point."""
+ return '<ExtensionPoint %s>' % self.interface.__name__
+
+
+class ComponentMeta(type):
+ """Meta class for components.
+
+ Takes care of component and extension point registration.
+ """
+ _components = []
+ _registry = {}
+
+ def __new__(cls, name, bases, d):
+ """Create the component class."""
+
+ d['_implements'] = _implements[:]
+ del _implements[:]
+
+ new_class = type.__new__(cls, name, bases, d)
+ if name == 'Component':
+ # Don't put the Component base class in the registry
+ return new_class
+
+ # Only override __init__ for Components not inheriting ComponentManager
+ if True not in [issubclass(x, ComponentManager) for x in bases]:
+ # Allow components to have a no-argument initializer so that
+ # they don't need to worry about accepting the component manager
+ # as argument and invoking the super-class initializer
+ init = d.get('__init__')
+ if not init:
+ # Because we're replacing the initializer, we need to make sure
+ # that any inherited initializers are also called.
+ for init in [b.__init__._original for b in new_class.mro()
+ if issubclass(b, Component)
+ and '__init__' in b.__dict__]:
+ break
+ def maybe_init(self, compmgr, init=init, cls=new_class):
+ if cls not in compmgr.components:
+ compmgr.components[cls] = self
+ if init:
+ init(self)
+ maybe_init._original = init
+ new_class.__init__ = maybe_init
+
+ if d.get('abstract'):
+ # Don't put abstract component classes in the registry
+ return new_class
+
+ ComponentMeta._components.append(new_class)
+ for interface in d.get('_implements', []):
+ ComponentMeta._registry.setdefault(interface, []).append(new_class)
+ for base in [base for base in bases if hasattr(base, '_implements')]:
+ for interface in base._implements:
+ ComponentMeta._registry.setdefault(interface, []).append(new_class)
+
+ return new_class
+
+
+_implements = []
+
+def implements(*interfaces):
+ """Can be used in the class definiton of `Component` subclasses to declare
+ the extension points that are extended.
+ """
+ _implements.extend(interfaces)
+
+
+class Component(object):
+ """Base class for components.
+
+ Every component can declare what extension points it provides, as well as
+ what extension points of other components it extends.
+ """
+ __metaclass__ = ComponentMeta
+
+ def __new__(cls, *args, **kwargs):
+ """Return an existing instance of the component if it has already been
+ activated, otherwise create a new instance.
+ """
+ # If this component is also the component manager, just invoke that
+ if issubclass(cls, ComponentManager):
+ self = super(Component, cls).__new__(cls)
+ self.compmgr = self
+ return self
+
+ # The normal case where the component is not also the component manager
+ compmgr = args[0]
+ self = compmgr.components.get(cls)
+ if self is None:
+ self = super(Component, cls).__new__(cls)
+ self.compmgr = compmgr
+ compmgr.component_activated(self)
+ return self
+
+
+class ComponentManager(object):
+ """The component manager keeps a pool of active components."""
+
+ def __init__(self):
+ """Initialize the component manager."""
+ self.components = {}
+ self.enabled = {}
+ if isinstance(self, Component):
+ self.components[self.__class__] = self
+
+ def __contains__(self, cls):
+ """Return wether the given class is in the list of active components."""
+ return cls in self.components
+
+ def __getitem__(self, cls):
+ """Activate the component instance for the given class, or return the
+ existing the instance if the component has already been activated."""
+ if cls not in self.enabled:
+ self.enabled[cls] = self.is_component_enabled(cls)
+ if not self.enabled[cls]:
+ return None
+ component = self.components.get(cls)
+ if not component:
+ if cls not in ComponentMeta._components:
+ raise TelemetaError, 'Component "%s" not registered' % cls.__name__
+ try:
+ component = cls(self)
+ except TypeError, e:
+ raise TelemetaError, 'Unable to instantiate component %r (%s)' \
+ % (cls, e)
+ return component
+
+ def component_activated(self, component):
+ """Can be overridden by sub-classes so that special initialization for
+ components can be provided.
+ """
+
+ def is_component_enabled(self, cls):
+ """Can be overridden by sub-classes to veto the activation of a
+ component.
+
+ If this method returns False, the component with the given class will
+ not be available.
+ """
+ return True
{% if collection %}\r
\r
{% block submenu %}\r
- <div><a href="{% url telemeta-collection-dublincore collection.public_id %}">Dublin Core</a></div>\r
+ <div>\r
+ <a href="{% url telemeta-collection-detail-edit collection.public_id %}"><button>EDIT</button></a>\r
+ <a href="{% url telemeta-collection-dublincore collection.public_id %}">Dublin Core</a>\r
+ </div>\r
{% endblock %}\r
\r
{% block content %}\r
{% endblock %}\r
{% block extra_javascript %}\r
\r
-<script src="{% url telemeta-js "wz_jsgraphics.js" %}" type="text/javascript"></script>\r
-<script src="{% url telemeta-js "soundmanager2.js" %}" type="text/javascript"></script>\r
-<script src="{% url telemeta-timeside "src/timeside.js" %}" type="text/javascript"></script>\r
-<script src="{% url telemeta-js "player.js" %}" type="text/javascript"></script>\r
-\r
-<script type="text/javascript">\r
-soundManager.url = '{% url telemeta-swf "./" %}';\r
-soundManager.flashVersion = 9;\r
-soundManager.useMovieStar = true; // enable MP4/M4A/AAC\r
-soundManager.debugMode = false;\r
-set_player_image_url('{% url telemeta-item-visualize item.public_id,visualizer_id,"WIDTH","HEIGHT" %}');\r
-load_player({{ item.approx_duration.as_seconds }});\r
-</script>\r
\r
{% endblock %}\r
\r
{% block content %}\r
\r
<h3>Item : {{ item }}</h3>\r
-<div class="{% if item.file %}with-rightcol{% endif %}">\r
-\r
-{% if item.file %}\r
- <div id="player_maximized" class="ts-skin-lab">\r
- <a href="#" class="toggle">Minimize</a>\r
- <div class="wazing"></div>\r
- </div>\r
- <div id="rightcol">\r
- <div id="player_minimized" class="ts-skin-lab">\r
- <a href="#" class="toggle">Maximize</a>\r
- <div class="wazing"></div>\r
- <div id="player" class="ts-player">\r
- <div class="ts-viewer">\r
- <div class="ts-wave">\r
- <div class="ts-image-container">\r
- <a href="{% url telemeta-item-export item.public_id,"mp3" %}">\r
- <img class="ts-image" src="{% url telemeta-item-visualize item.public_id,visualizer_id,360,130 %}"\r
- alt="" /></a>\r
- </div>\r
- </div>\r
- </div>\r
- </div>\r
- </div>\r
-\r
- <div class="item_visualization">\r
- <form id="visualizer_id_form" method="get" action="#">\r
- <!--\r
- <select name="visualizer_id" onchange="this.form.submit()">\r
- {% for v in visualizers %}\r
- <option value="{{ v.id }}" {% ifequal v.id visualizer_id %} selected="selected" {% endifequal %}>\r
- {{v.name}}</option>\r
- {% endfor %}\r
- </select>\r
- -->\r
- <select id="visualizer_id" name="visualizer_id">\r
- {% for v in visualizers %}\r
- <option value="{% url telemeta-item-visualize item.public_id,v.id,"WIDTH","HEIGHT" %}">\r
- {{v.name}}</option>\r
- {% endfor %}\r
- </select>\r
- <input type="submit" value="Set" />\r
- </form>\r
-\r
- <div class="analyzer">\r
- <table width="100%">\r
- <tr class="analyzer-title">\r
- <td>Property</td>\r
- <td>Value</td>\r
- <td>Unit</td>\r
- <tr>\r
- {% for analyser in analysers %}\r
- <tr class="analyzer-line">\r
- <td>\r
- {{ analyser.name }}\r
- </td>\r
- <td>\r
- {{ analyser.value }}\r
- </td>\r
- <td>\r
- {{ analyser.unit }}\r
- </td>\r
- </tr>\r
- {% endfor %}\r
- </table>\r
- </div>\r
-<!--\r
- <form method="get" action="#">\r
- <p> Vamp plugin analysis</p>\r
- <select name="vamp_id">\r
- {% for plugin in vamp_plugins %}\r
- <option value="{{ plugin }}" {% ifequal plugin vamp_id %} selected="selected" {% endifequal %}>\r
- {{ plugin }}</option>\r
- {% endfor %}\r
- </select>\r
- <input type="submit" value="Get" />\r
- </form>\r
--->\r
- </div>\r
-\r
- {% if audio_export_enabled %}\r
- <div class="exporter">\r
- <p>{% trans "Download:" %}\r
- {% for format in export_formats %}\r
- <a href="{% url telemeta-item-export item.public_id,format.extension %}">{{ format.name }}</a>\r
- {% endfor %}</p>\r
- </div>\r
- {% endif %}\r
-\r
- </div>\r
-{% endif %}\r
\r
<div class="infos">\r
<form method="POST" action="">{% csrf_token %}\r
- {{ formset }}\r
+ {{ formset }}\r
<button type="submit">SAVE</button>\r
</form>\r
</div>\r
\r
-</div> <!-- with-rightcol -->\r
\r
{% endblock %}\r
{% else %}\r
web_view.collection_playlist,
dict(template="telemeta/collection.m3u", mimetype="audio/mpegurl"),
name="telemeta-collection-m3u"),
+ url(r'^collections/(?P<public_id>[A-Za-z0-9._-]+)/edit/$', web_view.collection_detail_edit,
+ dict(template='telemeta/collection_detail_edit.html'), name="telemeta-collection-detail-edit"),
# search
url(r'^search/$', web_view.search, name="telemeta-search"),
'items': items})
return HttpResponse(template.render(context))
- def collection_detail(self, request, public_id, template=''):
+ def collection_detail(self, request, public_id, template='telemeta/collection_detail.html'):
collection = MediaCollection.objects.get(public_id=public_id)
return render(request, template, {'collection': collection})
+ def collection_detail_edit(self, request, public_id, template='telemeta/collection_detail_edit.html'):
+ collection = MediaCollection.objects.get(public_id=public_id)
+ MediaCollectionFormSet = modelformset_factory(MediaCollection)
+ if request.method == 'POST':
+ formset = MediaCollectionFormSet(request.POST, request.FILES, queryset=MediaCollection.objects.filter(code=public_id))
+ if formset.is_valid():
+ formset.save()
+ else:
+ formset = MediaCollectionFormSet(queryset=MediaCollection.objects.filter(code=public_id))
+ return render(request, template, {'collection': collection, "formset": formset,})
def item_detail(self, request, public_id, template='telemeta/mediaitem_detail.html'):
"""Show the details of a given item"""
item = MediaItem.objects.get(public_id=public_id)
- print 'ok'
formats = []
for encoder in self.encoders:
formats.append({'name': encoder.format(), 'extension': encoder.file_extension()})
else:
grapher_id = 'waveform'
- analyze_file = public_id + '.xml'
-
- if self.cache.exists(analyze_file):
- analyzers = self.cache.read_analyzer_xml(analyze_file)
- if not item.approx_duration:
- for analyzer in analyzers:
- if analyzer['id'] == 'duration':
- value = analyzer['value']
- time = value.split(':')
- time[2] = time[2].split('.')[0]
- time = ':'.join(time)
- item.approx_duration = time
- item.save()
- else:
- analyzers = []
- analyzers_sub = []
- if item.file:
- decoder = timeside.decoder.FileDecoder(item.file.path)
- pipe = decoder
-
- for analyzer in self.analyzers:
- subpipe = analyzer()
- analyzers_sub.append(subpipe)
- pipe = pipe | subpipe
-
- pipe.run()
-
- mime_type = decoder.format()
- analyzers.append({'name': 'Mime type', 'id': 'mime_type', 'unit': '', 'value': mime_type})
-
- for analyzer in analyzers_sub:
- value = analyzer.result()
- if analyzer.id() == 'duration':
- approx_value = int(round(value))
- item.approx_duration = approx_value
- item.save()
- value = datetime.timedelta(0,value)
-
- analyzers.append({'name':analyzer.name(),
- 'id':analyzer.id(),
- 'unit':analyzer.unit(),
- 'value':str(value)})
-
- self.cache.write_analyzer_xml(analyzers, analyze_file)
-
+ analyzers = self.item_analyze(item)
+
return render(request, template,
{'item': item, 'export_formats': formats,
'visualizers': graphers, 'visualizer_id': grapher_id,'analysers': analyzers, #FIXME analysers
def item_detail_edit(self, request, public_id, template='telemeta/mediaitem_detail_edit.html'):
"""Show the details of a given item"""
item = MediaItem.objects.get(public_id=public_id)
-
formats = []
for encoder in self.encoders:
formats.append({'name': encoder.format(), 'extension': encoder.file_extension()})
grapher_id = request.REQUEST['grapher_id']
else:
grapher_id = 'waveform'
+
+ analyzers = self.item_analyze(item)
+
+ MediaItemFormSet = modelformset_factory(MediaItem)
+ if request.method == 'POST':
+ formset = MediaItemFormSet(request.POST, request.FILES, queryset=MediaItem.objects.filter(code=public_id))
+ if formset.is_valid():
+ formset.save()
+ else:
+ formset = MediaItemFormSet(queryset=MediaItem.objects.filter(code=public_id))
+
+ return render(request, template,
+ {'item': item, 'export_formats': formats,
+ 'visualizers': graphers, 'visualizer_id': grapher_id,'analysers': analyzers, #FIXME analysers
+ 'audio_export_enabled': getattr(settings, 'TELEMETA_DOWNLOAD_ENABLED', True), "formset": formset,
+ })
+ def item_analyze(self, item):
+ public_id = item.public_id
analyze_file = public_id + '.xml'
if self.cache.exists(analyze_file):
'value':str(value)})
self.cache.write_analyzer_xml(analyzers, analyze_file)
-
- MediaItemFormSet = modelformset_factory(MediaItem)
- if request.method == 'POST':
- formset = MediaItemFormSet(request.POST, request.FILES, queryset=MediaItem.objects.filter(code=public_id))
- if formset.is_valid():
- formset.save()
- # do something.
- else:
- formset = MediaItemFormSet(queryset=MediaItem.objects.filter(code=public_id))
-
- return render(request, template,
- {'item': item, 'export_formats': formats,
- 'visualizers': graphers, 'visualizer_id': grapher_id,'analysers': analyzers, #FIXME analysers
- 'audio_export_enabled': getattr(settings, 'TELEMETA_DOWNLOAD_ENABLED', True), "formset": formset,
- })
+ return analyzers
- def item_analyze(self):
- pass
def item_visualize(self, request, public_id, visualizer_id, width, height):
item = MediaItem.objects.get(public_id=public_id)
def logout(self, request):
auth.logout(request)
return redirect('telemeta-home')
-
- @jsonrpc_method('telemeta.add_marker_test')
- def add_marker_test(request,marker):
- print "Received"
@jsonrpc_method('telemeta.add_marker')
def add_marker(request, marker):