From: yomguy Date: Mon, 7 Feb 2011 16:39:33 +0000 (+0100) Subject: fix collection edit, separate item_analyze method X-Git-Tag: 1.1~462 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=60147d1d55a4bb2744e9d4c6a05683c4981d491a;p=telemeta.git fix collection edit, separate item_analyze method --- diff --git a/telemeta/core.py b/telemeta/core.py index c7e7e221..4c3c17bb 100644 --- a/telemeta/core.py +++ b/telemeta/core.py @@ -1,14 +1,20 @@ # -*- coding: utf-8 -*- # # Copyright (C) 2007 Samalyse SARL +# Copyright (C) 2003-2005 Edgewall Software +# Copyright (C) 2003-2004 Jonas Borgström +# Copyright (C) 2004-2005 Christopher Lenz # 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 +# Author: Jonas Borgström +# Christopher Lenz +# Olivier Guilyardi -__all__ = ['TelemetaError'] +__all__ = ['Component', 'ExtensionPoint', 'implements', 'Interface', + 'TelemetaError'] class TelemetaError(Exception): @@ -21,3 +27,168 @@ 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 '' % 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 diff --git a/telemeta/templates/telemeta_default/collection_detail.html b/telemeta/templates/telemeta_default/collection_detail.html index cf87ccdf..daad1e77 100644 --- a/telemeta/templates/telemeta_default/collection_detail.html +++ b/telemeta/templates/telemeta_default/collection_detail.html @@ -11,7 +11,10 @@ {% if collection %} {% block submenu %} - + {% endblock %} {% block content %} diff --git a/telemeta/templates/telemeta_default/mediaitem_detail_edit.html b/telemeta/templates/telemeta_default/mediaitem_detail_edit.html index d505c778..1d099886 100644 --- a/telemeta/templates/telemeta_default/mediaitem_detail_edit.html +++ b/telemeta/templates/telemeta_default/mediaitem_detail_edit.html @@ -12,19 +12,6 @@ {% endblock %} {% block extra_javascript %} - - - - - - {% endblock %} @@ -38,105 +25,14 @@ load_player({{ item.approx_duration.as_seconds }}); {% block content %}

Item : {{ item }}

-
- -{% if item.file %} -
- Minimize -
-
-
-
- Maximize -
-
-
-
-
- - -
-
-
-
-
- -
-
- - - -
- -
- - - - - - - {% for analyser in analysers %} - - - - - - {% endfor %} -
PropertyValueUnit
- {{ analyser.name }} - - {{ analyser.value }} - - {{ analyser.unit }} -
-
- -
- - {% if audio_export_enabled %} -
-

{% trans "Download:" %} - {% for format in export_formats %} - {{ format.name }} - {% endfor %}

-
- {% endif %} - -
-{% endif %}
{% csrf_token %} - {{ formset }} + {{ formset }}
-
{% endblock %} {% else %} diff --git a/telemeta/urls.py b/telemeta/urls.py index 9e6b3a01..0d9fb499 100644 --- a/telemeta/urls.py +++ b/telemeta/urls.py @@ -108,6 +108,8 @@ urlpatterns = patterns('', web_view.collection_playlist, dict(template="telemeta/collection.m3u", mimetype="audio/mpegurl"), name="telemeta-collection-m3u"), + url(r'^collections/(?P[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"), diff --git a/telemeta/web/base.py b/telemeta/web/base.py index 6d9ffe42..2ae4af7d 100644 --- a/telemeta/web/base.py +++ b/telemeta/web/base.py @@ -109,15 +109,24 @@ class WebView(object): '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()}) @@ -130,51 +139,8 @@ class WebView(object): 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 @@ -184,7 +150,6 @@ class WebView(object): 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()}) @@ -196,7 +161,25 @@ class WebView(object): 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): @@ -241,24 +224,8 @@ class WebView(object): '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) @@ -606,10 +573,6 @@ class WebView(object): 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):