Install all dependencies like this::
sudo aptitude install python python-django python-xml python-mysqldb mysql-server \
- python-ctypes python-setuptools python-support python-docutils
+ python-ctypes python-setuptools python-support python-docutils \
+ python-libxml2
To get MP3 reading and writing, just add these lines to your /etc/apt/sources-list::
setup(
name = "telemeta",
- url = "/http://svn.parisson.org/telemeta",
- description = "web frontend to backup, transcode and tag any audio content with metadata",
- author = ["Guillaume Pellerin, Olivier Guilyardi"],
- author_email = ["pellerin@parisson.com","olivier@samalyse.com"],
+ url = "http://telemeta.org",
+ description = "Web Audio Content Management System",
+ author = ["Guillaume Pellerin, Olivier Guilyardi", "Riccardo Zaccarelli"],
+ author_email = ["pellerin@parisson.com","olivier@samalyse.com", "riccardo.zaccarrelli@gmail.com"],
version = version,
packages = packages,
data_files = data_files,
long_description = """
-Telemeta is a web audio archiving program which introduces useful and secure methods to
-backup, index, transcode, analyse and publish any digitalized audio file with its metadata.
-It is dedicated to professionnals who wants to easily backup and publish documented sounds
-from collections of vinyls, magnetic tapes or audio CDs over a strong database, in accordance
-with open standards.
+Telemeta is a web audio archiving program which introduces useful and secure methods to backup, index, transcode, analyse and publish any digitalized audio file with its metadata. It is dedicated to professionnals who wants to easily backup and publish documented sounds from collections of vinyls, magnetic tapes or audio CDs over a strong database, in accordance with open standards.
Here are the main features of Telemeta:
- * Secure archiving, editing and publishing of audio files over internet.
- * User friendly web frontend including workflows and high level search methods
- * Smart dynamical and skinnable audio player (thanks to Timeside and soundmanager2)
- * "On the fly" analyzing, transcoding and metadata embedding based on an easy plugin architecture
- * Multi-format support : FLAC, OGG, MP3, WAV and more
- * GEO Navigator for audio geolocalization
- * DublinCore compatibility
- * OAI-PMH data provider
- * XML serialized backup
- * Strong SQL backend
+ * Secure archiving, editing and publishing of audio files over internet.
+ * User friendly web frontend including workflows and high level search methods
+ * Smart dynamical and skinnable audio player (thanks to Timeside and soundmanager2)
+ * "On the fly" analyzing, transcoding and metadata embedding based on an easy plugin architecture
+ * Multi-format support : FLAC, OGG, MP3, WAV and more
+ * GEO Navigator for audio geolocalization
+ * DublinCore compatibility
+ * OAI-PMH data provider
+ * XML serialized backup
+ * Strong SQL backend
The Telemeta data model is based on 'collections' and 'items'. A collection is described
by its metadata and includes original audio items (sounds) and its own metadata. This
return hash.hexdigest()
def __get_media_filename(self, item):
- return item.id + ".wav"
+ return str(item.id) + ".wav"
def store(self, dest_dir):
"""Serialize and store the collection with related items and media
files into a subdirectory of the provided directory
"""
- coll_dir = dest_dir + "/" + self.collection.id
+ coll_dir = dest_dir + "/" + str(self.collection.id)
os.mkdir(coll_dir)
xml = self.get_xml()
coll_doc = self.collection.to_dom()
coll_node = doc.documentElement.appendChild(coll_doc.documentElement)
coll_doc.unlink()
- items_node_name = MediaItem.get_dom_element_name() + "List"
+ items_node_name = MediaItem.get_dom_name() + "List"
items_node = doc.createElement(items_node_name)
coll_node.appendChild(items_node)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2006-2010 Guillaume Pellerin
-
-# <yomguy@parisson.com>
+# Copyright (C) 2006-2010 Guillaume Pellerin, Parisson SARL
# This software is a computer program whose purpose is to stream audio
# and video data through icecast2 servers.
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
#
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
# knowledge of the CeCILL license and that you accept its terms.
#
# Authors: Olivier Guilyardi <olivier@samalyse.com>
+# Guillaume Pellerin <yomguy@parisson.com>
__all__ = ['ModelCore', 'MetaCore', 'DurationField', 'Duration', 'WeakForeignKey',
'EnhancedModel', 'CharField', 'TextField', 'IntegerField', 'BooleanField',
# -*- coding: utf-8 -*-
# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
#
# Authors: Olivier Guilyardi <olivier@samalyse.com>
# David LIPSZYC <davidlipszyc@gmail.com>
+# Guillaume Pellerin <yomguy@parisson.com>
from telemeta.models.core import *
from django.utils.translation import ugettext_lazy as _
# -*- coding: utf-8 -*-
# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
#
# Authors: Olivier Guilyardi <olivier@samalyse.com>
# David LIPSZYC <davidlipszyc@gmail.com>
+# Guillaume Pellerin <yomguy@parisson.com>
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
if value:
if key == 'date':
value = value.split(';')[0].split('=')
- print value
if len(value) > 1:
value = value[1]
value = value.split('-')[0]
# -*- coding: utf-8 -*-
# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
#
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
#
# Authors: Olivier Guilyardi <olivier@samalyse.com>
# David LIPSZYC <davidlipszyc@gmail.com>
+# Guillaume Pellerin <yomguy@parisson.com>
from django.db.models import Q, Max, Min
from telemeta.models.core import *
# -*- coding: utf-8 -*-
# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
#
# Authors: Olivier Guilyardi <olivier@samalyse.com>
# David LIPSZYC <davidlipszyc@gmail.com>
+# Guillaume Pellerin <yomguy@parisson.com>
from django.contrib.auth.models import User
from telemeta.models.core import *
Introduction
==============
-Telemeta est un système de gestion d'archives sonores. Cette plateforme a été conçue par le CREM et Parisson pour satisfaire les besoins de valorisation des archives audio des laboratoires de recherche mais aussi pour permettre aux chercheurs et aux documentalistes de collaborer autour d'un outil commun en réseau.
-
-
+Telemeta est un système de gestion collaborative d'archives sonores. Il a été conçue par le Centre de Recherche en Ethnomusicologie et la société Parisson pour satisfaire les besoins de valorisation des archives audio des laboratoires de recherche mais aussi pour permettre aux chercheurs et aux documentalistes d'indéxer mutuellement les fonds d'archives.
Prise en main
================
+
-----------
Connexion
-----------
{% dl_field collection "metadata_author" %}
{% dl_field collection "booklet_description" %}
{% dl_field collection "publishing_status" %}
- <!-- FIXME: alt_ids unsupported
{% dl_field collection "alt_ids" %}
- -->
{% dl_field collection "comment" %}
{% dl_field collection "metadata_writer" %}
{% dl_field collection "travail" %}
{% block content %}
<table class="listing">
-<tr>
- <th>{% trans "Country" %}</th>
- <th>{% trans "Number of collections" %}</th>
- <th>{% trans "Number of items" %}</th>
-</tr>
-{% for country in countries %}
-<tr>
- <td>{{ country }}</td>
- <td>
- {% with country.collections.count as num %}
- <a href="{% url telemeta-geo-country-collections continent.flatname,country.flatname %}">
- {% blocktrans count num as counter %}1 collection{% plural %}{{ counter }} collections{% endblocktrans %}
- </a>
- {% endwith %}
- </td>
- <td>
- {% with country.items.count as num %}
- <a href="{% url telemeta-geo-country-items continent.flatname,country.flatname %}">
- {% blocktrans count num as counter %}1 item{% plural %}{{ counter }} items {% endblocktrans %}
- </a>
- {% endwith %}
- </td>
-</tr>
+ <tr>
+ <th>{% trans "Country" %}</th>
+ <th>{% trans "Number of collections" %}</th>
+ <th>{% trans "Number of items" %}</th>
+ </tr>
+ {% for country in countries %}
+ <tr>
+ <td>{{ country }}</td>
+ <td>
+ {% with country.collections.count as num %}
+ <a href="{% url telemeta-geo-country-collections continent.flatname,country.flatname %}">
+ {% blocktrans count num as counter %}1 collection{% plural %}{{ counter }} collections{% endblocktrans %}
+ </a>
+ {% endwith %}
+ </td>
+ <td>
+ {% with country.items.count as num %}
+ <a href="{% url telemeta-geo-country-items continent.flatname,country.flatname %}">
+ {% blocktrans count num as counter %}1 item{% plural %}{{ counter }} items {% endblocktrans %}
+ </a>
+ {% endwith %}
+ </td>
+ </tr>
{% endfor %}
</table>
{% endblock %}
</script>
{% endblock %}
-
{% block content %}
-
<div class="module-set" style="width: 33%">
{% block modules %}
{% include "telemeta/inc/module_revisions.html" %}
{% endblock %}
</div>
-
<div class="home-description">
<h1><img src="{% url telemeta-images "playlist_title.png" %}" style="vertical-align:middle" /> {% trans "Playlists" %}</h1>
<a href=# id="_new_playlist" style="float:right" class="component_icon button icon_add">
</tr>
{% endif %}
</table>
-
<table class="listing" width="100%">
<tr>
<th class="highlight">{% trans "Title" %}</th>
<th>{% trans "Sound" %}</th>
<th>{% trans "Action" %}</th>
</tr>
-
{% for resource in playlist.resources %}
<tr {% if not forloop.counter0|divisibleby:"2" %}class="odd"{% endif %}>
<td>
</table>
{% endfor %}
</div>
-
{% endblock %}
{% endif %}
</dd>
{% endfor %}
-
</dl>
{% block content %}
<div class="home-content">
-
<div class="module-set">
{% block modules %}
{% include "telemeta/inc/module_revisions.html" %}
-<!--
-{{ block.super }}
-<div id="module" class="module">
- <h3><img src="{% url telemeta-images "module_playlist.png" %}" style="vertical-align:middle" />
- {% trans "Partenaires" %}</h3>
- <img class="image-link" src="http://files.parisson.com/img/logos/logo-CNRS.png">
- <img class="image-link" src="http://files.parisson.com/img/logos/logo_mcc_2.png">
- <img class="image-link" src="http://files.parisson.com/img/logos/mnhn.gif">
-</div>
--->
-
{% endblock %}
</div>
{% block tabcontents %}
<h4>{% trans "Instruments" %}</h4>
-
<form class="addnew" id="_addinstru" method="POST"
action="{% url telemeta-instrument-add %}">{% csrf_token %}
<fieldset>
{% block tabcontents %}
<h4>{% trans "Instruments" %}</h4>
-
<form class="mod" id="addinstru" method="post"
action="{% url telemeta-instrument-record-update instrument.id %}">{% csrf_token %}
<fieldset>
</fieldset>
</form>
<br style="clear: right"/>
-
{% endblock %}
{% endblock %}
{% block content %}
-
{% if form.errors %}
<p class="login-error">{% trans "Your username and password didn't match. Please try again." %}</p>
{% endif %}
-
<form class="login" id="_loginForm" method="post" action="{% url telemeta-login %}">{% csrf_token %}
<p>
{{ form.username.label_tag }}
{{ form.username }}<br />
-
{{ form.password.label_tag }}
{{ form.password }}
-
</p>
<a href="#" class="component_icon button icon_login" style="float: right;"
onclick="document.getElementById('_loginForm').submit(); return false;">{% trans "Sign in" %}</a>
<input type="hidden" name="next" value="{{ next }}" />
<span style="align: right;"><a href="{% url telemeta-password-reset %}">{% trans "Password forgotten" %} ?</a></span>
</form>
-
-
{% endblock %}
</div>
</div>
<div>
- <span style="font-size:70%; float:left">{% organization %} - Item : <a href="{% url telemeta-item-detail item.public_id %}">{% if item.code %}{{ item.code }}{% else %}{{ item.old_code }}{% endif %}</a></span>
- <span style="font-size:70%; float:right"><a href="http://telemeta.org">Telemeta</a> powered</span>
+ <span style="font-size:70%; float:left">{% organization %} - Item : <a href="{% url telemeta-item-detail item.public_id %}" target="_blank">{% if item.code %}{{ item.code }}{% else %}{{ item.old_code }}{% endif %}</a></span>
+ <span style="font-size:70%; float:right"><a href="http://telemeta.org" target="_blank">Telemeta</a> powered</span>
</div>
</div>
{% endif %}
{% endblock %}
{% block content %}
- <div class="infos" style="padding-top: 1em;">
-
- <form method="POST" id="_editUserProfileForm" action="">{% csrf_token %}
- <table>
- {% for form in forms %}
- {% for field in form %}
- {% if not field.html_name in user_hidden_fields %}
- <tr>
- <tr><td class="error">{{ field.errors }}</td></tr>
- <td>{% trans field.label_tag %} : </td><td>{{ field }}</td>
- </tr>
- {% else %}
- <tr>
- <td>{{ field.label_tag.as_hidden }}</td><td>{{ field.as_hidden }}</td>
- </tr>
- {% endif %}
+ <div class="infos" style="padding-top: 1em;">
+ <form method="POST" id="_editUserProfileForm" action="">{% csrf_token %}
+ <table>
+ {% for form in forms %}
+ {% for field in form %}
+ {% if not field.html_name in user_hidden_fields %}
+ <tr>
+ <tr><td class="error">{{ field.errors }}</td></tr>
+ <td>{% trans field.label_tag %} : </td><td>{{ field }}</td>
+ </tr>
+ {% else %}
+ <tr>
+ <td>{{ field.label_tag.as_hidden }}</td><td>{{ field.as_hidden }}</td>
+ </tr>
+ {% endif %}
+ {% endfor %}
{% endfor %}
- {% endfor %}
- </table>
+ </table>
<div align="center">
<a href="{% url telemeta-profile-detail usr.username %}" class="component_icon button icon_cancel">{% trans "Cancel" %}</a>
<a href="#" class="component_icon button icon_save"
onclick="document.getElementById('_editUserProfileForm').submit(); return false;">{% trans "Save" %}</a>
</div>
- </form>
-
- </div>
+ </form>
+ </div>
{% endblock %}
{% block title %}<br />{% trans 'Password reset complete' %}{% endblock %}
{% block content %}
-
<p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>
-
<p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>
-
{% endblock %}
{% block title %}<br />{% trans 'Password reset' %}{% endblock %}
{% block content %}
-
{% if validlink %}
-
<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
<form id="password_confirm" action="" method="post">{% csrf_token %}
</form>
{% else %}
-
<h1>{% trans 'Password reset unsuccessful' %}</h1>
-
<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
{% endif %}
-
{% endblock %}
{% block title %}<br />{% trans 'Password reset successful' %}{% endblock %}
{% block content %}
-
<p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p>
-
{% endblock %}
{% block title %}<br />{% trans "Password reset" %}{% endblock %}
{% block content %}
-
<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
<form id="password_reset" action="" method="post">{% csrf_token %}
{{ form.email.errors }}
<p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <a href="#" class="component_icon button icon_ok" onclick="document.getElementById('password_reset').submit(); return false;">{% trans 'Reset my password' %}</a></p>
</form>
-
{% endblock %}
# -*- coding: utf-8 -*-
# Copyright (C) 2007 Samalyse SARL
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+# Copyright (c) 2007-2011 Parisson SARL
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
#
-# Author: Olivier Guilyardi <olivier@samalyse.com>
+# Authors: Olivier Guilyardi <olivier@samalyse.com>
+# Guillaume Pellerin <yomguy@parisson.com>
from django.conf.urls.defaults import *
from telemeta.models import MediaItem, MediaCollection, MediaItemMarker
# -*- coding: utf-8 -*-
-# Copyright (C) 2007 Samalyse SARL
+# Copyright (C) 2007-2010 Samalyse SARL
+# Copyright (C) 2010-2011 Parisson SARL
# This software is a computer program whose purpose is to backup, analyse,
# transcode and stream any audio content with its metadata over a web frontend.
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
-# Author: Olivier Guilyardi <olivier@samalyse.com>
+# Authors: Olivier Guilyardi <olivier@samalyse.com>
+# Guillaume Pellerin <yomguy@parisson.com>
import re
import os
})
def get_public_access(self, access, date_from, date_to):
- # Rolling publishing date : Public access when time between recorded year
- # and currant year is over settings value PUBLIC_ACCESS_PERIOD
+ # Rolling publishing date : public access is given when time between recorded year
+ # and current year is over the settings value PUBLIC_ACCESS_PERIOD
if date_to:
date = date_to
elif date_from:
graph = grapher(width = int(width), height = int(height))
pipe = decoder | graph
pipe.run()
-# graph.watermark('telemeta', opacity=.6, margin=(5,5))
+ graph.watermark('telemeta', opacity=.6, margin=(5,5))
f = open(path, 'w')
graph.render(path)
f.close()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2011 Guillaume Pellerin
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://svn.parisson.org/telemeta/TelemetaLicense.
+#
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+#
+
+import os
+import sys
+import xlrd
+import logging
+import datetime
+from django.core.management import setup_environ
+from django.core.files.base import ContentFile
+
+class Logger:
+
+ def __init__(self, file):
+ self.logger = logging.getLogger('myapp')
+ self.hdlr = logging.FileHandler(file)
+ self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+ self.hdlr.setFormatter(self.formatter)
+ self.logger.addHandler(self.hdlr)
+ self.logger.setLevel(logging.INFO)
+
+ def write_info(self, prefix, message):
+ self.logger.info(' ' + prefix + ' : ' + message.decode('utf8'))
+
+ def write_error(self, prefix, message):
+ self.logger.error(prefix + ' : ' + message.decode('utf8'))
+
+
+class TelemetaAltIdsImport:
+
+ def __init__(self, xls_file, log_file):
+ self.logger = Logger(log_file)
+ self.xls = xls_file
+ self.row = 0
+
+ def alt_ids_import(self):
+ from telemeta.models import MediaCollection
+ self.book = xlrd.open_workbook(self.xls)
+ self.sheet = self.book.sheet_by_index(0)
+ self.length = len(self.sheet.col(0))-1
+
+ while True:
+ ids = []
+ self.row += 1
+ row = self.sheet.row(self.row)
+ if self.row == self.length:
+ break
+ collection_id = row[0].value
+ cell_alt_id = row[1]
+ if cell_alt_id.ctype == 1:
+ for i in range(1,len(row)):
+ cell_alt_id = row[i]
+ if cell_alt_id.ctype == 1:
+ ids.append(cell_alt_id.value)
+ alt_ids = ' '.join(ids)
+ try:
+ collection = MediaCollection.objects.get(old_code=collection_id)
+ collection.alt_ids = alt_ids
+ collection.save()
+ print self.row, collection_id, alt_ids
+ except:
+ msg = 'No collection found for this id'
+ self.logger.write_error(collection_id, msg)
+ continue
+
+
+def print_usage(tool_name):
+ print "Usage: "+tool_name+" <project_dir> <xls_file> <log_file>"
+ print " project_dir: the directory of the Django project which hosts Telemeta"
+ print " xls_file: the excel file containing all collection alt_ids"
+
+def run():
+ if len(sys.argv) < 3:
+ print_usage(os.path.basename(sys.argv[0]))
+ sys.exit(1)
+ else:
+ project_dir = sys.argv[-3]
+ xls_file = sys.argv[-2]
+ log_file = sys.argv[-1]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ t = TelemetaAltIdsImport(xls_file, log_file)
+ t.alt_ids_import()
+
+if __name__ == '__main__':
+ run()