body {
font-family: Verdana;
+ font-size: 11px;
}
#header {
input {
margin-bottom: 4px;
}
+
+#menu {
+ text-align: right;
+}
+
+#menu a:link, #menu a:visited {
+ border-bottom:1px dotted #BBBBBB;
+ color:#BB0000;
+ text-decoration:none;
+}
+
+#menu a:link:hover, #menu a:visited:hover {
+ background-color:#EEEEEE;
+ color:#555555;
+}
+
+#menu a {
+}
import telemeta
from django.db import models
-from django.core import validators
+from telemeta.core import *
-class Collection(models.Model):
- "Group related media items"
+class MediaModel(Component):
+ pass
- name = models.CharField(maxlength=250)
+class MediaCore:
+ def list(self):
+ fields_list = []
+ for field in self._meta.fields:
+ fields_list.append({'name': field.name, 'value': getattr(self, field.name)})
+ return fields_list
- def __str__(self):
- return self.name
+ def to_dict(self):
+ fields_dict = {}
+ for field in self._meta.fields:
+ fields_dict[field.name] = getattr(self, field.name)
+ return fields_dict
- class Admin:
- pass
-
-class MediaItem(models.Model):
- "Describe an audio/video item with metadata"
+class MediaCollection(models.Model, MediaCore):
+ "Group related media items"
- collection = models.ForeignKey(Collection)
title = models.CharField(maxlength=250)
- author = models.CharField(maxlength=250)
-
-
-
- def get_dynamic_properties(self):
- "Retrieve dynamic properties associated with a given media item"
-
- definitions = MediaItemPropertyDefinition.objects.all()
- assigned = MediaItemProperty.objects.filter(media_item=self)
- assigned_dict = {}
- for p in assigned:
- assigned_dict[p.definition.id] = p
-
- properties = []
- for d in definitions:
- enumeration = MediaItemPropertyEnumerationItem.objects.filter(definition=d)
-
- if d.id in assigned_dict:
- if d.type == "text":
- value = assigned_dict[d.id].value
- else:
- value = assigned_dict[d.id].enum_item
-
- properties.append({
- "id": d.id, "name": d.name, "value": value,
- "type" : d.type, "enumeration" : enumeration})
- else:
- properties.append({"id": d.id, "name": d.name, "value": "",
- "type" : d.type, "enumeration" : enumeration})
-
- return properties
+ date = models.DateField()
+ contributor = models.CharField(maxlength=250, blank=True)
+ coverage = models.CharField(maxlength=250, blank=True)
+ creator = models.CharField(maxlength=250, blank=True)
+ description = models.CharField(maxlength=250, blank=True)
+ format = models.CharField(maxlength=250, blank=True)
+ identifier = models.CharField(maxlength=250, blank=True)
+ language = models.CharField(maxlength=250, blank=True)
+ publisher = models.CharField(maxlength=250, blank=True)
+ rights = models.CharField(maxlength=250, blank=True)
+ source = models.CharField(maxlength=250, blank=True)
+ subject = models.CharField(maxlength=250, blank=True)
def __str__(self):
- return self.author + " - " + self.title
+ return self.title
class Meta:
- pass
+ ordering = ['title']
+ db_table = 'telemeta_collection'
class Admin:
pass
-class MediaItemPropertyDefinition(models.Model):
- "Define a media item dynamic property"
-
- TYPE_CHOICES = (
- ('text', 'Text'),
- ('enumeration', 'Enumeration'),
- )
- name = models.CharField(maxlength=64)
- type = models.CharField(maxlength=64, choices = TYPE_CHOICES)
-
- def __str__(self):
- return self.name
-
- class Admin:
- pass
-class MediaItemPropertyEnumerationItem(models.Model):
- "Define a possible value for media item dynamic enumeration properties"
+class MediaItem(models.Model, MediaCore):
+ "Describe a item with metadata"
- definition = models.ForeignKey(MediaItemPropertyDefinition, core=True)
- name = models.CharField(maxlength=250)
+ collection = models.ForeignKey(MediaCollection, related_name="items")
+ collection.dublin_core = 'relation'
+ identifier = models.CharField(maxlength=250)
+ title = models.CharField(maxlength=250)
+ creator = models.CharField(maxlength=250)
+ date = models.DateField()
+ file = models.FileField(upload_to='items/%Y/%m/%d')
+ subject = models.CharField(maxlength=250, blank=True)
+ description = models.TextField(maxlength=250, blank=True)
+ contributor = models.CharField(maxlength=250, blank=True)
+ coverage = models.CharField(maxlength=250, blank=True)
+ format = models.CharField(maxlength=25, blank=True)
+ language = models.CharField(maxlength=250, blank=True)
+ publisher = models.CharField(maxlength=250, blank=True)
+ rights = models.CharField(maxlength=250, blank=True)
+ source = models.CharField(maxlength=250, blank=True)
+ duration = models.FloatField(max_digits=11, decimal_places=3, null=True, blank=True)
def __str__(self):
- return self.definition.name + " / " + self.name
+ return self.title
class Admin:
pass
-
-class MediaItemProperty(models.Model):
- "Associate a value to a media item dynamic property"
- definition = models.ForeignKey(MediaItemPropertyDefinition, core=True)
+ class Meta:
+ ordering = ['title']
+ db_table = 'telemeta_item'
+
+
+class MediaPart(models.Model, MediaCore):
+ "Describe the part of a media item"
+
+ contributor = models.CharField(maxlength=250)
+ coverage = models.CharField(maxlength=250)
+ creator = models.CharField(maxlength=250)
+ date = models.DateField()
+ description = models.CharField(maxlength=250)
+ format = models.CharField(maxlength=250)
+ identifier = models.CharField(maxlength=250)
+ language = models.CharField(maxlength=250)
+ publisher = models.CharField(maxlength=250)
+ rights = models.CharField(maxlength=250)
+ source = models.CharField(maxlength=250)
+ subject = models.CharField(maxlength=250)
+ title = models.CharField(maxlength=250)
media_item = models.ForeignKey(MediaItem)
- value = models.CharField(maxlength=250)
- enum_item = models.ForeignKey(MediaItemPropertyEnumerationItem, null=True)
+ media_item.dublin_core = 'relation'
+ parent = models.ForeignKey('self', null=True, related_name='children')
+ media_item.dublin_core = 'relation'
+ start = models.FloatField(max_digits=11, decimal_places=3)
+ end = models.FloatField(max_digits=11, decimal_places=3)
def __str__(self):
- return str(self.media_item) + " / " + str(self.definition)
+ return self.title
class Meta:
- unique_together = (("media_item", "definition"),)
+ ordering = ['title']
+ db_table = 'telemeta_part'
class Admin:
pass
-
-class Part:
- media_item = models.ForeignKey(MediaItem)
- parent = models.ForeignKey('self', null=True, related_name='children')
- name = models.CharField(maxlength=250)
+
<html>
-<link rel="stylesheet" href="/telemeta/css/style.css" />
+<link rel="stylesheet" href="/css/style.css" />
<body>
<div id="header">
Telemeta Web Interface
</div>
+<div id="menu">
+<a href="/collections">Collections</a> |
+<a href="/items">Items</a>
+</div>
{% block content %}{% endblock %}
</body>
</html>
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+{% if object %}
+ <h3>Collection: {{ object.title }}</h3>
+ <ul>
+ {% for field in object.list %}
+ {% ifnotequal field.name "id" %}
+ {% ifnotequal field.name "title" %}
+
+ <li><b>{{ field.name }}</b> : {{ field.value }}</li>
+
+ {% endifnotequal %}
+ {% endifnotequal %}
+ {% endfor %}
+ </ul>
+ <hr>
+ <h4>Items</h4>
+ <ul>
+ {% for item in object.items.all %}
+ <li><b>{{ item.creator }}</b> - {{ items.title }}
+ <a href="/items/{{ item.id }}">View</a>
+ <a href="#">Edit</a>
+ </li>
+ {% endfor %}
+ </ul>
+{% else %}
+ <p>No such collection</p>
+{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+<h3>Collections</h3>
+{% if object_list %}
+ <ul>
+ {% for p in object_list %}
+ <li><b>{{ p.title }}</b>
+ <a href="{{ p.id }}">View</a>
+ <a href="#">Edit</a>
+ </li>
+ {% endfor %}
+ </ul>
+{% else %}
+ <p>No pieces are available.</p>
+{% endif %}
+{% endblock %}
-<pre>{% debug %}</pre>
+{% extends "base.html" %}
-<h3>Pieces</h3>
-{% if pieces %}
+{% block content %}
+<h3>Media items</h3>
+{% if object_list %}
<ul>
- {% for p in pieces %}
- <li><b>{{ p.author }}</b> - {{ p.title }}</li>
+ {% for p in object_list %}
+ <li><b>{{ p.author }}</b> - {{ p.title }}
+ <a href="{{ p.id }}">View</a>
+ <a href="#">Edit</a>
+ </li>
{% endfor %}
</ul>
{% else %}
- <p>No pieces are available.</p>
+ <p>No media item available.</p>
{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+{% if item %}
+ <h3>Item: {{ item.title }}</h3>
+ <ul>
+ {% for field in item.list %}
+ {% ifnotequal field.name "id" %}
+ {% ifnotequal field.name "title" %}
+ {% ifnotequal field.name "file" %}
+
+ <li><b>{{ field.name }}</b> :
+ {% ifequal field.name "collection" %}
+ <a href="/collections/{{ field.value.id }}">{{ field.value }}</a>
+ {% else %}
+ {{ field.value }}
+ {% endifequal %}
+ </li>
+
+ {% endifnotequal %}
+ {% endifnotequal %}
+ {% endifnotequal %}
+ {% endfor %}
+ </ul>
+ Download:
+ {% for format in export_formats %}
+ <a href="/items/{{ item.id }}/download/{{ format }}">{{ format }}</a>
+ {% endfor %}
+{% else %}
+ <p>No such item</p>
+{% endif %}
+{% endblock %}
{% if object_list %}
<ul>
{% for p in object_list %}
- <li><b>{{ p.author }}</b> - {{ p.title }}
+ <li><b>{{ p.creator }}</b> - {{ p.title }}
<a href="{{ p.id }}">View</a>
<a href="#">Edit</a>
</li>
from django.conf.urls.defaults import *
-from telemeta.models import MediaItem
+from telemeta.models import MediaItem, MediaCollection
-list_dict = {
+all_items = {
'queryset': MediaItem.objects.all(),
}
+all_collections = {
+ 'queryset': MediaCollection.objects.all(),
+}
+
urlpatterns = patterns('',
(r'^$', 'telemeta.views.web.index'),
- (r'^media_item/$', 'django.views.generic.list_detail.object_list',
- dict(list_dict, paginate_by=10, template_name="mediaitem_list.html")),
- (r'^media_item/(?P<media_item_id>[0-9]+)/$', 'telemeta.views.web.media_item_edit'),
+ (r'^items/$', 'django.views.generic.list_detail.object_list',
+ dict(all_items, paginate_by=10, template_name="mediaitem_list.html")),
+ (r'^items/(?P<item_id>[0-9]+)/$', 'telemeta.views.web.item_detail'),
+ (r'^items/(?P<item_id>[0-9]+)/download/(?P<format>[0-9A-Z]+)/$',
+ 'telemeta.views.web.item_export'),
+ #(r'^media_item/(?P<media_item_id>[0-9]+)/$', 'telemeta.views.web.media_item_edit'),
(r'^media_item/(?P<media_item_id>[0-9]+)/update/$', 'telemeta.views.web.media_item_update'),
+ (r'^collections/$', 'django.views.generic.list_detail.object_list',
+ dict(all_collections, paginate_by=10, template_name="collection_list.html")),
+ (r'^collections/(?P<object_id>[0-9]+)/$',
+ 'django.views.generic.list_detail.object_detail',
+ dict(all_collections, template_name="collection_detail.html")),
+
+
# CSS (FIXME: for developement only)
(r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': './telemeta/css'}),
)
import telemeta
from django.template import Context, loader
from django.http import HttpResponse
+from django.http import Http404
from telemeta.models import MediaItem
-from telemeta.models import MediaItemPropertyDefinition
-from telemeta.models import MediaItemPropertyEnumerationItem
-from telemeta.models import MediaItemProperty
from django.shortcuts import render_to_response
import re
+from telemeta.core import *
+from telemeta.core import ComponentManager
+from telemeta.export import *
+from django.conf import settings
+import os
def index(request):
"Render the homepage"
})
return HttpResponse(template.render(context))
+class WebView(Component):
+
+ exporters = ExtensionPoint(IExporter)
+
+ def item_detail(self, request, item_id):
+ item = MediaItem.objects.get(pk=item_id)
+ formats = []
+ for exporter in self.exporters:
+ formats.append(exporter.get_format())
+ return render_to_response('mediaitem_detail.html',
+ {'item': item, 'export_formats': formats})
+
+ def file_stream(self, filepath):
+ buffer_size = 0xFFFF
+ f = open(filepath, 'rb')
+ chunk = f.read(buffer_size)
+ yield chunk
+ while chunk:
+ chunk = f.read(buffer_size)
+ yield chunk
+ f.close()
+
+ def item_export(self, request, item_id, format):
+ for exporter in self.exporters:
+ if exporter.get_format() == format:
+ break
+
+ if exporter.get_format() != format:
+ raise Http404
+
+ mime_type = exporter.get_mime_type()
+
+ exporter.set_cache_dir(settings.TELEMETA_EXPORT_CACHE_DIR)
+
+ item = MediaItem.objects.get(pk=item_id)
+
+ infile = settings.MEDIA_ROOT + "/" + item.file
+ metadata = item.to_dict()
+ metadata['collection'] = str(metadata['collection'])
+ metadata['Collection'] = metadata['collection']
+ metadata['Artist'] = metadata['creator']
+ metadata['Title'] = metadata['title']
+
+ outfile = exporter.process(item.id, infile, metadata, [])
+
+ return HttpResponse(self.file_stream(outfile), mimetype = mime_type)
+
+comp_mgr = ComponentManager()
+view = WebView(comp_mgr)
+item_detail = view.item_detail
+item_export = view.item_export
+
def media_item_edit(request, media_item_id):
"Provide MediaItem object edition"