--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Vérifier que les nouvelles cotes d'item :
+
+- correspondent toutes à la collection décrite par le fichier .csv
+ (le fichier .csv est nommé d'après la nouvelle cote de collection)
+
+- sont uniques dans le fichiers .csv
+
+- ont un des formats suivant :
+ - soit CNRSMH_I_aaaa_nnn_mmm
+ - soit CNRSMH_I_aaaa_nnn_mmm_tt
+ - soit CNRSMH_I_aaaa_nnn_mmm_tt_pp
+ - soit CNRSMH_E_aaaa_nnn_mmm_tt
+ - soit CNRSMH_E_aaaa_nnn_mmm_tt_pp
+
+- correspondent à fichier .wav (et qu'il n'y a pas de fichiers .wav
+ supplémentaire)
+
+Vérifier que le répertoire est nommé d'apprès la nouvelle cote de collection
+
+Vérifier que la nouvelle cote de collection a l'un des formats suivant :
+ - soit CNRSMH_I_aaaa_nnn
+ - soit CNRSMH_E_aaaa_nnn_mmm
+
+Vérifier que les fichiers .wav sont lisibles, ont une durée et sont identifés
+comme WAV par audiolab.
+"""
+
+
+import os
+import re
+import sys
+import csv
+import xlrd
+import datetime
+import logging
+import shutil
+
+COLLECTION_OLD_PATTERN = [
+ { 'format': 'BM.aaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'},
+ { 'format': 'BM.aaaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'BM.aaaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
+ { 'format': 'BM.aaaa.nnn.mmm/', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/$'},
+ { 'format': 'BM.aaaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'},
+ { 'format': 'BM.aaaa.nnn.mm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{2})/[0-9]{2}$'},
+ { 'format': 'BM.aaaa.nnn', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})$'},
+ { 'format': 'BM.aaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'BM.aaa.nnn FANTOME', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3}) FANTOME$'},
+ { 'format': 'BM.aaa.nnn', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})$'},
+ { 'format': 'BM.aaa.nnnBISoo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})BIS([0-9]{2})/[0-9]{2}$'},
+ { 'format': 'BM.aaa.nnn.mmm.ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})\.[0-9]{3}$'},
+ { 'format': 'BM.aaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'},
+ { 'format': 'BM.aaa.nnn/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'BM.aaa.nnn-BIS.ooo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})-BIS\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'BM.aaaa.nnn.mmm/NN', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/NN$'},
+ { 'format': 'BM.aaa.nnn.mmm/pp-DEPOT', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}-DEPOT$'},
+ { 'format': 'BM.aaa.nnn.mmm-o>p', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]>[0-9]$'},
+ { 'format': 'CY.aaaa.nnn', 'regex': r'^(CY)\.([0-9]{4})\.([0-9]{3})$'},
+ { 'format': 'DI.aaaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
+ { 'format': 'DI.aaaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'DI.aaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'},
+ { 'format': 'DI.aaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
+ { 'format': 'DI.aaa.nnn.mmm-o/p', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]/[0-9]$'},
+ { 'format': 'FANTOME 2*', 'regex': r'FANTOME 2\*$'},
+
+ ## yomguy
+ { 'format': 'BM.aaaa.nnn.mm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
+ #{ 'format': 'BM.aaaa.nnn.mmm/pp:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/([0-9]{2})\:([0-9]{2})\-([0-9]{2})$'},
+ #{ 'format': 'BM.aaaa.nnn.mmm/ppp:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/([0-9]{2})\:([0-9]{2})\-([0-9]{2})$'},
+ #{ 'format': 'BM.aaaa.nnn.mmm:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3}):([0-9]{2})\-([0-9]{2})$'},
+ ]
+
+ITEM_NEW_PATTERN = [
+ { 'format': 'CNRSMH_I_aaaa_nnn_mmm', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})$'},
+ { 'format': 'CNRSMH_I_aaaa_nnn_mmm_tt', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})$'},
+ { 'format': 'CNRSMH_I_aaaa_nnn_mmm_tt_pp', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})_([0-9]{2})$'},
+ { 'format': 'CNRSMH_E_aaaa_nnn_mmm_tt', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})$'},
+ { 'format': 'CNRSMH_E_aaaa_nnn_mmm_tt_pp', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2,3})_([0-9]{2})$'},
+
+ # yomguy
+ { 'format': 'CNRSMH_I_aaaa_nnn_mm', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{2})$'},
+ ]
+
+COLLECTION_PATTERN = [
+ { 'format': 'CNRSMH_I_aaaa_nnn', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})$'},
+ { 'format': 'CNRSMH_E_aaaa_nnn_mmm', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})$'},
+ ]
+
+
+def check_name(patterns, name):
+ match = False
+ for pattern in patterns:
+ match = re.match(pattern['regex'], name)
+ if match:
+ break
+ return match
+
+
+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 CremCollection:
+
+ def __init__(self, dir, logger):
+ self.dir = dir
+ self.dir_name = self.dir.split(os.sep)[-1]
+ self.file_list = os.listdir(self.dir)
+ self.logger = logger
+
+ def xls_list(self):
+ file_list = []
+ for file in self.file_list:
+ filename = os.path.basename(file)
+ ext = os.path.splitext(file)[1]
+ if not '.' == filename[0] and (ext == '.xls' or ext == '.XLS'):
+ file_list.append(file)
+ print file_list
+ return file_list
+
+ def wav_list(self):
+ list = []
+ for file in self.file_list:
+ filename = os.path.basename(file)
+ ext = os.path.splitext(file)[1]
+ if not '.' == filename[0] and (ext == '.wav' or ext == '.WAV'):
+ list.append(file)
+ elif '.' == filename[0]:
+ self.logger.write_error(file, 'Warning : fichier caché présent !')
+ return list
+
+
+class CremCSV:
+
+ def __init__(self, file):
+ self.csv_file = open(file, 'w')
+ self.csv = csv.writer(self.csv_file, delimiter=';')
+
+ def close(self):
+ self.csv_file.close()
+
+class CremXLS:
+
+ def __init__(self, file):
+ self.first_row = 8
+ self.original_col = 0
+ self.new_col = 1
+ self.book = xlrd.open_workbook(file)
+ self.sheet = self.book.sheet_by_index(0)
+ self.original_refs = self.original_refs()
+ self.new_refs = self.new_refs()
+ #print len(self.new_refs)
+ while True:
+ if len(self.original_refs) == 0 or len(self.new_refs) == 0:
+ break
+ else:
+ if not 'CNRS' in self.new_refs[0].encode('utf8') \
+ and not self.original_refs[0].encode('utf8') == '':
+ self.original_refs = self.original_refs[1:]
+ self.new_refs = self.new_refs[1:]
+ else:
+ break
+
+ self.size = max(len(self.new_refs), len(self.original_refs))
+
+ def original_refs(self):
+ col = self.sheet.col(self.original_col)
+ list = []
+ for cell in col[self.first_row:]:
+ if cell.ctype == 1:
+ list.append(cell.value)
+ return list
+
+ def new_refs(self):
+ col = self.sheet.col(self.new_col)
+ list = []
+ for cell in col[self.first_row:]:
+ if cell.ctype == 1:
+ list.append(cell.value)
+ return list
+
+
+class CremItemFile:
+
+ def __init__(self):
+ self.media = ''
+
+ def set_media(self, media):
+ self.media = media
+
+ def properties(self):
+ self.frames = self.audio_file.get_nframes()
+ self.samplerate = self.audio_file.get_samplerate()
+ self.channels = self.audio_file.get_channels()
+ self.format = self.audio_file.get_file_format()
+ self.encoding = self.audio_file.get_encoding()
+
+
+class CremCheck:
+
+ def __init__(self, root_dir, log_file):
+ self.root_dir = root_dir
+ self.logger = Logger(log_file)
+ dir_list = os.listdir(self.root_dir)
+ list = []
+ for dir in dir_list:
+ if not dir[0] == '.':
+ list.append(dir)
+ self.dir_list = list
+
+ def check_new_refs(self):
+ for name in self.new_refs:
+ return check_name(ITEM_PATTERN, name)
+
+ def check(self):
+ for dir in self.dir_list:
+ collection = CremCollection(self.root_dir + dir, self.logger)
+ msg = '************************ ' + collection.dir_name + ' ******************************'
+ self.logger.write_info(collection.dir, msg[:70])
+
+ xls_list = collection.xls_list()
+ wav_list = collection.wav_list()
+
+ if not check_name(COLLECTION_PATTERN, dir):
+ self.logger.write_error(collection.dir, 'Le dossier de la collection est mal nommé -> SORTIE')
+ elif len(xls_list) == 0:
+ self.logger.write_error(collection.dir, 'PAS de fichier XLS dans le dossier collection -> SORTIE')
+ elif len(xls_list) > 1:
+ self.logger.write_error(collection.dir, 'Plusieurs fichiers XLS dans le dossier collection -> SORTIE')
+
+ else:
+ xls = CremXLS(self.root_dir + os.sep + dir + os.sep + xls_list[0])
+ self.logger.write_info(collection.dir, 'XLS : ' + xls_list[0] + ' - Feuille : ' + xls.sheet.name.encode('utf8'))
+ self.logger.write_info(collection.dir, 'Nombre d\'items détectés : ' + str(xls.size))
+ csv_file = CremCSV(self.root_dir + dir + os.sep + collection.dir_name + '.csv')
+
+ if len(wav_list) != xls.size:
+ self.logger.write_error(collection.dir, \
+ 'Le nombre de références du fichier XLS (' + str(xls.size) + ') diffère du nombre de fichiers (' + str(len(wav_list)) + ')')
+
+ temp_list = []
+ item_file = CremItemFile()
+
+ for i in range(0,xls.size):
+ error = False
+
+ try:
+ item_old = xls.original_refs[i]
+ #self.logger.write_error(collection.dir, item_old)
+ except:
+ item_old = ''
+ msg = 'Ligne ' + str(i+xls.first_row+1) + ' : l\'ancienne référence d\'item est inexistante'
+ self.logger.write_error(collection.dir, msg)
+ error = True
+ continue
+
+ try:
+ item = xls.new_refs[i]
+ #self.logger.write_error(collection.dir, item)
+ except:
+ item = ''
+ msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la nouvelle référence d\'item est inexistante'
+ self.logger.write_error(collection.dir, msg)
+ error = True
+ continue
+
+ if not item in temp_list:
+ temp_list.append(item)
+ else:
+ msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la référence d\'item ' + item.encode('utf8') + ' est multiple'
+ self.logger.write_error(collection.dir, msg)
+ error = True
+
+ #if not check_name(ITEM_OLD_PATTERN, item_old):
+ #msg = 'Ligne ' + str(i+xls.first_row+1) + ' : l\'ancienne référence d\'item ' + item_old.encode('utf8') + ' est mal formatée'
+ #self.logger.write_error(collection.dir, msg)
+
+ if not check_name(ITEM_NEW_PATTERN, item):
+ msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la nouvelle référence d\'item ' + item.encode('utf8') + ' est mal formatée'
+ self.logger.write_error(collection.dir, msg)
+ error = True
+
+ if not collection.dir_name in item:
+ msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la référence d\'item ' + item.encode('utf8') + ' ne correspond pas à celle de la collection'
+ self.logger.write_error(collection.dir, msg)
+ error = True
+
+ name_wav = item.encode('utf8') + '.wav'
+ if not name_wav in wav_list:
+ self.logger.write_error(collection.dir, 'Le fichier ' + item.encode('utf8') + '.wav n\'existe pas')
+ else:
+ item_file.set_media(collection.dir + os.sep + name_wav)
+ #if not item_file.is_wav():
+ # self.logger.write_error(collection.dir, 'Le fichier ' + item.encode('utf8') + '.wav n\'est pas valide')
+ # error = True
+
+ if not error:
+ csv_file.csv.writerow([xls.original_refs[i], xls.new_refs[i]])
+
+ csv_file.close()
+
+ for filename in wav_list:
+ if not check_name(ITEM_NEW_PATTERN, os.path.splitext(filename)[0]):
+ self.logger.write_error(collection.dir, 'Le nom du fichier ' + str(os.path.splitext(filename)[0]) + ' est mal formaté')
+
+ msg = '********************************************************************************'
+ self.logger.write_info(collection.dir, msg[:70])
+
+
+def main():
+ log_file = sys.argv[-1]
+ root_dir = sys.argv[-2]
+ log_tmp = log_file+'.tmp'
+
+ c = CremCheck(root_dir, log_tmp)
+ c.check()
+
+ date = datetime.datetime.now().strftime("%x-%X").replace('/','_')
+ shutil.copy(log_tmp,log_file+'-'+date+'.log')
+ shutil.move(log_tmp,log_file)
+
+if __name__ == '__main__':
+ main()
+
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+# for python2.5
+
+version = '0.5'
+
+
+import os
+import sys
+import time
+import shutil
+import datetime
+import timeside
+
+# soon with python2.6
+#from multiprocessing import Process
+
+from django.core.management import setup_environ
+from django.core.files.base import ContentFile
+import cgi
+fs = cgi.FieldStorage()
+
+
+orig_media_dir = '/mnt/awdiomusic/musicbase'
+project_dir = '/mnt/awdio'
+log_file = project_dir + '/logs/process.log'
+sys.path.append('/home/awdio/apps/telemeta-awdio')
+
+
+class GrapherScheme:
+
+ def __init__(self):
+ self.color = 255
+ self.color_scheme = {
+ 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
+ (self.color,self.color,self.color)
+# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
+ ],
+ 'spectrogram': [
+ (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
+ ]}
+
+ # Grapher id
+ self.id = 'waveform_awdio'
+
+ # Width of the image
+ self.width = 1800
+
+ # Height of the image
+ self.height = 233
+
+ # Background color
+ self.bg_color = None
+
+ # Force computation. By default, the class doesn't overwrite existing image files.
+ self.force = False
+
+ # Nb of threads
+ # FIXME: memory leak for > 1 !
+ self.threads = 1
+
+
+class TelemetaPreprocessImport(object):
+
+ def __init__(self, root_dir, dest_dir, log_file):
+ from telemeta.cache import TelemetaCache as Cache
+ from telemeta.util.logger import Logger
+ self.media_item_dir = 'items'
+ self.root_dir = root_dir + 'items'
+ self.dest_dir = dest_dir
+ self.threads = 1
+ self.logger = Logger(log_file)
+ self.counter = 0
+ self.force = 0
+ self.cache = Cache(self.dest_dir)
+
+ self.scheme = GrapherScheme()
+ self.width = self.scheme.width
+ self.height = self.scheme.height
+ self.bg_color = self.scheme.bg_color
+ self.color_scheme = self.scheme.color_scheme
+ self.force = self.scheme.force
+ self.threads = self.scheme.threads
+ self.logger = Logger(log_file)
+ self.counter = 0
+ self.collection_name = 'awdio'
+ self.collection = self.set_collection(self.collection_name)
+
+ self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
+ self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
+ height=self.height,
+ bg_color=self.bg_color,
+ color_scheme=self.color_scheme)
+
+
+ def set_collection(self, collection_name):
+ import telemeta.models
+ collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
+ if not collections:
+ c = telemeta.models.media.MediaCollection(code=collection_name)
+ c.title = collection_name
+ c.save()
+ msg = 'added'
+ self.logger.logger.info(collection_name, msg)
+ collection = c
+ else:
+ collection = collections[0]
+ return collection
+
+ def process(self):
+ import telemeta.models
+ keys = fs.keys()
+ if keys[0] == 'file':
+ filename = fs['file'].value
+ media_orig = orig_media_dir + os.sep + filename
+ media = self.root_dir + os.sep + filename
+
+ if not os.path.exists(media):
+ shutil.copy(media_orig, media)
+ os.system('chmod 644 ' + media)
+
+ name, ext = os.path.splitext(filename)
+ size = str(self.width) + '_' + str(self.height)
+ image_name = name + '.' + self.scheme.id + '.' + size + '.png'
+ image = self.dest_dir + os.sep + image_name
+ xml = name + '.xml'
+
+ if not self.cache.exists(image_name) or not self.cache.exists(xml):
+ mess = 'Processing ' + media
+ self.logger.logger.info(mess)
+
+ print "Content-type: text/plain\n"
+ print mess
+ decoder = timeside.decoder.FileDecoder(media)
+ pipe = decoder | self.grapher
+ analyzers = []
+ analyzers_sub = []
+ for analyzer in self.analyzers:
+ subpipe = analyzer()
+ analyzers_sub.append(subpipe)
+ pipe = pipe | subpipe
+ pipe.run()
+
+ mess = 'Rendering ' + image
+ self.logger.logger.info(mess)
+ self.grapher.render(output=image)
+
+ mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
+ self.logger.logger.info(mess)
+
+ for analyzer in analyzers_sub:
+ value = analyzer.result()
+ if analyzer.id() == 'duration':
+ 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, xml)
+
+ item = telemeta.models.media.MediaItem.objects.filter(code=name)
+
+ if not item:
+ item = telemeta.models.media.MediaItem(collection=self.collection, code=name)
+ item.title = name
+ item.file = self.media_item_dir + os.sep + filename
+ item.save()
+ msg = 'added item : ' + filename
+ self.logger.logger.info(self.collection_name, msg)
+
+ pipe = 0
+ decoder = 0
+
+ print "OK"
+
+ #except:
+ #pipe = 0
+ #decoder = 0
+ #mess = 'Could NOT process : ' + media
+ #self.logger.logger.error(mess)
+ #print mess
+
+ else:
+ mess = "Nothing to do with file : " + media
+ self.logger.logger.info(mess)
+ print "Content-type: text/plain\n"
+ print mess
+
+ else:
+ print "Content-type: text/plain\n"
+ print "No file given !"
+
+
+if __name__ == '__main__':
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ media_dir = settings.MEDIA_ROOT
+ data_dir = settings.TELEMETA_DATA_CACHE_DIR
+ t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
+ t.process()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007 Samalyse 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.
+
+# This software is governed by the CeCILL license under French law and
+# abiding by the rules of distribution of free software. You can use,
+# modify and/ or redistribute the software under the terms of the CeCILL
+# license as circulated by CEA, CNRS and INRIA at the following URL
+# "http://www.cecill.info".
+
+# As a counterpart to the access to the source code and rights to copy,
+# modify and redistribute granted by the license, users are provided only
+# with a limited warranty and the software's author, the holder of the
+# economic rights, and the successive licensors have only limited
+# liability.
+
+# In this respect, the user's attention is drawn to the risks associated
+# with loading, using, modifying and/or developing or reproducing the
+# software by the user in light of its specific status of free software,
+# that may mean that it is complicated to manipulate, and that also
+# therefore means that it is reserved for developers and experienced
+# professionals having in-depth computer knowledge. Users are therefore
+# encouraged to load and test the software's suitability as regards their
+# requirements in conditions enabling the security of their systems and/or
+# data to be ensured and, more generally, to use and operate it in the
+# same conditions as regards security.
+
+# 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>
+
+import os
+import sys
+import time
+from django.core.management import setup_environ
+
+def print_usage(toolname):
+ print "Usage: " + toolname + " <project_dir> <backup_dir>"
+ print " project_dir: the directory of the Django project which hosts Telemeta"
+ print " backup_dir: the destination backup folder (must exist)"
+
+def write_readme(dest_dir, coll_num):
+ readme = open(dest_dir + "/" + "README", "w")
+ timestr = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
+ readme.write("Telemeta Backup\n\n")
+ readme.write("- date: " + timestr + "\n")
+ readme.write("- number of collections: " + str(coll_num) + "\n\n")
+ readme.close()
+
+def backup(dest_dir):
+ from telemeta.models import MediaCollection
+ from telemeta.backup import CollectionSerializer
+
+ collections = MediaCollection.objects.order_by('id')
+ count = collections.count()
+
+ print "Writing README file..",
+ write_readme(dest_dir, count)
+ print "Done."
+
+ i = 0
+ for collection in collections:
+ if i % 100 == 0:
+ set_dir = dest_dir + ("/collections-%d-%d" % (i+1, i+100))
+ os.mkdir(set_dir)
+ i += 1
+ print "Processing collection %d/%d (%d%%) with id: %s.. " \
+ % (i, count, i*100/count, collection.id),
+ sys.stdout.flush()
+ serializer = CollectionSerializer(collection)
+ serializer.backup(set_dir)
+ print "Done"
+
+def run():
+ if len(sys.argv) != 3:
+ print_usage(os.path.basename(sys.argv[0]))
+ sys.exit(1)
+ else:
+ project_dir = sys.argv[1]
+ backup_dir = sys.argv[2]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ backup(backup_dir)
+
+if __name__ == '__main__':
+ run()
--- /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()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 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 csv
+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 info(self, prefix, message):
+ self.logger.info(' ' + prefix + ' : ' + message.decode('utf8'))
+
+ def error(self, prefix, message):
+ self.logger.error(prefix + ' : ' + message.decode('utf8'))
+
+
+class TelemetaWavImport:
+
+ def __init__(self, source_dir, log_file, pattern, domain):
+ from django.contrib.auth.models import User
+ self.logger = Logger(log_file)
+ self.source_dir = source_dir
+ self.collections = os.listdir(self.source_dir)
+ self.pattern = pattern
+ self.user = User.objects.filter(username='admin')[0]
+ self.domain = domain
+
+ def write_file(self, item, wav_file, overwrite=False):
+ filename = wav_file.split(os.sep)[-1]
+ if os.path.exists(wav_file):
+ if not item.file or overwrite:
+# f = open(wav_file, 'r')
+# file_content = ContentFile(f.read())
+# item.file.save(filename, file_content)
+# f.close()
+ item.save()
+ item.set_revision(self.user)
+ else:
+ msg = item.code + ' : fichier ' + item.file.name + ' deja inscrit dans la base de donnees !'
+ self.logger.error('item', msg)
+ else:
+ msg = item.code + ' : fichier audio ' + filename + ' inexistant dans le dossier !'
+ self.logger.error('item', msg)
+
+ def wav_import(self):
+ from telemeta.models import MediaItem, MediaCollection
+
+ collections = []
+ for collection in self.collections:
+ collection_dir = self.source_dir + os.sep + collection
+ collection_files = os.listdir(collection_dir)
+
+
+ if not '/.' in collection_dir and self.pattern in collection_dir:
+ collection_name = collection.split(os.sep)[-1]
+ collections.append(collection_name)
+ c = MediaCollection.objects.filter(code=collection_name)
+
+ if not c and collection + '.csv' in collection_files:
+ msg = collection + ' collection NON présente dans la base de données, SORTIE '
+ self.logger.error(collection, msg)
+ sys.exit(msg)
+ elif not c:
+ msg = 'collection NON présente dans la base de données, CREATION '
+ self.logger.info(collection, msg)
+ c = MediaCollection(code=collection_name)
+ c.save()
+ c.set_revision(self.user)
+ else:
+ msg = 'collection présente dans la base de données, SELECTION'
+ self.logger.info(collection, msg)
+
+ for collection in collections:
+ collection_dir = self.source_dir + os.sep + collection
+ collection_name = collection
+ collection_files = os.listdir(collection_dir)
+ msg = '************************ ' + collection + ' ******************************'
+ self.logger.info(collection, msg[:70])
+ overwrite = True
+ csv_file = ''
+ rows = {}
+
+ if collection + '.csv' in collection_files:
+ csv_file = self.source_dir + os.sep + collection + os.sep + collection + '.csv'
+ csv_data = csv.reader(open(csv_file), delimiter=';')
+ for row in csv_data:
+ rows[row[1].strip()] = row[0].strip()
+ msg = collection + ' import du fichier CSV de la collection'
+ self.logger.info(collection, msg[:70])
+ else:
+ msg = collection + ' pas de fichier CSV dans la collection'
+ self.logger.info(collection, msg[:70])
+
+ c = MediaCollection.objects.filter(code=collection_name)
+ if not c:
+ c = MediaCollection(code=collection_name)
+ c.save()
+ msg = ' collection NON présente dans la BDD, CREATION '
+ self.logger.info(c.code, msg)
+ else:
+ c = c[0]
+ msg = ' id = '+str(c.id)
+ self.logger.info(c.code, msg)
+
+ audio_files = []
+ for file in collection_files:
+ ext = ['WAV', 'wav']
+ if file.split('.')[-1] in ext:
+ audio_files.append(file)
+
+ audio_files.sort()
+ nb_items = c.items.count()
+ counter = 0
+
+ for file in audio_files:
+ code = file.split('.')[0]
+ wav_file = self.source_dir + os.sep + collection + os.sep + file
+
+ if len(audio_files) <= nb_items:
+ items = MediaItem.objects.filter(code=code)
+
+ old_ref = ''
+ if code in rows and not items:
+ old_ref = rows[code]
+ items = MediaItem.objects.filter(old_code=old_ref)
+
+ if items:
+ item = items[0]
+ msg = code + ' : ' + item.old_code + ' : Cas 1 ou 2 : id = ' + str(item.id)
+ self.logger.info('item', msg)
+ item.code = code
+ item.save()
+ else:
+ item = MediaItem(code=code, collection=c)
+ msg = code + ' : ' + old_ref + ' : Cas 1 ou 2 : item NON présent dans la base de données, CREATION'
+ self.logger.info('item', msg)
+
+ self.write_file(item, wav_file, overwrite)
+
+ elif nb_items == 1 and len(audio_files) > 1:
+ if counter == 0:
+ msg = code + ' : Cas 3a : item n°01 présent dans la base de données, PASSE'
+ self.logger.info('item', msg)
+ else:
+ item = MediaItem(code=code, collection=c)
+ msg = code + ' : Cas 3a : item NON présent dans la base de données, CREATION'
+ self.logger.info('item', msg)
+ self.write_file(item, wav_file, overwrite)
+
+ elif nb_items > 1 and nb_items < len(audio_files):
+ msg = code + ' : Cas 3b : nb items < nb de fichiers audio, PAS de creation'
+ self.logger.info('item', msg)
+
+ counter += 1
+
+ msg = 'Liste des URLs des collections importées :'
+ self.logger.info('INFO', msg)
+ for collection in collections:
+ msg = 'http://'+self.domain+'/collections/'+collection
+ self.logger.info(collection, msg)
+
+
+def print_usage(tool_name):
+ print "Usage: "+tool_name+" <project_dir> <source_dir> <pattern> <log_file> <domain>"
+ print " project_dir: the directory of the Django project which hosts Telemeta"
+ print " source_dir: the directory containing the wav files to include"
+ print " pattern: a pattern to match the collection names"
+ print " log_file: a log file to write logs"
+ print " domain: root domain for collections"
+
+def run():
+ if len(sys.argv) < 3:
+ print_usage(os.path.basename(sys.argv[0]))
+ sys.exit(1)
+ else:
+ project_dir = sys.argv[-5]
+ source_dir = sys.argv[-4]
+ pattern = sys.argv[-3]
+ log_file = sys.argv[-2]
+ url = sys.argv[-1]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ t = TelemetaWavImport(source_dir, log_file, pattern, url)
+ t.wav_import()
+
+if __name__ == '__main__':
+ run()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 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 csv
+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 info(self, prefix, message):
+ self.logger.info(' ' + prefix + ' : ' + message.decode('utf8'))
+
+ def error(self, prefix, message):
+ self.logger.error(prefix + ' : ' + message.decode('utf8'))
+
+
+class TelemetaWavImport:
+
+ def __init__(self, source_dir, log_file, pattern, domain):
+ from django.contrib.auth.models import User
+ self.logger = Logger(log_file)
+ self.source_dir = source_dir
+ self.collections = os.listdir(self.source_dir)
+ self.pattern = pattern
+ self.user = User.objects.filter(username='admin')[0]
+ self.domain = domain
+
+ def write_file(self, item, wav_file, overwrite=False):
+ filename = wav_file.split(os.sep)[-1]
+ if os.path.exists(wav_file):
+ if not item.file or overwrite:
+ f = open(wav_file, 'r')
+ file_content = ContentFile(f.read())
+ item.file.save(filename, file_content)
+ f.close()
+ item.save()
+ item.set_revision(self.user)
+ else:
+ msg = item.code + ' : fichier ' + item.file.name + ' deja inscrit dans la base de donnees !'
+ self.logger.error('item', msg)
+ else:
+ msg = item.code + ' : fichier audio ' + filename + ' inexistant dans le dossier !'
+ self.logger.error('item', msg)
+
+ def wav_import(self):
+ from telemeta.models import MediaItem, MediaCollection
+
+ collections = []
+ for collection in self.collections:
+ collection_dir = self.source_dir + os.sep + collection
+ collection_files = os.listdir(collection_dir)
+
+
+ if not '/.' in collection_dir and self.pattern in collection_dir:
+ collection_name = collection.split(os.sep)[-1]
+ collections.append(collection_name)
+ c = MediaCollection.objects.filter(code=collection_name)
+
+ if not c and collection + '.csv' in collection_files:
+ msg = collection + ' collection NON présente dans la base de données, SORTIE '
+ self.logger.error(collection, msg)
+ sys.exit(msg)
+ elif not c:
+ msg = 'collection NON présente dans la base de données, CREATION '
+ self.logger.info(collection, msg)
+ c = MediaCollection(code=collection_name, title=collection_name)
+ c.save()
+ c.set_revision(self.user)
+ else:
+ msg = 'collection présente dans la base de données, SELECTION'
+ self.logger.info(collection, msg)
+
+ for collection in collections:
+ collection_dir = self.source_dir + os.sep + collection
+ collection_name = collection
+ collection_files = os.listdir(collection_dir)
+ msg = '************************ ' + collection + ' ******************************'
+ self.logger.info(collection, msg[:70])
+ overwrite = True
+ csv_file = ''
+ rows = {}
+
+ if collection + '.csv' in collection_files:
+ csv_file = self.source_dir + os.sep + collection + os.sep + collection + '.csv'
+ csv_data = csv.reader(open(csv_file), delimiter=';')
+ for row in csv_data:
+ rows[row[1].strip()] = row[0].strip()
+ msg = collection + ' import du fichier CSV de la collection'
+ self.logger.info(collection, msg[:70])
+ else:
+ msg = collection + ' pas de fichier CSV dans la collection'
+ self.logger.info(collection, msg[:70])
+
+ c = MediaCollection.objects.filter(code=collection_name)
+ if not c:
+ c = MediaCollection(code=collection_name)
+ c.save()
+ msg = ' collection NON présente dans la BDD, CREATION '
+ self.logger.info(c.code, msg)
+ else:
+ c = c[0]
+ msg = ' id = '+str(c.id)
+ self.logger.info(c.code, msg)
+
+ audio_files = []
+ for file in collection_files:
+ ext = ['WAV', 'wav']
+ if file.split('.')[-1] in ext and file[0] != '.':
+ audio_files.append(file)
+
+ audio_files.sort()
+ nb_items = c.items.count()
+ counter = 0
+
+ for file in audio_files:
+ code = file.split('.')[0]
+ wav_file = self.source_dir + os.sep + collection + os.sep + file
+
+ if len(audio_files) <= nb_items:
+ items = MediaItem.objects.filter(code=code)
+
+ old_ref = ''
+ if code in rows and not items:
+ old_ref = rows[code]
+ items = MediaItem.objects.filter(old_code=old_ref)
+
+ if items:
+ item = items[0]
+ msg = code + ' : ' + item.old_code + ' : Cas 1 ou 2 : id = ' + str(item.id)
+ self.logger.info('item', msg)
+ item.code = code
+ item.save()
+ else:
+ item = MediaItem(code=code, collection=c)
+ msg = code + ' : ' + old_ref + ' : Cas 1 ou 2 : item NON présent dans la base de données, CREATION'
+ self.logger.info('item', msg)
+
+ self.write_file(item, wav_file, overwrite)
+
+ elif nb_items == 1 and len(audio_files) > 1:
+ if counter == 0:
+ msg = code + ' : Cas 3a : item n°01 présent dans la base de données, PASSE'
+ self.logger.info('item', msg)
+ else:
+ item = MediaItem(code=code, collection=c)
+ msg = code + ' : Cas 3a : item NON présent dans la base de données, CREATION'
+ self.logger.info('item', msg)
+ self.write_file(item, wav_file, overwrite)
+
+ elif nb_items > 1 and nb_items < len(audio_files):
+ msg = code + ' : Cas 3b : nb items < nb de fichiers audio, PAS de creation'
+ self.logger.info('item', msg)
+
+ counter += 1
+
+ msg = 'Liste des URLs des collections importées :'
+ self.logger.info('INFO', msg)
+ for collection in collections:
+ msg = 'http://'+self.domain+'/archives/collections/'+collection
+ self.logger.info(collection, msg)
+
+
+def print_usage(tool_name):
+ print "Usage: "+tool_name+" <project_dir> <source_dir> <pattern> <log_file> <domain>"
+ print " project_dir: the directory of the Django project which hosts Telemeta"
+ print " source_dir: the directory containing the wav files to include"
+ print " pattern: a pattern to match the collection names"
+ print " log_file: a log file to write logs"
+ print " domain: root domain for collections"
+
+def run():
+ if len(sys.argv) < 3:
+ print_usage(os.path.basename(sys.argv[0]))
+ sys.exit(1)
+ else:
+ project_dir = sys.argv[-5]
+ source_dir = sys.argv[-4]
+ pattern = sys.argv[-3]
+ log_file = sys.argv[-2]
+ url = sys.argv[-1]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ t = TelemetaWavImport(source_dir, log_file, pattern, url)
+ t.wav_import()
+
+if __name__ == '__main__':
+ run()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 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 re
+import sys
+import logging
+import datetime
+import timeside
+from django.core.management import setup_environ
+from django.core.files.base import ContentFile
+
+mapping = {
+ 'title': 'title',
+ 'album': 'collection',
+ 'date': 'recorded_from_date',
+ 'artist': 'author',
+ 'track-number': 'track',
+ 'encoder': 'comment',
+ 'genre': 'generic_style',
+ 'audio-codec': 'comment',
+ 'container-format': 'comment',
+ }
+
+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 TelemetaMediaImport:
+
+ def __init__(self, media_dir, log_file):
+ self.logger = Logger(log_file)
+ self.media_dir = media_dir
+ self.medias = self.get_medias()
+
+ def get_medias(self):
+ os.chdir(self.media_dir)
+ file_list = []
+ for root, dirs, files in os.walk('.'):
+ for file in files:
+ path = root + os.sep + file
+ if not os.sep+'.' in path:
+ file_list.append({'root': root, 'file': file})
+ return file_list
+
+ def set_collection(self, collection_name):
+ if not collection_name:
+ collection_name = 'Unkown'
+ code = collection_name.replace(' ','_')
+ code = re.sub(r'\W+', '_', code)
+ from telemeta.models.media import MediaCollection
+ collections = MediaCollection.objects.filter(code=code)
+ if not collections:
+ collection = MediaCollection(code=code,title=collection_name)
+ collection.save()
+ msg = 'created'
+ self.logger.write_info('collection ' + collection_name, msg)
+ else:
+ collection = collections[0]
+ return collection
+
+ def media_import(self):
+ from telemeta.models.media import MediaItem
+ for media in self.medias:
+ path = media['root'] + os.sep + media['file']
+ print 'checking ' + path
+ filename, ext = os.path.splitext(media['file'])
+ item = MediaItem.objects.filter(code=filename)
+ if not item:
+ print 'importing ' + path
+ decoder = timeside.decoder.FileDecoder(path)
+ try:
+ metadata = decoder.metadata()
+ print metadata
+ collection = self.set_collection(metadata['album'])
+ item = MediaItem(collection=collection)
+ item.code = re.sub(r'\W+', '_', metadata['title'])
+ for tag in mapping.keys():
+ try:
+ if tag == 'date':
+ date = metadata[tag].split(' ')[1].split('/')
+ metadata[tag] = date[2]+'-'+date[1]+'-'+date[0]
+ if mapping[tag] == 'comment':
+ item[mapping[tag]] = item[mapping[tag]] + '\n' + metadata[tag]
+ else:
+ item[mapping[tag]] = metadata[tag]
+ except:
+ continue
+ item.file = path
+ item.save()
+ msg = 'added item : ' + path
+ self.logger.write_info(collection.code, msg)
+ except:
+ continue
+
+
+def run():
+ project_dir = sys.argv[-2]
+ log_file = sys.argv[-1]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ media_dir = settings.MEDIA_ROOT
+ t = TelemetaMediaImport(media_dir, log_file)
+ t.media_import()
+
+if __name__ == '__main__':
+ run()
--- /dev/null
+#!/usr/bin/python
+
+import os, sys, string
+import logging
+
+class Logger:
+ """A logging object"""
+
+ def __init__(self, file):
+ self.logger = logging.getLogger('myapp')
+ self.hdlr = logging.FileHandler(file)
+ self.formatter = logging.Formatter('%(message)s')
+ self.hdlr.setFormatter(self.formatter)
+ self.logger.addHandler(self.hdlr)
+ self.logger.setLevel(logging.INFO)
+
+log_file = 'thumbs.log'
+logger = Logger(log_file)
+root_dir = sys.argv[-1]
+args = sys.argv[1:-1]
+source_format = 'webm'
+done = []
+preview_tc = '00:00:05'
+
+if os.path.exists(log_file):
+ f = open(log_file, 'r')
+ for line in f.readlines():
+ done.append(line[:-1])
+ f.close()
+
+for root, dirs, files in os.walk(root_dir):
+ for file in files:
+ path = os.path.abspath(root + os.sep + file)
+ name, ext = os.path.splitext(file)
+ if ext[1:] == source_format:
+ dest = os.path.abspath(root + os.sep + name + '.png')
+ if not dest in done or '--force' in args:
+ command = 'ffmpeg -ss '+ preview_tc + ' -i ' + path + ' -y ' + dest
+ os.system(command)
+ logger.logger.info(dest)
+
+print "DONE!"
--- /dev/null
+#!/usr/bin/python
+
+import os, sys, psutil
+import datetime
+from ebml.utils.ebml_data import *
+
+class FixCheckMedia(object):
+
+ def __init__(self, dir, tmp_dir):
+ self.dir = dir
+ self.tmp_dir = tmp_dir
+ if not os.path.exists(self.tmp_dir):
+ os.makedirs(self.tmp_dir)
+
+ def process(self):
+ webm_fixed_log = 'webm.fixed'
+ webm_tofix_log = 'webm.tofix'
+ mp3_fixed_log = 'mp3.fixed'
+ mp3_tofix_log = 'mp3.tofix'
+
+ for root, dirs, files in os.walk(self.dir):
+ for filename in files:
+ source = root + os.sep + filename
+ name = os.path.splitext(filename)[0]
+ ext = os.path.splitext(filename)[1][1:]
+
+ if ext == 'webm' and os.path.getsize(source):
+ dir_files = os.listdir(root)
+
+ if not webm_fixed_log in dir_files:
+ print source
+ self.fix_webm(source)
+ f = open(root + os.sep + webm_fixed_log, 'w')
+ f.close()
+ if os.path.exists(root + os.sep + webm_tofix_log):
+ os.remove(root + os.sep + webm_tofix_log)
+
+ if mp3_tofix_log in dir_files or not mp3_fixed_log in dir_files:
+ for file in dir_files:
+ dest_ext = os.path.splitext(file)[1][1:]
+ if dest_ext == 'mp3':
+ dest = root + os.sep + file
+ print dest
+ self.fix_mp3(source, dest)
+ f = open(root + os.sep + mp3_fixed_log, 'w')
+ f.close()
+ if os.path.exists(root + os.sep + mp3_tofix_log):
+ os.remove(root + os.sep + mp3_tofix_log)
+ #break
+
+
+ def hard_fix_webm(self, path):
+ try:
+ tmp_file = self.tmp_dir + 'out.webm '
+ command = 'ffmpeg -loglevel 0 -i "'+ path + '" -vcodec libvpx -vb 500k -acodec libvorbis -aq 7 -f webm -y "' + tmp_file + '" > /dev/null'
+ print command
+ os.system(command)
+ command = 'mv ' + tmp_file + path
+ os.system(command)
+ except:
+ pass
+
+
+ def fix_webm(self, path):
+ try:
+ tmp_file = self.tmp_dir + 'out.webm'
+ command = '/usr/local/bin/ffmpeg -loglevel 0 -i "' + path + '" -vcodec copy -acodec copy -f webm -y "' + tmp_file + '" > /dev/null'
+ print command
+ os.system(command)
+ ebml_obj = EBMLData(tmp_file)
+ offset = ebml_obj.get_first_cluster_seconds()
+ command = '/usr/local/bin/ffmpeg -loglevel 0 -ss ' + str(offset) + ' -i "' + tmp_file + '" -vcodec copy -acodec copy -f webm -y "' + path + '" > /dev/null'
+ print command
+ os.system(command)
+ except:
+ pass
+
+ def fix_mp3(self, source, path):
+ try:
+ command = '/usr/local/bin/ffmpeg -loglevel 0 -i "'+ source + '" -vn -aq 6 -y "' + path + '" > /dev/null'
+ print command
+ os.system(command)
+ except:
+ pass
+
+def get_pids(name, args=None):
+ """Get a process pid filtered by arguments and uid"""
+ pids = []
+ for proc in psutil.process_iter():
+ if proc.cmdline:
+ if name == proc.name:
+ if args:
+ if args in proc.cmdline:
+ pids.append(proc.pid)
+ else:
+ pids.append(proc.pid)
+ return pids
+
+dir = sys.argv[-2]
+tmp_dir = sys.argv[-1]
+
+path = os.path.abspath(__file__)
+pids = get_pids('python2.6',args=path)
+
+print datetime.datetime.now()
+if len(pids) <= 1:
+ print 'starting process...'
+ f = FixCheckMedia(dir, tmp_dir)
+ f.process()
+ print 'process finished.\n'
+else:
+ print 'already started !\n'
+
--- /dev/null
+#!/usr/bin/python
+
+import os, sys, string
+import logging
+
+
+class Logger:
+ """A logging object"""
+
+ def __init__(self, file):
+ self.logger = logging.getLogger('myapp')
+ self.hdlr = logging.FileHandler(file)
+ self.formatter = logging.Formatter('%(asctime)s %(message)s')
+ self.hdlr.setFormatter(self.formatter)
+ self.logger.addHandler(self.hdlr)
+ self.logger.setLevel(logging.INFO)
+
+
+source_format = 'webm'
+preview_tc = '00:00:05'
+threads = 4
+
+ffmpeg_args = {
+ 'mp3' : '-i "%s" -vn -acodec libmp3lame -aq 6 -ac 2',
+ 'ogg' : '-i "%s" -vn -acodec copy',
+ 'mp4' : '-i "%s" -vcodec libx264 -threads ' + str(threads) + \
+ ' -c:v libx264 -crf 17 -maxrate 1100k -bufsize 1835k -acodec libfaac -ab 96k -ac 2',
+ 'png' : '-ss ' + preview_tc + ' -i "%s"',
+ }
+
+args = sys.argv[1:]
+log_file = args[-1]
+root_dir = args[-2]
+logger = Logger(log_file)
+
+for root, dirs, files in os.walk(root_dir):
+ for file in files:
+ path = os.path.abspath(root + os.sep + file)
+ name, ext = os.path.splitext(file)
+ if ext[1:] == source_format:
+ for format in ffmpeg_args.keys():
+ local_file = name + '.' + format
+ dest = os.path.abspath(root + os.sep + local_file)
+ local_files = os.listdir(root)
+ if not local_file in local_files or '--force' in args:
+ command = 'ffmpeg -loglevel 0 ' + ffmpeg_args[format] % path + ' -y "' + dest + '"'
+ logger.logger.info(command)
+ if not '--dry-run' in args:
+ os.system(command)
+++ /dev/null
-
-git filter-branch -f --commit-filter '
- if [ "$GIT_COMMITTER_EMAIL" = "<>" ];
- then
- GIT_COMMITTER_NAME="<yomguy>";
- GIT_AUTHOR_NAME="<yomguy>";
- GIT_COMMITTER_EMAIL="<yomguy@parisson.com>";
- GIT_AUTHOR_EMAIL="<yomguy@parisson.com>";
- git commit-tree "$@";
- else
- git commit-tree "$@";
- fi' HEAD
+++ /dev/null
-#!/bin/sh
-# needs epydoc
-
-app="telemeta"
-dir=/home/$USER/dev/$app/doc/
-server="git.parisson.com"
-
-epydoc -n $app -u https://github.com/Parisson/Telemeta -o $dir $app/
-rsync -a $dir $server:/var/www/files/doc/$app/html/
-
+++ /dev/null
-#!/bin/bash
-
-git branch | tr -d \* | while read line
-do
- branch=${line/#\ }
-
- if [[ ! $branch == *master* ]]; then
- echo "Merge master to $branch:"
- git checkout $branch
- git merge master
- git checkout master
- fi
-done
-
-echo "Done !"
+++ /dev/null
-#!/bin/sh
-
-git checkout $1
-git merge master
-git checkout master
-
+++ /dev/null
-#!/bin/bash
-
-git branch | tr -d \* | while read line
-do
- branch=${line/#\ }
-
- git push origin $branch
- git push hub $branch
-
-done
-
-git push --tags
-git push --tags hub
-
-ssh vcs.parisson.com "cd /var/git/telemeta.git; git update-server-info"
-
-#echo "Update jimi.parisson.com:"
-echo "Update angus.parisson.com:"
-ssh angus.parisson.com "cd /home/telemeta/telemeta-master; git pull origin master; \
- cd /home/telemeta/telemeta-develop; git pull origin dev; \
- cd /home/telemeta/demo/; ./manage.py migrate --delete-ghost-migrations;
- cd /home/telemeta/sandbox/; ./manage.py migrate --delete-ghost-migrations;
- cd /home/telemeta/parisson/; ./manage.py migrate --delete-ghost-migrations; "
-
-echo "Done !"
+++ /dev/null
-#!/bin/sh
-
-python setup.py register
-python setup.py sdist upload
-
+++ /dev/null
-#!/bin/sh
-
-cd telemeta
-django-admin.py makemessages -a
-django-admin.py makemessages -d djangojs -a
-django-admin.py compilemessages
-cd ..
+++ /dev/null
-eztelemeta (0.1)
- * Initial release
-
- -- Olivier Guilyardi <olivier {at} samalyse {dot} com> Thu, 16 Apr 2009 16:02:17 +0200
+++ /dev/null
-
-CeCILL FREE SOFTWARE LICENSE AGREEMENT
-
-
- Notice
-
-This Agreement is a Free Software license agreement that is the result
-of discussions between its authors in order to ensure compliance with
-the two main principles guiding its drafting:
-
- * firstly, compliance with the principles governing the distribution
- of Free Software: access to source code, broad rights granted to
- users,
- * secondly, the election of a governing law, French law, with which
- it is conformant, both as regards the law of torts and
- intellectual property law, and the protection that it offers to
- both authors and holders of the economic rights over software.
-
-The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
-license are:
-
-Commissariat à l'Energie Atomique - CEA, a public scientific, technical
-and industrial research establishment, having its principal place of
-business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
-
-Centre National de la Recherche Scientifique - CNRS, a public scientific
-and technological establishment, having its principal place of business
-at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
-
-Institut National de Recherche en Informatique et en Automatique -
-INRIA, a public scientific and technological establishment, having its
-principal place of business at Domaine de Voluceau, Rocquencourt, BP
-105, 78153 Le Chesnay cedex, France.
-
-
- Preamble
-
-The purpose of this Free Software license agreement is to grant users
-the right to modify and redistribute the software governed by this
-license within the framework of an open source distribution model.
-
-The exercising of these rights is conditional upon certain obligations
-for users so as to preserve this status for all subsequent redistributions.
-
-In consideration of access to the source code and the rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors only have limited liability.
-
-In this respect, the risks associated with loading, using, modifying
-and/or developing or reproducing the software by the user are brought to
-the user's attention, given its Free Software status, which may make it
-complicated to use, with the result that its use is reserved for
-developers and experienced professionals having in-depth computer
-knowledge. Users are therefore encouraged to load and test the
-suitability of the software as regards their requirements in conditions
-enabling the security of their systems and/or data to be ensured and,
-more generally, to use and operate it in the same conditions of
-security. This Agreement may be freely reproduced and published,
-provided it is not altered, and that no provisions are either added or
-removed herefrom.
-
-This Agreement may apply to any or all software for which the holder of
-the economic rights decides to submit the use thereof to its provisions.
-
-
- Article 1 - DEFINITIONS
-
-For the purpose of this Agreement, when the following expressions
-commence with a capital letter, they shall have the following meaning:
-
-Agreement: means this license agreement, and its possible subsequent
-versions and annexes.
-
-Software: means the software in its Object Code and/or Source Code form
-and, where applicable, its documentation, "as is" when the Licensee
-accepts the Agreement.
-
-Initial Software: means the Software in its Source Code and possibly its
-Object Code form and, where applicable, its documentation, "as is" when
-it is first distributed under the terms and conditions of the Agreement.
-
-Modified Software: means the Software modified by at least one
-Contribution.
-
-Source Code: means all the Software's instructions and program lines to
-which access is required so as to modify the Software.
-
-Object Code: means the binary files originating from the compilation of
-the Source Code.
-
-Holder: means the holder(s) of the economic rights over the Initial
-Software.
-
-Licensee: means the Software user(s) having accepted the Agreement.
-
-Contributor: means a Licensee having made at least one Contribution.
-
-Licensor: means the Holder, or any other individual or legal entity, who
-distributes the Software under the Agreement.
-
-Contribution: means any or all modifications, corrections, translations,
-adaptations and/or new functions integrated into the Software by any or
-all Contributors, as well as any or all Internal Modules.
-
-Module: means a set of sources files including their documentation that
-enables supplementary functions or services in addition to those offered
-by the Software.
-
-External Module: means any or all Modules, not derived from the
-Software, so that this Module and the Software run in separate address
-spaces, with one calling the other when they are run.
-
-Internal Module: means any or all Module, connected to the Software so
-that they both execute in the same address space.
-
-GNU GPL: means the GNU General Public License version 2 or any
-subsequent version, as published by the Free Software Foundation Inc.
-
-Parties: mean both the Licensee and the Licensor.
-
-These expressions may be used both in singular and plural form.
-
-
- Article 2 - PURPOSE
-
-The purpose of the Agreement is the grant by the Licensor to the
-Licensee of a non-exclusive, transferable and worldwide license for the
-Software as set forth in Article 5 hereinafter for the whole term of the
-protection granted by the rights over said Software.
-
-
- Article 3 - ACCEPTANCE
-
-3.1 The Licensee shall be deemed as having accepted the terms and
-conditions of this Agreement upon the occurrence of the first of the
-following events:
-
- * (i) loading the Software by any or all means, notably, by
- downloading from a remote server, or by loading from a physical
- medium;
- * (ii) the first time the Licensee exercises any of the rights
- granted hereunder.
-
-3.2 One copy of the Agreement, containing a notice relating to the
-characteristics of the Software, to the limited warranty, and to the
-fact that its use is restricted to experienced users has been provided
-to the Licensee prior to its acceptance as set forth in Article 3.1
-hereinabove, and the Licensee hereby acknowledges that it has read and
-understood it.
-
-
- Article 4 - EFFECTIVE DATE AND TERM
-
-
- 4.1 EFFECTIVE DATE
-
-The Agreement shall become effective on the date when it is accepted by
-the Licensee as set forth in Article 3.1.
-
-
- 4.2 TERM
-
-The Agreement shall remain in force for the entire legal term of
-protection of the economic rights over the Software.
-
-
- Article 5 - SCOPE OF RIGHTS GRANTED
-
-The Licensor hereby grants to the Licensee, who accepts, the following
-rights over the Software for any or all use, and for the term of the
-Agreement, on the basis of the terms and conditions set forth hereinafter.
-
-Besides, if the Licensor owns or comes to own one or more patents
-protecting all or part of the functions of the Software or of its
-components, the Licensor undertakes not to enforce the rights granted by
-these patents against successive Licensees using, exploiting or
-modifying the Software. If these patents are transferred, the Licensor
-undertakes to have the transferees subscribe to the obligations set
-forth in this paragraph.
-
-
- 5.1 RIGHT OF USE
-
-The Licensee is authorized to use the Software, without any limitation
-as to its fields of application, with it being hereinafter specified
-that this comprises:
-
- 1. permanent or temporary reproduction of all or part of the Software
- by any or all means and in any or all form.
-
- 2. loading, displaying, running, or storing the Software on any or
- all medium.
-
- 3. entitlement to observe, study or test its operation so as to
- determine the ideas and principles behind any or all constituent
- elements of said Software. This shall apply when the Licensee
- carries out any or all loading, displaying, running, transmission
- or storage operation as regards the Software, that it is entitled
- to carry out hereunder.
-
-
- 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
-
-The right to make Contributions includes the right to translate, adapt,
-arrange, or make any or all modifications to the Software, and the right
-to reproduce the resulting software.
-
-The Licensee is authorized to make any or all Contributions to the
-Software provided that it includes an explicit notice that it is the
-author of said Contribution and indicates the date of the creation thereof.
-
-
- 5.3 RIGHT OF DISTRIBUTION
-
-In particular, the right of distribution includes the right to publish,
-transmit and communicate the Software to the general public on any or
-all medium, and by any or all means, and the right to market, either in
-consideration of a fee, or free of charge, one or more copies of the
-Software by any means.
-
-The Licensee is further authorized to distribute copies of the modified
-or unmodified Software to third parties according to the terms and
-conditions set forth hereinafter.
-
-
- 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
-
-The Licensee is authorized to distribute true copies of the Software in
-Source Code or Object Code form, provided that said distribution
-complies with all the provisions of the Agreement and is accompanied by:
-
- 1. a copy of the Agreement,
-
- 2. a notice relating to the limitation of both the Licensor's
- warranty and liability as set forth in Articles 8 and 9,
-
-and that, in the event that only the Object Code of the Software is
-redistributed, the Licensee allows future Licensees unhindered access to
-the full Source Code of the Software by indicating how to access it, it
-being understood that the additional cost of acquiring the Source Code
-shall not exceed the cost of transferring the data.
-
-
- 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
-
-When the Licensee makes a Contribution to the Software, the terms and
-conditions for the distribution of the resulting Modified Software
-become subject to all the provisions of this Agreement.
-
-The Licensee is authorized to distribute the Modified Software, in
-source code or object code form, provided that said distribution
-complies with all the provisions of the Agreement and is accompanied by:
-
- 1. a copy of the Agreement,
-
- 2. a notice relating to the limitation of both the Licensor's
- warranty and liability as set forth in Articles 8 and 9,
-
-and that, in the event that only the object code of the Modified
-Software is redistributed, the Licensee allows future Licensees
-unhindered access to the full source code of the Modified Software by
-indicating how to access it, it being understood that the additional
-cost of acquiring the source code shall not exceed the cost of
-transferring the data.
-
-
- 5.3.3 DISTRIBUTION OF EXTERNAL MODULES
-
-When the Licensee has developed an External Module, the terms and
-conditions of this Agreement do not apply to said External Module, that
-may be distributed under a separate license agreement.
-
-
- 5.3.4 COMPATIBILITY WITH THE GNU GPL
-
-The Licensee can include a code that is subject to the provisions of one
-of the versions of the GNU GPL in the Modified or unmodified Software,
-and distribute that entire code under the terms of the same version of
-the GNU GPL.
-
-The Licensee can include the Modified or unmodified Software in a code
-that is subject to the provisions of one of the versions of the GNU GPL,
-and distribute that entire code under the terms of the same version of
-the GNU GPL.
-
-
- Article 6 - INTELLECTUAL PROPERTY
-
-
- 6.1 OVER THE INITIAL SOFTWARE
-
-The Holder owns the economic rights over the Initial Software. Any or
-all use of the Initial Software is subject to compliance with the terms
-and conditions under which the Holder has elected to distribute its work
-and no one shall be entitled to modify the terms and conditions for the
-distribution of said Initial Software.
-
-The Holder undertakes that the Initial Software will remain ruled at
-least by this Agreement, for the duration set forth in Article 4.2.
-
-
- 6.2 OVER THE CONTRIBUTIONS
-
-The Licensee who develops a Contribution is the owner of the
-intellectual property rights over this Contribution as defined by
-applicable law.
-
-
- 6.3 OVER THE EXTERNAL MODULES
-
-The Licensee who develops an External Module is the owner of the
-intellectual property rights over this External Module as defined by
-applicable law and is free to choose the type of agreement that shall
-govern its distribution.
-
-
- 6.4 JOINT PROVISIONS
-
-The Licensee expressly undertakes:
-
- 1. not to remove, or modify, in any manner, the intellectual property
- notices attached to the Software;
-
- 2. to reproduce said notices, in an identical manner, in the copies
- of the Software modified or not.
-
-The Licensee undertakes not to directly or indirectly infringe the
-intellectual property rights of the Holder and/or Contributors on the
-Software and to take, where applicable, vis-à-vis its staff, any and all
-measures required to ensure respect of said intellectual property rights
-of the Holder and/or Contributors.
-
-
- Article 7 - RELATED SERVICES
-
-7.1 Under no circumstances shall the Agreement oblige the Licensor to
-provide technical assistance or maintenance services for the Software.
-
-However, the Licensor is entitled to offer this type of services. The
-terms and conditions of such technical assistance, and/or such
-maintenance, shall be set forth in a separate instrument. Only the
-Licensor offering said maintenance and/or technical assistance services
-shall incur liability therefor.
-
-7.2 Similarly, any Licensor is entitled to offer to its licensees, under
-its sole responsibility, a warranty, that shall only be binding upon
-itself, for the redistribution of the Software and/or the Modified
-Software, under terms and conditions that it is free to decide. Said
-warranty, and the financial terms and conditions of its application,
-shall be subject of a separate instrument executed between the Licensor
-and the Licensee.
-
-
- Article 8 - LIABILITY
-
-8.1 Subject to the provisions of Article 8.2, the Licensee shall be
-entitled to claim compensation for any direct loss it may have suffered
-from the Software as a result of a fault on the part of the relevant
-Licensor, subject to providing evidence thereof.
-
-8.2 The Licensor's liability is limited to the commitments made under
-this Agreement and shall not be incurred as a result of in particular:
-(i) loss due the Licensee's total or partial failure to fulfill its
-obligations, (ii) direct or consequential loss that is suffered by the
-Licensee due to the use or performance of the Software, and (iii) more
-generally, any consequential loss. In particular the Parties expressly
-agree that any or all pecuniary or business loss (i.e. loss of data,
-loss of profits, operating loss, loss of customers or orders,
-opportunity cost, any disturbance to business activities) or any or all
-legal proceedings instituted against the Licensee by a third party,
-shall constitute consequential loss and shall not provide entitlement to
-any or all compensation from the Licensor.
-
-
- Article 9 - WARRANTY
-
-9.1 The Licensee acknowledges that the scientific and technical
-state-of-the-art when the Software was distributed did not enable all
-possible uses to be tested and verified, nor for the presence of
-possible defects to be detected. In this respect, the Licensee's
-attention has been drawn to the risks associated with loading, using,
-modifying and/or developing and reproducing the Software which are
-reserved for experienced users.
-
-The Licensee shall be responsible for verifying, by any or all means,
-the suitability of the product for its requirements, its good working
-order, and for ensuring that it shall not cause damage to either persons
-or properties.
-
-9.2 The Licensor hereby represents, in good faith, that it is entitled
-to grant all the rights over the Software (including in particular the
-rights set forth in Article 5).
-
-9.3 The Licensee acknowledges that the Software is supplied "as is" by
-the Licensor without any other express or tacit warranty, other than
-that provided for in Article 9.2 and, in particular, without any warranty
-as to its commercial value, its secured, safe, innovative or relevant
-nature.
-
-Specifically, the Licensor does not warrant that the Software is free
-from any error, that it will operate without interruption, that it will
-be compatible with the Licensee's own equipment and software
-configuration, nor that it will meet the Licensee's requirements.
-
-9.4 The Licensor does not either expressly or tacitly warrant that the
-Software does not infringe any third party intellectual property right
-relating to a patent, software or any other property right. Therefore,
-the Licensor disclaims any and all liability towards the Licensee
-arising out of any or all proceedings for infringement that may be
-instituted in respect of the use, modification and redistribution of the
-Software. Nevertheless, should such proceedings be instituted against
-the Licensee, the Licensor shall provide it with technical and legal
-assistance for its defense. Such technical and legal assistance shall be
-decided on a case-by-case basis between the relevant Licensor and the
-Licensee pursuant to a memorandum of understanding. The Licensor
-disclaims any and all liability as regards the Licensee's use of the
-name of the Software. No warranty is given as regards the existence of
-prior rights over the name of the Software or as regards the existence
-of a trademark.
-
-
- Article 10 - TERMINATION
-
-10.1 In the event of a breach by the Licensee of its obligations
-hereunder, the Licensor may automatically terminate this Agreement
-thirty (30) days after notice has been sent to the Licensee and has
-remained ineffective.
-
-10.2 A Licensee whose Agreement is terminated shall no longer be
-authorized to use, modify or distribute the Software. However, any
-licenses that it may have granted prior to termination of the Agreement
-shall remain valid subject to their having been granted in compliance
-with the terms and conditions hereof.
-
-
- Article 11 - MISCELLANEOUS
-
-
- 11.1 EXCUSABLE EVENTS
-
-Neither Party shall be liable for any or all delay, or failure to
-perform the Agreement, that may be attributable to an event of force
-majeure, an act of God or an outside cause, such as defective
-functioning or interruptions of the electricity or telecommunications
-networks, network paralysis following a virus attack, intervention by
-government authorities, natural disasters, water damage, earthquakes,
-fire, explosions, strikes and labor unrest, war, etc.
-
-11.2 Any failure by either Party, on one or more occasions, to invoke
-one or more of the provisions hereof, shall under no circumstances be
-interpreted as being a waiver by the interested Party of its right to
-invoke said provision(s) subsequently.
-
-11.3 The Agreement cancels and replaces any or all previous agreements,
-whether written or oral, between the Parties and having the same
-purpose, and constitutes the entirety of the agreement between said
-Parties concerning said purpose. No supplement or modification to the
-terms and conditions hereof shall be effective as between the Parties
-unless it is made in writing and signed by their duly authorized
-representatives.
-
-11.4 In the event that one or more of the provisions hereof were to
-conflict with a current or future applicable act or legislative text,
-said act or legislative text shall prevail, and the Parties shall make
-the necessary amendments so as to comply with said act or legislative
-text. All other provisions shall remain effective. Similarly, invalidity
-of a provision of the Agreement, for any reason whatsoever, shall not
-cause the Agreement as a whole to be invalid.
-
-
- 11.5 LANGUAGE
-
-The Agreement is drafted in both French and English and both versions
-are deemed authentic.
-
-
- Article 12 - NEW VERSIONS OF THE AGREEMENT
-
-12.1 Any person is authorized to duplicate and distribute copies of this
-Agreement.
-
-12.2 So as to ensure coherence, the wording of this Agreement is
-protected and may only be modified by the authors of the License, who
-reserve the right to periodically publish updates or new versions of the
-Agreement, each with a separate number. These subsequent versions may
-address new issues encountered by Free Software.
-
-12.3 Any Software distributed under a given version of the Agreement may
-only be subsequently distributed under the same version of the Agreement
-or a subsequent version, subject to the provisions of Article 5.3.4.
-
-
- Article 13 - GOVERNING LAW AND JURISDICTION
-
-13.1 The Agreement is governed by French law. The Parties agree to
-endeavor to seek an amicable solution to any disagreements or disputes
-that may arise during the performance of the Agreement.
-
-13.2 Failing an amicable solution within two (2) months as from their
-occurrence, and unless emergency proceedings are necessary, the
-disagreements or disputes shall be referred to the Paris Courts having
-jurisdiction, by the more diligent Party.
-
-
-Version 2.0 dated 2006-09-05.
+++ /dev/null
-
-CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL
-
-
- Avertissement
-
-Ce contrat est une licence de logiciel libre issue d'une concertation
-entre ses auteurs afin que le respect de deux grands principes préside à
-sa rédaction:
-
- * d'une part, le respect des principes de diffusion des logiciels
- libres: accès au code source, droits étendus conférés aux
- utilisateurs,
- * d'autre part, la désignation d'un droit applicable, le droit
- français, auquel elle est conforme, tant au regard du droit de la
- responsabilité civile que du droit de la propriété intellectuelle
- et de la protection qu'il offre aux auteurs et titulaires des
- droits patrimoniaux sur un logiciel.
-
-Les auteurs de la licence CeCILL (pour Ce[a] C[nrs] I[nria] L[ogiciel]
-L[ibre]) sont:
-
-Commissariat à l'Energie Atomique - CEA, établissement public de
-recherche à caractère scientifique, technique et industriel, dont le
-siège est situé 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris.
-
-Centre National de la Recherche Scientifique - CNRS, établissement
-public à caractère scientifique et technologique, dont le siège est
-situé 3 rue Michel-Ange, 75794 Paris cedex 16.
-
-Institut National de Recherche en Informatique et en Automatique -
-INRIA, établissement public à caractère scientifique et technologique,
-dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153
-Le Chesnay cedex.
-
-
- Préambule
-
-Ce contrat est une licence de logiciel libre dont l'objectif est de
-conférer aux utilisateurs la liberté de modification et de
-redistribution du logiciel régi par cette licence dans le cadre d'un
-modèle de diffusion en logiciel libre.
-
-L'exercice de ces libertés est assorti de certains devoirs à la charge
-des utilisateurs afin de préserver ce statut au cours des
-redistributions ultérieures.
-
-L'accessibilité au code source et les droits de copie, de modification
-et de redistribution qui en découlent ont pour contrepartie de n'offrir
-aux utilisateurs qu'une garantie limitée et de ne faire peser sur
-l'auteur du logiciel, le titulaire des droits patrimoniaux et les
-concédants successifs qu'une responsabilité restreinte.
-
-A cet égard l'attention de l'utilisateur est attirée sur les risques
-associés au chargement, à l'utilisation, à la modification et/ou au
-développement et à la reproduction du logiciel par l'utilisateur étant
-donné sa spécificité de logiciel libre, qui peut le rendre complexe à
-manipuler et qui le réserve donc à des développeurs ou des
-professionnels avertis possédant des connaissances informatiques
-approfondies. Les utilisateurs sont donc invités à charger et tester
-l'adéquation du logiciel à leurs besoins dans des conditions permettant
-d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus
-généralement, à l'utiliser et l'exploiter dans les mêmes conditions de
-sécurité. Ce contrat peut être reproduit et diffusé librement, sous
-réserve de le conserver en l'état, sans ajout ni suppression de clauses.
-
-Ce contrat est susceptible de s'appliquer à tout logiciel dont le
-titulaire des droits patrimoniaux décide de soumettre l'exploitation aux
-dispositions qu'il contient.
-
-
- Article 1 - DEFINITIONS
-
-Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une
-lettre capitale, auront la signification suivante:
-
-Contrat: désigne le présent contrat de licence, ses éventuelles versions
-postérieures et annexes.
-
-Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code
-Source et le cas échéant sa documentation, dans leur état au moment de
-l'acceptation du Contrat par le Licencié.
-
-Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et
-éventuellement de Code Objet et le cas échéant sa documentation, dans
-leur état au moment de leur première diffusion sous les termes du Contrat.
-
-Logiciel Modifié: désigne le Logiciel modifié par au moins une
-Contribution.
-
-Code Source: désigne l'ensemble des instructions et des lignes de
-programme du Logiciel et auquel l'accès est nécessaire en vue de
-modifier le Logiciel.
-
-Code Objet: désigne les fichiers binaires issus de la compilation du
-Code Source.
-
-Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur
-sur le Logiciel Initial.
-
-Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le
-Contrat.
-
-Contributeur: désigne le Licencié auteur d'au moins une Contribution.
-
-Concédant: désigne le Titulaire ou toute personne physique ou morale
-distribuant le Logiciel sous le Contrat.
-
-Contribution: désigne l'ensemble des modifications, corrections,
-traductions, adaptations et/ou nouvelles fonctionnalités intégrées dans
-le Logiciel par tout Contributeur, ainsi que tout Module Interne.
-
-Module: désigne un ensemble de fichiers sources y compris leur
-documentation qui permet de réaliser des fonctionnalités ou services
-supplémentaires à ceux fournis par le Logiciel.
-
-Module Externe: désigne tout Module, non dérivé du Logiciel, tel que ce
-Module et le Logiciel s'exécutent dans des espaces d'adressage
-différents, l'un appelant l'autre au moment de leur exécution.
-
-Module Interne: désigne tout Module lié au Logiciel de telle sorte
-qu'ils s'exécutent dans le même espace d'adressage.
-
-GNU GPL: désigne la GNU General Public License dans sa version 2 ou
-toute version ultérieure, telle que publiée par Free Software Foundation
-Inc.
-
-Parties: désigne collectivement le Licencié et le Concédant.
-
-Ces termes s'entendent au singulier comme au pluriel.
-
-
- Article 2 - OBJET
-
-Le Contrat a pour objet la concession par le Concédant au Licencié d'une
-licence non exclusive, cessible et mondiale du Logiciel telle que
-définie ci-après à l'article 5 pour toute la durée de protection des droits
-portant sur ce Logiciel.
-
-
- Article 3 - ACCEPTATION
-
-3.1 L'acceptation par le Licencié des termes du Contrat est réputée
-acquise du fait du premier des faits suivants:
-
- * (i) le chargement du Logiciel par tout moyen notamment par
- téléchargement à partir d'un serveur distant ou par chargement à
- partir d'un support physique;
- * (ii) le premier exercice par le Licencié de l'un quelconque des
- droits concédés par le Contrat.
-
-3.2 Un exemplaire du Contrat, contenant notamment un avertissement
-relatif aux spécificités du Logiciel, à la restriction de garantie et à
-la limitation à un usage par des utilisateurs expérimentés a été mis à
-disposition du Licencié préalablement à son acceptation telle que
-définie à l'article 3.1 ci dessus et le Licencié reconnaît en avoir pris
-connaissance.
-
-
- Article 4 - ENTREE EN VIGUEUR ET DUREE
-
-
- 4.1 ENTREE EN VIGUEUR
-
-Le Contrat entre en vigueur à la date de son acceptation par le Licencié
-telle que définie en 3.1.
-
-
- 4.2 DUREE
-
-Le Contrat produira ses effets pendant toute la durée légale de
-protection des droits patrimoniaux portant sur le Logiciel.
-
-
- Article 5 - ETENDUE DES DROITS CONCEDES
-
-Le Concédant concède au Licencié, qui accepte, les droits suivants sur
-le Logiciel pour toutes destinations et pour la durée du Contrat dans
-les conditions ci-après détaillées.
-
-Par ailleurs, si le Concédant détient ou venait à détenir un ou
-plusieurs brevets d'invention protégeant tout ou partie des
-fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas
-opposer les éventuels droits conférés par ces brevets aux Licenciés
-successifs qui utiliseraient, exploiteraient ou modifieraient le
-Logiciel. En cas de cession de ces brevets, le Concédant s'engage à
-faire reprendre les obligations du présent alinéa aux cessionnaires.
-
-
- 5.1 DROIT D'UTILISATION
-
-Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant
-aux domaines d'application, étant ci-après précisé que cela comporte:
-
- 1. la reproduction permanente ou provisoire du Logiciel en tout ou
- partie par tout moyen et sous toute forme.
-
- 2. le chargement, l'affichage, l'exécution, ou le stockage du
- Logiciel sur tout support.
-
- 3. la possibilité d'en observer, d'en étudier, ou d'en tester le
- fonctionnement afin de déterminer les idées et principes qui sont
- à la base de n'importe quel élément de ce Logiciel; et ceci,
- lorsque le Licencié effectue toute opération de chargement,
- d'affichage, d'exécution, de transmission ou de stockage du
- Logiciel qu'il est en droit d'effectuer en vertu du Contrat.
-
-
- 5.2 DROIT D'APPORTER DES CONTRIBUTIONS
-
-Le droit d'apporter des Contributions comporte le droit de traduire,
-d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel
-et le droit de reproduire le logiciel en résultant.
-
-Le Licencié est autorisé à apporter toute Contribution au Logiciel sous
-réserve de mentionner, de façon explicite, son nom en tant qu'auteur de
-cette Contribution et la date de création de celle-ci.
-
-
- 5.3 DROIT DE DISTRIBUTION
-
-Le droit de distribution comporte notamment le droit de diffuser, de
-transmettre et de communiquer le Logiciel au public sur tout support et
-par tout moyen ainsi que le droit de mettre sur le marché à titre
-onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé.
-
-Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou
-non, à des tiers dans les conditions ci-après détaillées.
-
-
- 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION
-
-Le Licencié est autorisé à distribuer des copies conformes du Logiciel,
-sous forme de Code Source ou de Code Objet, à condition que cette
-distribution respecte les dispositions du Contrat dans leur totalité et
-soit accompagnée:
-
- 1. d'un exemplaire du Contrat,
-
- 2. d'un avertissement relatif à la restriction de garantie et de
- responsabilité du Concédant telle que prévue aux articles 8
- et 9,
-
-et que, dans le cas où seul le Code Objet du Logiciel est redistribué,
-le Licencié permette aux futurs Licenciés d'accéder facilement au Code
-Source complet du Logiciel en indiquant les modalités d'accès, étant
-entendu que le coût additionnel d'acquisition du Code Source ne devra
-pas excéder le simple coût de transfert des données.
-
-
- 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE
-
-Lorsque le Licencié apporte une Contribution au Logiciel, les conditions
-de distribution du Logiciel Modifié en résultant sont alors soumises à
-l'intégralité des dispositions du Contrat.
-
-Le Licencié est autorisé à distribuer le Logiciel Modifié, sous forme de
-code source ou de code objet, à condition que cette distribution
-respecte les dispositions du Contrat dans leur totalité et soit
-accompagnée:
-
- 1. d'un exemplaire du Contrat,
-
- 2. d'un avertissement relatif à la restriction de garantie et de
- responsabilité du Concédant telle que prévue aux articles 8
- et 9,
-
-et que, dans le cas où seul le code objet du Logiciel Modifié est
-redistribué, le Licencié permette aux futurs Licenciés d'accéder
-facilement au code source complet du Logiciel Modifié en indiquant les
-modalités d'accès, étant entendu que le coût additionnel d'acquisition
-du code source ne devra pas excéder le simple coût de transfert des données.
-
-
- 5.3.3 DISTRIBUTION DES MODULES EXTERNES
-
-Lorsque le Licencié a développé un Module Externe les conditions du
-Contrat ne s'appliquent pas à ce Module Externe, qui peut être distribué
-sous un contrat de licence différent.
-
-
- 5.3.4 COMPATIBILITE AVEC LA LICENCE GNU GPL
-
-Le Licencié peut inclure un code soumis aux dispositions d'une des
-versions de la licence GNU GPL dans le Logiciel modifié ou non et
-distribuer l'ensemble sous les conditions de la même version de la
-licence GNU GPL.
-
-Le Licencié peut inclure le Logiciel modifié ou non dans un code soumis
-aux dispositions d'une des versions de la licence GNU GPL et distribuer
-l'ensemble sous les conditions de la même version de la licence GNU GPL.
-
-
- Article 6 - PROPRIETE INTELLECTUELLE
-
-
- 6.1 SUR LE LOGICIEL INITIAL
-
-Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel
-Initial. Toute utilisation du Logiciel Initial est soumise au respect
-des conditions dans lesquelles le Titulaire a choisi de diffuser son
-oeuvre et nul autre n'a la faculté de modifier les conditions de
-diffusion de ce Logiciel Initial.
-
-Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi
-par le Contrat et ce, pour la durée visée à l'article 4.2.
-
-
- 6.2 SUR LES CONTRIBUTIONS
-
-Le Licencié qui a développé une Contribution est titulaire sur celle-ci
-des droits de propriété intellectuelle dans les conditions définies par
-la législation applicable.
-
-
- 6.3 SUR LES MODULES EXTERNES
-
-Le Licencié qui a développé un Module Externe est titulaire sur celui-ci
-des droits de propriété intellectuelle dans les conditions définies par
-la législation applicable et reste libre du choix du contrat régissant
-sa diffusion.
-
-
- 6.4 DISPOSITIONS COMMUNES
-
-Le Licencié s'engage expressément:
-
- 1. à ne pas supprimer ou modifier de quelque manière que ce soit les
- mentions de propriété intellectuelle apposées sur le Logiciel;
-
- 2. à reproduire à l'identique lesdites mentions de propriété
- intellectuelle sur les copies du Logiciel modifié ou non.
-
-Le Licencié s'engage à ne pas porter atteinte, directement ou
-indirectement, aux droits de propriété intellectuelle du Titulaire et/ou
-des Contributeurs sur le Logiciel et à prendre, le cas échéant, à
-l'égard de son personnel toutes les mesures nécessaires pour assurer le
-respect des dits droits de propriété intellectuelle du Titulaire et/ou
-des Contributeurs.
-
-
- Article 7 - SERVICES ASSOCIES
-
-7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de
-prestations d'assistance technique ou de maintenance du Logiciel.
-
-Cependant le Concédant reste libre de proposer ce type de services. Les
-termes et conditions d'une telle assistance technique et/ou d'une telle
-maintenance seront alors déterminés dans un acte séparé. Ces actes de
-maintenance et/ou assistance technique n'engageront que la seule
-responsabilité du Concédant qui les propose.
-
-7.2 De même, tout Concédant est libre de proposer, sous sa seule
-responsabilité, à ses licenciés une garantie, qui n'engagera que lui,
-lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce,
-dans les conditions qu'il souhaite. Cette garantie et les modalités
-financières de son application feront l'objet d'un acte séparé entre le
-Concédant et le Licencié.
-
-
- Article 8 - RESPONSABILITE
-
-8.1 Sous réserve des dispositions de l'article 8.2, le Licencié a la
-faculté, sous réserve de prouver la faute du Concédant concerné, de
-solliciter la réparation du préjudice direct qu'il subirait du fait du
-Logiciel et dont il apportera la preuve.
-
-8.2 La responsabilité du Concédant est limitée aux engagements pris en
-application du Contrat et ne saurait être engagée en raison notamment:
-(i) des dommages dus à l'inexécution, totale ou partielle, de ses
-obligations par le Licencié, (ii) des dommages directs ou indirects
-découlant de l'utilisation ou des performances du Logiciel subis par le
-Licencié et (iii) plus généralement d'un quelconque dommage indirect. En
-particulier, les Parties conviennent expressément que tout préjudice
-financier ou commercial (par exemple perte de données, perte de
-bénéfices, perte d'exploitation, perte de clientèle ou de commandes,
-manque à gagner, trouble commercial quelconque) ou toute action dirigée
-contre le Licencié par un tiers, constitue un dommage indirect et
-n'ouvre pas droit à réparation par le Concédant.
-
-
- Article 9 - GARANTIE
-
-9.1 Le Licencié reconnaît que l'état actuel des connaissances
-scientifiques et techniques au moment de la mise en circulation du
-Logiciel ne permet pas d'en tester et d'en vérifier toutes les
-utilisations ni de détecter l'existence d'éventuels défauts. L'attention
-du Licencié a été attirée sur ce point sur les risques associés au
-chargement, à l'utilisation, la modification et/ou au développement et à
-la reproduction du Logiciel qui sont réservés à des utilisateurs avertis.
-
-Il relève de la responsabilité du Licencié de contrôler, par tous
-moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et
-de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens.
-
-9.2 Le Concédant déclare de bonne foi être en droit de concéder
-l'ensemble des droits attachés au Logiciel (comprenant notamment les
-droits visés à l'article 5).
-
-9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le
-Concédant sans autre garantie, expresse ou tacite, que celle prévue à
-l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale,
-son caractère sécurisé, innovant ou pertinent.
-
-En particulier, le Concédant ne garantit pas que le Logiciel est exempt
-d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible
-avec l'équipement du Licencié et sa configuration logicielle ni qu'il
-remplira les besoins du Licencié.
-
-9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le
-Logiciel ne porte pas atteinte à un quelconque droit de propriété
-intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout
-autre droit de propriété. Ainsi, le Concédant exclut toute garantie au
-profit du Licencié contre les actions en contrefaçon qui pourraient être
-diligentées au titre de l'utilisation, de la modification, et de la
-redistribution du Logiciel. Néanmoins, si de telles actions sont
-exercées contre le Licencié, le Concédant lui apportera son aide
-technique et juridique pour sa défense. Cette aide technique et
-juridique est déterminée au cas par cas entre le Concédant concerné et
-le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage
-toute responsabilité quant à l'utilisation de la dénomination du
-Logiciel par le Licencié. Aucune garantie n'est apportée quant à
-l'existence de droits antérieurs sur le nom du Logiciel et sur
-l'existence d'une marque.
-
-
- Article 10 - RESILIATION
-
-10.1 En cas de manquement par le Licencié aux obligations mises à sa
-charge par le Contrat, le Concédant pourra résilier de plein droit le
-Contrat trente (30) jours après notification adressée au Licencié et
-restée sans effet.
-
-10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à
-utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les
-licences qu'il aura concédées antérieurement à la résiliation du Contrat
-resteront valides sous réserve qu'elles aient été effectuées en
-conformité avec le Contrat.
-
-
- Article 11 - DISPOSITIONS DIVERSES
-
-
- 11.1 CAUSE EXTERIEURE
-
-Aucune des Parties ne sera responsable d'un retard ou d'une défaillance
-d'exécution du Contrat qui serait dû à un cas de force majeure, un cas
-fortuit ou une cause extérieure, telle que, notamment, le mauvais
-fonctionnement ou les interruptions du réseau électrique ou de
-télécommunication, la paralysie du réseau liée à une attaque
-informatique, l'intervention des autorités gouvernementales, les
-catastrophes naturelles, les dégâts des eaux, les tremblements de terre,
-le feu, les explosions, les grèves et les conflits sociaux, l'état de
-guerre...
-
-11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou
-plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du
-Contrat, ne pourra en aucun cas impliquer renonciation par la Partie
-intéressée à s'en prévaloir ultérieurement.
-
-11.3 Le Contrat annule et remplace toute convention antérieure, écrite
-ou orale, entre les Parties sur le même objet et constitue l'accord
-entier entre les Parties sur cet objet. Aucune addition ou modification
-aux termes du Contrat n'aura d'effet à l'égard des Parties à moins
-d'être faite par écrit et signée par leurs représentants dûment habilités.
-
-11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat
-s'avèrerait contraire à une loi ou à un texte applicable, existants ou
-futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les
-amendements nécessaires pour se conformer à cette loi ou à ce texte.
-Toutes les autres dispositions resteront en vigueur. De même, la
-nullité, pour quelque raison que ce soit, d'une des dispositions du
-Contrat ne saurait entraîner la nullité de l'ensemble du Contrat.
-
-
- 11.5 LANGUE
-
-Le Contrat est rédigé en langue française et en langue anglaise, ces
-deux versions faisant également foi.
-
-
- Article 12 - NOUVELLES VERSIONS DU CONTRAT
-
-12.1 Toute personne est autorisée à copier et distribuer des copies de
-ce Contrat.
-
-12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé
-et ne peut être modifié que par les auteurs de la licence, lesquels se
-réservent le droit de publier périodiquement des mises à jour ou de
-nouvelles versions du Contrat, qui posséderont chacune un numéro
-distinct. Ces versions ultérieures seront susceptibles de prendre en
-compte de nouvelles problématiques rencontrées par les logiciels libres.
-
-12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra
-faire l'objet d'une diffusion ultérieure que sous la même version du
-Contrat ou une version postérieure, sous réserve des dispositions de
-l'article 5.3.4.
-
-
- Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE
-
-13.1 Le Contrat est régi par la loi française. Les Parties conviennent
-de tenter de régler à l'amiable les différends ou litiges qui
-viendraient à se produire par suite ou à l'occasion du Contrat.
-
-13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter
-de leur survenance et sauf situation relevant d'une procédure d'urgence,
-les différends ou litiges seront portés par la Partie la plus diligente
-devant les Tribunaux compétents de Paris.
-
-
-Version 2.0 du 2006-09-05.
+++ /dev/null
-PACKAGE = eztelemeta
-VERSION = 0.1
-
-DOCS = VERSION ChangeLog doc/README.fr doc/README.fr.html doc/doc.css doc/README.fr.latex \
- doc/README.fr.pdf doc/player.png LICENCE LICENCE.fr
-
-SETTINGS = \
- settings/content.ini.append \
- settings/design.ini.append \
- settings/site.ini.append \
- settings/override.ini.append
-
-TEMPLATES = \
- design/standard/templates/content/datatype/view/eztelemetaitem.tpl \
- design/standard/templates/content/datatype/edit/eztelemetaitem.tpl \
- design/standard/templates/eztelemeta_head.tpl \
- design/standard/override/templates/embed/eztelemetaitem.tpl \
- design/standard/override/templates/full/eztelemetaitem.tpl
-
-HTDOCS = \
- design/standard/stylesheets/eztelemeta.css \
- design/standard/javascript/soundmanager2.js \
- design/standard/javascript/soundmanager2-nodebug-jsmin.js \
- design/standard/javascript/eztelemeta-player.js \
- design/standard/swf/soundmanager2_flash9.swf \
- design/standard/swf/soundmanager2.swf \
- design/standard/images/play.gif \
- design/standard/images/stop.gif
-
-PHP = datatypes/eztelemetaitem/eztelemetaitemtype.php \
- autoloads/eztelemetadata.php \
- autoloads/eztemplateautoload.php
-
-I18N = translations/fre-FR/translation.ts
-
-DISTFILES = $(DOCS) $(SETTINGS) $(TEMPLATES) $(HTDOCS) $(PHP) $(I18N)
-
-DISTPKG = $(PACKAGE)-$(VERSION).tar.gz
-
-dist: $(DISTPKG)
-
-$(DISTPKG): doc $(DISTFILES)
- tar -czf $@ --transform 's|^|eztelemeta/|' $(DISTFILES)
-
-.PHONY: doc
-doc: VERSION
- $(MAKE) -C doc
-
-.PHONY: clean
-clean:
- $(MAKE) -C doc clean
- rm VERSION
-
-VERSION:
- echo $(VERSION) > $@
-
-.PHONY: list
-list: doc $(DISTFILES)
- @echo "------------------"
- @echo "Distributed files:"
- @echo "------------------"
- @echo $(DISTFILES) | tr ' ' '\n' > cmp.tmp
- @cat cmp.tmp
- @echo
- @echo "--------------------"
- @echo "Undistributed files:"
- @echo "--------------------"
- @find -type f | grep -v svn | grep -v 'swp$$' | sed 's/^\.\///' >> cmp.tmp
- @cat cmp.tmp | sort | uniq -u | grep -v 'cmp.tmp'
- @rm cmp.tmp
-
-# vim: set noexpandtab: ts=2: sw=2:
+++ /dev/null
-<?php
-/*
- * eZTelemeta page data handling
- *
- * Note: this is a simplified version of the eZPageData utility from ezwebin (GPL)
- *
- * Copyright (c) 1999-2009 eZ Systems AS, 2009 Samalyse
- * Author: Olivier Guilyardi <olivier samalyse com>
- * License: CeCILL Free Software License Agreement
- */
-
-/*
- Template operator to speed up page settings and style init time
- Gets its parameters directly from template.
- module_result.path | content_info | persistant_variable | menu.ini ++
- are all used to generate page data, what menues to show
- and so on.
-
-*/
-
-class eZTelemetaData
-{
- function eZTelemetaData()
- {
- }
-
- function operatorList()
- {
- return array( 'eztelemetadata_set', 'eztelemetadata_append' );
- }
-
- function namedParameterPerOperator()
- {
- return true;
- }
-
- function namedParameterList()
- {
- return array( 'eztelemetadata_set' => array(
- 'key' => array( 'type' => 'string',
- 'required' => true,
- 'default' => false ),
- 'value' => array( 'type' => 'mixed',
- 'required' => true,
- 'default' => false ) ),
- 'eztelemetadata_append' => array(
- 'key' => array( 'type' => 'string',
- 'required' => true,
- 'default' => false ),
- 'value' => array( 'type' => 'mixed',
- 'required' => true,
- 'default' => false ) ) );
- }
-
- function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters )
- {
- switch ( $operatorName )
- {
- // note: these functions are not cache-block safe
- // as in: if called inside a cache-block then they will not be called when cache is used.
- case 'eztelemetadata_set':
- case 'eztelemetadata_append':
- {
- self::setPersistentVariable( $namedParameters['key'], $namedParameters['value'], $tpl, $operatorName === 'eztelemetadata_append' );
- }break;
- }
- }
-
- // reusable function for setting persistent_variable
- static public function setPersistentVariable( $key, $value, $tpl, $append = false )
- {
- $persistentVariable = array();
- if ( $tpl->hasVariable('persistent_variable') && is_array( $tpl->variable('persistent_variable') ) )
- {
- $persistentVariable = $tpl->variable('persistent_variable');
- }
- else if ( self::$persistentVariable !== null && is_array( self::$persistentVariable ) )
- {
- $persistentVariable = self::$persistentVariable;
- }
-
- if ( $append )
- {
- if ( isset( $persistentVariable[ $key ] ) && is_array( $persistentVariable[ $key ] ) )
- {
- $persistentVariable[ $key ][] = $value;
- }
- else
- {
- $persistentVariable[ $key ] = array( $value );
- }
- }
- else
- {
- $persistentVariable[ $key ] = $value;
- }
-
- // set the finnished array in the template
- $tpl->setVariable('persistent_variable', $persistentVariable);
-
- // storing the value internally as well in case this is not a view that supports persistent_variable (eztelemetadata will look for it)
- self::$persistentVariable = $persistentVariable;
- }
-
- // reusable function for getting persistent_variable
- static public function getPersistentVariable( $key = null )
- {
- if ( $key !== null )
- {
- if ( isset( self::$persistentVariable[ $key ] ) )
- return self::$persistentVariable[ $key ];
- return null;
- }
- return self::$persistentVariable;
- }
-
- // Internal version of the $persistent_variable used on view that don't support it
- static protected $persistentVariable = null;
-
-}
-
-?>
+++ /dev/null
-<?php
-/*
- * eZTelemeta page data handling
- *
- * Copyright (c) 2009 Samalyse
- * Author: Olivier Guilyardi <olivier samalyse com>
- * License: CeCILL Free Software License Agreement
- */
-
-$eZTemplateOperatorArray = array();
-$eZTemplateOperatorArray[] = array( 'script' => 'extension/eztelemeta/autoloads/eztelemetadata.php',
- 'class' => 'eZTelemetaData',
- 'operator_names' => array( 'eztelemetadata_set', 'eztelemetadata_append' ) );
-?>
+++ /dev/null
-<?php
-/**
- * Definition of the Telemeta Item datatype
- *
- * @package eztelemeta
- * @author Olivier Guilyardi <olivier samalyse com>
- * @copyright 2009 Samalyse
- * @license CeCILL Free Software License Agreement
- */
-
-/**
- * Class definining the Telemeta Item datatype
- *
- * @package eztelemeta
- * @author Olivier Guilyardi
- * @copyright 2009 Samalyse
- * @license CeCILL Free Software License Agreement
- */
-class eZTelemetaItemType extends eZDataType
-{
- const DATA_TYPE_STRING = 'eztelemetaitem';
-
- public function __construct()
- {
- parent::__construct(self::DATA_TYPE_STRING, 'Telemeta Item');
- }
-
- function validateObjectAttributeHTTPInput($http, $base, $attribute)
- {
- $idvar = "{$base}_itemid_" . $attribute->attribute('id');
- $urlvar = "{$base}_url_" . $attribute->attribute('id');
- if ($http->hasPostVariable($idvar)) {
- $itemId = trim($http->postVariable($idvar));
- $url = trim($http->postVariable($urlvar));
- $classAttribute = $attribute->contentClassAttribute();
- if ($classAttribute->attribute("is_required")) {
- if (!$itemId) {
- $attribute->setValidationError(ezi18n('content/datatypes',
- "A valid Telemeta Item identifier is required",
- __CLASS__));
- return eZInputValidator::STATE_INVALID;
- }
- if (!$url) {
- $attribute->setValidationError(ezi18n('content/datatypes',
- "A valid Telemeta URL is required",
- __CLASS__));
- return eZInputValidator::STATE_INVALID;
- }
- }
- $item = $this->initItem($url, $itemId);
- try {
- $this->fetchItem($item);
- } catch (eZTelemetaError $e) {
- $attribute->setValidationError(ezi18n('content/datatypes', $e->getMessage(), __CLASS__));
- return eZInputValidator::STATE_INVALID;
- }
- }
- return eZInputValidator::STATE_ACCEPTED;
- }
-
- function initItem($url, $itemId)
- {
- return array(
- 'id' => $itemId,
- 'url' => $url,
- 'title' => '',
- 'creator' => '',
- 'description' => '',
- 'rights' => '',
- 'mp3' => '',
- 'duration' => 0,
- 'duration_str' => ''
- );
- }
-
- function fetchItem($item)
- {
- $url = $item['url'];
- if (!ereg('^http://', $url)) {
- $url = "http://$url";
- }
- $url = ereg_replace('/*$', '', $url);
- $encodedId = urlencode($item['id']);
- $request = "$url/oai/?verb=GetRecord&identifier=item:$encodedId&metadataPrefix=oai_dc";
-
- $doc = new DOMDocument();
- if (!@$doc->load($request)) {
- throw new eZTelemetaError("The Telemeta server couldn't be reached or returned malformed XML (request: $request)");
- }
-
- $root = $doc->getElementsByTagName('OAI-PMH');
- if (!$root->length)
- throw new eZTelemetaError("Retrieved XML document isn't a valid OAI-PMH response");
-
- $root = $root->item(0);
- $error = $root->getElementsByTagName('error');
- if ($error->length) {
- $msg = $error->item(0)->firstChild->nodeValue;
- throw new eZTelemetaError("Telemeta OAI-PMH error: $msg");
- }
-
- $record = $root->getElementsByTagName('GetRecord');
- if (!$record->length) {
- throw new eZTelemetaError("Retrieved XML document isn't a valid OAI-PMH response (missing GetRecord tag)");
- }
-
- $dc = $record->item(0)->getElementsByTagNameNS('*', 'dc')->item(0);
- $result = $this->initItem($item['url'], $item['id']);
- foreach ($dc->childNodes as $element) {
- if ($element->nodeType == XML_ELEMENT_NODE) {
- $tag = str_replace('dc:', '', $element->tagName);
- $value = $element->childNodes->length ? trim($element->firstChild->nodeValue) : '';
- if ($tag == 'format' and ereg('^([0-9]{2}):([0-9]{2}):([0-9]{2})$', $value, $regs)) {
- $tag = 'duration';
- $value = $regs[1] * 3600 + $regs[2] * 60 + $regs[3];
- }
- if (array_key_exists($tag, $result) and empty($result[$tag])) {
- $result[$tag] = $value;
- }
- }
- }
-
- if (!$result['title']) {
- throw new eZTelemetaError("The retrieved item has no title");
- }
-
- if ($result['duration']) {
- $d = $result['duration'];
- $result['duration_str'] = sprintf("%02d:%02d:%02d", $d / 3600, $d % 3600 / 60, $d % 3600 % 60);
- } else {
- throw new eZTelemetaError("The retrieved item has no duration (no sound file?)");
- }
-
- $result['mp3'] = "$url/items/download/$encodedId.mp3";
-
- return array_merge($item, $result);
- }
-
- function fetchObjectAttributeHTTPInput($http, $base, $attribute)
- {
- $idvar = "{$base}_itemid_" . $attribute->attribute('id');
- $urlvar = "{$base}_url_" . $attribute->attribute('id');
- if ($http->hasPostVariable($idvar)) {
- $itemId = trim($http->postVariable($idvar));
- $url = trim($http->postVariable($urlvar));
- $item = $this->initItem($url, $itemId);
- try {
- $item = $this->fetchItem($item);
- } catch (eZTelemetaError $e) {
- }
- $attribute->setAttribute("data_text", serialize($item));
- }
- return true;
- }
-
- function objectAttributeContent($attribute)
- {
- $item = unserialize($attribute->attribute("data_text"));
- try {
- $filled = $this->fetchItem($item);
- return $filled;
- } catch (eZTelemetaError $e) {
- return $item;
- }
- }
-
- function metaData($attribute)
- {
- $data = unserialize($attribute->attribute("data_text"));
- $words = array();
- $src = $data['title'] . ' ' . $data['description'];
- $cut = split('[ =+()[{}_,.:;\\/"\'*#%!?&-]+', $src);
- foreach ($cut as $w) {
- if (strlen($w) >= 3) {
- $words[] = $w;
- }
- }
- $words = join(" ", $words);
- file_put_contents("/tmp/c{$data['id']}", $words);
- return $words;
- }
-
- function title($attribute, $name = null)
- {
- $item = $this->objectAttributeContent($attribute);
- if (!$item['title'])
- return 'untitled';
- return $item['title'];
- }
-
- function isIndexable()
- {
- return true;
- }
-
-}
-
-class eZTelemetaError extends ezcBaseException
-{
- public function __construct($msg)
- {
- parent::__construct($msg);
- }
-
-}
-
-eZDataType::register(eZTelemetaItemType::DATA_TYPE_STRING, "eztelemetaitemtype");
+++ /dev/null
-/*
- * eZTelemeta web audio player
- *
- * Copyright (c) 2009 Samalyse
- * Author: Olivier Guilyardi <olivier samalyse com>
- * License: CeCILL Free Software License Agreement
- */
-
-function TelemetaPlayer(cfg)
-{
- var that = this;
- var soundManager = null;
- var sound = null;
- var currentLink = null;
-
- this.init = function() {
- var sounds = this.byClass(document, 'dd', 'telemeta-sound');
- var i;
- for (i in sounds) {
- if (typeof(sounds[i].getElementsByTagName) != 'undefined') {
- link = sounds[i].getElementsByTagName('a')[0];
- link.onclick = this.togglePlayback;
- }
- }
- }
-
- this.findContainer = function(link) {
- var e = link;
- while (e) {
- e = e.parentNode;
- if (this.hasClass(e, 'telemeta-item'))
- break;
- if (e == document)
- e = null;
- }
- return e;
- }
-
- this.setStateStyle = function(link, state) {
- var container = this.findContainer(link);
- if (state == 'stopped') {
- if (this.hasClass(container, 'telemeta-playing'))
- container.className = container.className.replace('telemeta-playing', '');
- }
-
- if (state == 'stopped' || state == 'playing') {
- if (this.hasClass(container, 'telemeta-loading'))
- container.className = container.className.replace('telemeta-loading', '');
- }
-
- if (state == 'playing' || state == 'loading') {
- if (!this.hasClass(container, 'telemeta-playing'))
- container.className += ' telemeta-playing';
- if (state == 'loading') {
- if (!this.hasClass(container, 'telemeta-loading'))
- container.className += ' telemeta-loading';
- }
- }
- }
-
- this.togglePlayback = function() {
- var link = this;
- if (that.soundManager) {
- if (that.sound)
- that.sound.stop();
- if (that.currentLink) {
- that.setStateStyle(that.currentLink, 'stopped');
- that.updatePosition(0);
- }
- if (!that.currentLink || that.currentLink != link) {
- that.sound = that.soundManager.createSound({
- id: 'telemeta_sound',
- url: link.href,
- whileplaying: function() { that.update(); },
- onbufferchange: function() { that.update(); }
- });
- that.currentLink = link;
- that.sound.play();
- that.setStateStyle(link, 'loading');
- that.updatePosition(0);
- } else {
- that.currentLink = null;
- }
- }
- return false;
- }
-
- this.updatePosition = function(position)
- {
- var container = that.findContainer(that.currentLink)
- var positionContainer = that.byClass(container, 'span', 'telemeta-position')[0];
-
- function format(i) { i = '' + parseInt(i); return i.length < 2 ? '0' + i : i; }
-
- var hours = format(position / 3600);
- var mins = format(position % 3600 / 60);
- var secs = format(position % 3600 % 60);
- positionContainer.firstChild.nodeValue = hours + ':' + mins + ':' + secs;
- }
-
- this.update = function()
- {
- that.updatePosition(that.sound.position / 1000);
- if (that.sound.isBuffering) {
- that.setStateStyle(that.currentLink, 'loading');
- } else {
- that.setStateStyle(that.currentLink, 'playing');
- }
- }
-
- this.hasClass = function(element, className) {
- if (typeof(element.className) != 'undefined')
- return new RegExp('(^|\\s)' + className + '(\\s|$)').test(element.className);
-
- return false;
- }
-
- this.byClass = function(root, tag, className) {
- var result = [];
- var nodes = root.getElementsByTagName(tag);
- var i;
- for (i = 0; i < nodes.length; i++) {
- if (this.hasClass(nodes[i], className))
- result.push(nodes[i]);
- }
- return result;
- }
-
- this.setSoundManager = function(soundManager) {
- this.soundManager = soundManager;
- }
-
- TelemetaDom.ready(function() { that.init(cfg); });
-}
-
-(function(){
-
- var DomReady = window.TelemetaDom = {};
-
- // Everything that has to do with properly supporting our document ready event. Brought over from the most awesome jQuery.
-
- var userAgent = navigator.userAgent.toLowerCase();
-
- // Figure out what browser is being used
- var browser = {
- version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
- safari: /webkit/.test(userAgent),
- opera: /opera/.test(userAgent),
- msie: (/msie/.test(userAgent)) && (!/opera/.test( userAgent )),
- mozilla: (/mozilla/.test(userAgent)) && (!/(compatible|webkit)/.test(userAgent))
- };
-
- var readyBound = false;
- var isReady = false;
- var readyList = [];
-
- // Handle when the DOM is ready
- function domReady() {
- // Make sure that the DOM is not already loaded
- if(!isReady) {
- // Remember that the DOM is ready
- isReady = true;
-
- if(readyList) {
- for(var fn = 0; fn < readyList.length; fn++) {
- readyList[fn].call(window, []);
- }
-
- readyList = [];
- }
- }
- };
-
- // From Simon Willison. A safe way to fire onload w/o screwing up everyone else.
- function addLoadEvent(func) {
- var oldonload = window.onload;
- if (typeof window.onload != 'function') {
- window.onload = func;
- } else {
- window.onload = function() {
- if (oldonload) {
- oldonload();
- }
- func();
- }
- }
- };
-
- // does the heavy work of working through the browsers idiosyncracies (let's call them that) to hook onload.
- function bindReady() {
- if(readyBound) {
- return;
- }
-
- readyBound = true;
-
- // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
- if (document.addEventListener && !browser.opera) {
- // Use the handy event callback
- document.addEventListener("DOMContentLoaded", domReady, false);
- }
-
- // If IE is used and is not in a frame
- // Continually check to see if the document is ready
- if (browser.msie && window == top) (function(){
- if (isReady) return;
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch(error) {
- setTimeout(arguments.callee, 0);
- return;
- }
- // and execute any waiting functions
- domReady();
- })();
-
- if(browser.opera) {
- document.addEventListener( "DOMContentLoaded", function () {
- if (isReady) return;
- for (var i = 0; i < document.styleSheets.length; i++)
- if (document.styleSheets[i].disabled) {
- setTimeout( arguments.callee, 0 );
- return;
- }
- // and execute any waiting functions
- domReady();
- }, false);
- }
-
- if(browser.safari) {
- var numStyles;
- (function(){
- if (isReady) return;
- if (document.readyState != "loaded" && document.readyState != "complete") {
- setTimeout( arguments.callee, 0 );
- return;
- }
- if (numStyles === undefined) {
- var links = document.getElementsByTagName("link");
- for (var i=0; i < links.length; i++) {
- if(links[i].getAttribute('rel') == 'stylesheet') {
- numStyles++;
- }
- }
- var styles = document.getElementsByTagName("style");
- numStyles += styles.length;
- }
- if (document.styleSheets.length != numStyles) {
- setTimeout( arguments.callee, 0 );
- return;
- }
-
- // and execute any waiting functions
- domReady();
- })();
- }
-
- // A fallback to window.onload, that will always work
- addLoadEvent(domReady);
- };
-
- // This is the public function that people can use to hook up ready.
- DomReady.ready = function(fn, args) {
- // Attach the listeners
- bindReady();
-
- // If the DOM is already ready
- if (isReady) {
- // Execute the function immediately
- fn.call(window, []);
- } else {
- // Add the function to the wait list
- readyList.push( function() { return fn.call(window, []); } );
- }
- };
-
- bindReady();
-
-})();
+++ /dev/null
-/*\r
- SoundManager 2: Javascript Sound for the Web\r
- --------------------------------------------\r
- http://schillmania.com/projects/soundmanager2/\r
-\r
- Copyright (c) 2008, Scott Schiller. All rights reserved.\r
- Code licensed under the BSD License:\r
- http://schillmania.com/projects/soundmanager2/license.txt\r
-\r
- V2.94a.20090206\r
-*/\r
-var soundManager=null;function SoundManager(b,a){this.flashVersion=8;this.debugMode=true;this.useConsole=true;this.consoleOnly=false;this.waitForWindowLoad=false;this.nullURL="null.mp3";this.allowPolling=true;this.useMovieStar=false;this.bgColor="#ffffff";this.useHighPerformance=false;this.flashLoadTimeout=750;this.defaultOptions={autoLoad:false,stream:true,autoPlay:false,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5000,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:true,position:null,pan:0,volume:100};this.flash9Options={onbufferchange:null,isMovieStar:null,usePeakData:false,useWaveformData:false,useEQData:false};this.movieStarOptions={onmetadata:null,useVideo:false};var f=null;var e=this;this.version=null;this.versionNumber="V2.94a.20090206";this.movieURL=null;this.url=null;this.altURL=null;this.swfLoaded=false;this.enabled=false;this.o=null;this.id=(a||"sm2movie");this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=false;this.wmode=null;this.isIE=(navigator.userAgent.match(/MSIE/i));this.isSafari=(navigator.userAgent.match(/safari/i));this.isGecko=(navigator.userAgent.match(/gecko/i));this.debugID="soundmanager-debug";this._debugOpen=true;this._didAppend=false;this._appendSuccess=false;this._didInit=false;this._disabled=false;this._windowLoaded=false;this._hasConsole=(typeof console!="undefined"&&typeof console.log!="undefined");this._debugLevels=["log","info","warn","error"];this._defaultFlashVersion=8;this._oRemoved=null;this._oRemovedHTML=null;var g=function(h){return document.getElementById(h)};this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.netStreamTypes=["aac","flv","mov","mp4","m4v","f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=new RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.filePattern=null;this.features={buffering:false,peakData:false,waveformData:false,eqData:false,movieStar:false};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local + internet access)"},description:null,noRemote:null,noLocal:null};this._setVersionInfo=function(){if(e.flashVersion!=8&&e.flashVersion!=9){alert('soundManager.flashVersion must be 8 or 9. "'+e.flashVersion+'" is invalid. Reverting to '+e._defaultFlashVersion+".");e.flashVersion=e._defaultFlashVersion}e.version=e.versionNumber+(e.flashVersion==9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(e.flashVersion>8){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.flash9Options);e.features.buffering=true}if(e.flashVersion>8&&e.useMovieStar){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.movieStarOptions);e.filePatterns.flash9=new RegExp("\\.(mp3|"+e.netStreamTypes.join("|")+")(\\?.*)?$","i");e.features.movieStar=true}else{e.useMovieStar=false;e.features.movieStar=false}e.filePattern=e.filePatterns[(e.flashVersion!=8?"flash9":"flash8")];e.movieURL=(e.flashVersion==8?"soundmanager2.swf":"soundmanager2_flash9.swf");e.features.peakData=e.features.waveformData=e.features.eqData=(e.flashVersion==9)};this._overHTTP=(document.location?document.location.protocol.match(/http/i):null);this._waitingforEI=false;this._initPending=false;this._tryInitOnFocus=(this.isSafari&&typeof document.hasFocus=="undefined");this._isFocused=(typeof document.hasFocus!="undefined"?document.hasFocus():null);this._okToDisable=!this._tryInitOnFocus;this.useAltURL=!this._overHTTP;var d="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html";this.supported=function(){return(e._didInit&&!e._disabled)};this.getMovie=function(h){return e.isIE?window[h]:(e.isSafari?g(h)||document[h]:g(h))};this.loadFromXML=function(h){try{e.o._loadFromXML(h)}catch(i){e._failSafely();return true}};this.createSound=function(i){if(!e._didInit){throw new Error("soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods")}if(arguments.length==2){i={id:arguments[0],url:arguments[1]}}var j=e._mergeObjects(i);var h=j;if(e._idCheck(h.id,true)){return e.sounds[h.id]}if(e.flashVersion>8&&e.useMovieStar){if(h.isMovieStar===null){h.isMovieStar=(h.url.match(e.netStreamPattern)?true:false)}if(h.isMovieStar&&(h.usePeakData||h.useWaveformData||h.useEQData)){h.usePeakData=false;h.useWaveformData=false;h.useEQData=false}}e.sounds[h.id]=new f(h);e.soundIDs[e.soundIDs.length]=h.id;if(e.flashVersion==8){e.o._createSound(h.id,h.onjustbeforefinishtime)}else{e.o._createSound(h.id,h.url,h.onjustbeforefinishtime,h.usePeakData,h.useWaveformData,h.useEQData,h.isMovieStar,(h.isMovieStar?h.useVideo:false))}if(h.autoLoad||h.autoPlay){if(e.sounds[h.id]){e.sounds[h.id].load(h)}}if(h.autoPlay){e.sounds[h.id].play()}return e.sounds[h.id]};this.createVideo=function(h){if(arguments.length==2){h={id:arguments[0],url:arguments[1]}}if(e.flashVersion>=9){h.isMovieStar=true;h.useVideo=true}else{return false}return e.createSound(h)};this.destroySound=function(j,h){if(!e._idCheck(j)){return false}for(var k=0;k<e.soundIDs.length;k++){if(e.soundIDs[k]==j){e.soundIDs.splice(k,1);continue}}e.sounds[j].unload();if(!h){e.sounds[j].destruct()}delete e.sounds[j]};this.destroyVideo=this.destroySound;this.load=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].load(i)};this.unload=function(h){if(!e._idCheck(h)){return false}e.sounds[h].unload()};this.play=function(h,i){if(!e._idCheck(h)){if(typeof i!="Object"){i={url:i}}if(i&&i.url){i.id=h;e.createSound(i)}else{return false}}e.sounds[h].play(i)};this.start=this.play;this.setPosition=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].setPosition(i)};this.stop=function(h){if(!e._idCheck(h)){return false}e.sounds[h].stop()};this.stopAll=function(){for(var h in e.sounds){if(e.sounds[h] instanceof f){e.sounds[h].stop()}}};this.pause=function(h){if(!e._idCheck(h)){return false}e.sounds[h].pause()};this.pauseAll=function(){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].pause()}};this.resume=function(h){if(!e._idCheck(h)){return false}e.sounds[h].resume()};this.resumeAll=function(){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].resume()}};this.togglePause=function(h){if(!e._idCheck(h)){return false}e.sounds[h].togglePause()};this.setPan=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].setPan(i)};this.setVolume=function(i,h){if(!e._idCheck(i)){return false}e.sounds[i].setVolume(h)};this.mute=function(h){if(typeof h!="string"){h=null}if(!h){for(var j=e.soundIDs.length;j--;){e.sounds[e.soundIDs[j]].mute()}e.muted=true}else{if(!e._idCheck(h)){return false}e.sounds[h].mute()}};this.muteAll=function(){e.mute()};this.unmute=function(h){if(typeof h!="string"){h=null}if(!h){for(var j=e.soundIDs.length;j--;){e.sounds[e.soundIDs[j]].unmute()}e.muted=false}else{if(!e._idCheck(h)){return false}e.sounds[h].unmute()}};this.unmuteAll=function(){e.unmute()};this.getMemoryUse=function(){if(e.flashVersion==8){return 0}if(e.o){return parseInt(e.o._getMemoryUse(),10)}};this.setPolling=function(h){if(!e.o||!e.allowPolling){return false}e.o._setPolling(h)};this.disable=function(j){if(typeof j=="undefined"){j=false}if(e._disabled){return false}e._disabled=true;for(var h=e.soundIDs.length;h--;){e._disableObject(e.sounds[e.soundIDs[h]])}e.initComplete(j)};this.canPlayURL=function(h){return(h?(h.match(e.filePattern)?true:false):null)};this.getSoundById=function(i,j){if(!i){throw new Error("SoundManager.getSoundById(): sID is null/undefined")}var h=e.sounds[i];return h};this.onload=function(){soundManager._wD("<em>Warning</em>: soundManager.onload() is undefined.",2)};this.onerror=function(){};this._idCheck=this.getSoundById;var c=function(){return false};c._protected=true;this._disableObject=function(i){for(var h in i){if(typeof i[h]=="function"&&typeof i[h]._protected=="undefined"){i[h]=c}}h=null};this._failSafely=function(h){if(typeof h=="undefined"){h=false}if(!e._disabled||h){e.disable(h)}};this._normalizeMovieURL=function(h){var i=null;if(h){if(h.match(/\.swf(\?.*)?$/i)){i=h.substr(h.toLowerCase().lastIndexOf(".swf?")+4);if(i){return h}}else{if(h.lastIndexOf("/")!=h.length-1){h=h+"/"}}}return(h&&h.lastIndexOf("/")!=-1?h.substr(0,h.lastIndexOf("/")+1):"./")+e.movieURL};this._getDocument=function(){return(document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName("div")[0]))};this._getDocument._protected=true;this._createMovie=function(n,l){if(e._didAppend&&e._appendSuccess){return false}if(window.location.href.indexOf("debug=1")+1){e.debugMode=true}e._didAppend=true;e._setVersionInfo();var u=(l?l:e.url);var k=(e.altURL?e.altURL:u);e.url=e._normalizeMovieURL(e._overHTTP?u:k);l=e.url;var m=null;if(e.useHighPerformance&&e.useMovieStar){m="Note: disabling highPerformance, not applicable with movieStar mode on";e.useHighPerformance=false}e.wmode=(e.useHighPerformance&&!e.useMovieStar?"transparent":"");var t={name:n,id:n,src:l,width:"100%",height:"100%",quality:"high",allowScriptAccess:"always",bgcolor:e.bgColor,pluginspage:"http://www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash",wmode:e.wmode};var w={id:n,data:l,type:"application/x-shockwave-flash",width:"100%",height:"100%",wmode:e.wmode};var o={movie:l,AllowScriptAccess:"always",quality:"high",bgcolor:e.bgColor,wmode:e.wmode};var j=null;var r=null;if(e.isIE){j=document.createElement("div");var h='<object id="'+n+'" data="'+l+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+l+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(e.useHighPerformance&&!e.useMovieStar?'<param name="wmode" value="'+e.wmode+'" /> ':"")+'<param name="bgcolor" value="'+e.bgColor+'" /><!-- --></object>'}else{j=document.createElement("embed");for(r in t){if(t.hasOwnProperty(r)){j.setAttribute(r,t[r])}}}var q="soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.";var i=e._getDocument();if(i){e.oMC=g("sm2-container")?g("sm2-container"):document.createElement("div");if(!e.oMC.id){e.oMC.id="sm2-container";e.oMC.className="movieContainer";var z=null;var p=null;if(e.useHighPerformance){z={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px"}}else{z={position:"absolute",width:"1px",height:"1px",top:"-999px",left:"-999px"}}var y=null;for(y in z){if(z.hasOwnProperty(y)){e.oMC.style[y]=z[y]}}try{if(!e.isIE){e.oMC.appendChild(j)}i.appendChild(e.oMC);if(e.isIE){p=e.oMC.appendChild(document.createElement("div"));p.className="sm2-object-box";p.innerHTML=h}e._appendSuccess=true}catch(v){throw new Error(q)}}else{e.oMC.appendChild(j);if(e.isIE){p=e.oMC.appendChild(document.createElement("div"));p.className="sm2-object-box";p.innerHTML=h}e._appendSuccess=true}}};this._writeDebug=function(h,j,i){};this._writeDebug._protected=true;this._wdCount=0;this._wdCount._protected=true;this._wD=this._writeDebug;this._toggleDebug=function(){};this._toggleDebug._protected=true;this._debug=function(){};this._debugTS=function(j,h,i){};this._debugTS._protected=true;this._mergeObjects=function(j,h){var m={};for(var k in j){if(j.hasOwnProperty(k)){m[k]=j[k]}}var l=(typeof h=="undefined"?e.defaultOptions:h);for(var n in l){if(l.hasOwnProperty(n)&&typeof m[n]=="undefined"){m[n]=l[n]}}return m};this.createMovie=function(h){if(h){e.url=h}e._initMovie()};this.go=this.createMovie;this._initMovie=function(){if(e.o){return false}e.o=e.getMovie(e.id);if(!e.o){if(!e.oRemoved){e._createMovie(e.id,e.url)}else{if(!e.isIE){e.oMC.appendChild(e.oRemoved)}else{e.oMC.innerHTML=e.oRemovedHTML}e.oRemoved=null;e._didAppend=true}e.o=e.getMovie(e.id)}};this.waitForExternalInterface=function(){if(e._waitingForEI){return false}e._waitingForEI=true;if(e._tryInitOnFocus&&!e._isFocused){return false}if(e.flashLoadTimeout>0){setTimeout(function(){if(!e._didInit&&e._okToDisable){e._failSafely(true)}},e.flashLoadTimeout)}};this.handleFocus=function(){if(e._isFocused||!e._tryInitOnFocus){return true}e._okToDisable=true;e._isFocused=true;if(e._tryInitOnFocus){window.removeEventListener("mousemove",e.handleFocus,false)}e._waitingForEI=false;setTimeout(e.waitForExternalInterface,500);if(window.removeEventListener){window.removeEventListener("focus",e.handleFocus,false)}else{if(window.detachEvent){window.detachEvent("onfocus",e.handleFocus)}}};this.initComplete=function(h){if(e._didInit){return false}e._didInit=true;if(e._disabled||h){e.onerror.apply(window);return false}else{}if(e.waitForWindowLoad&&!e._windowLoaded){if(window.addEventListener){window.addEventListener("load",e.initUserOnload,false)}else{if(window.attachEvent){window.attachEvent("onload",e.initUserOnload)}}return false}else{e.initUserOnload()}};this.initUserOnload=function(){e.onload.apply(window)};this.init=function(){e._initMovie();if(e._didInit){return false}if(window.removeEventListener){window.removeEventListener("load",e.beginDelayedInit,false)}else{if(window.detachEvent){window.detachEvent("onload",e.beginDelayedInit)}}try{e.o._externalInterfaceTest(false);e.setPolling(true);if(!e.debugMode){e.o._disableDebug()}e.enabled=true}catch(h){e._failSafely(true);e.initComplete();return false}e.initComplete()};this.beginDelayedInit=function(){e._windowLoaded=true;setTimeout(e.waitForExternalInterface,500);setTimeout(e.beginInit,20)};this.beginInit=function(){if(e._initPending){return false}e.createMovie();e._initMovie();e._initPending=true;return true};this.domContentLoaded=function(){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",e.domContentLoaded,false)}e.go()};this._externalInterfaceOK=function(){if(e.swfLoaded){return false}e.swfLoaded=true;e._tryInitOnFocus=false;if(e.isIE){setTimeout(e.init,100)}else{e.init()}};this._setSandboxType=function(h){var i=e.sandbox;i.type=h;i.description=i.types[(typeof i.types[h]!="undefined"?h:"unknown")];if(i.type=="localWithFile"){i.noRemote=true;i.noLocal=false}else{if(i.type=="localWithNetwork"){i.noRemote=false;i.noLocal=true}else{if(i.type=="localTrusted"){i.noRemote=false;i.noLocal=false}}}};this.reboot=function(){if(e.soundIDs.length){}for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].destruct()}try{if(e.isIE){e.oRemovedHTML=e.o.innerHTML}e.oRemoved=e.o.parentNode.removeChild(e.o)}catch(j){}e.enabled=false;e._didInit=false;e._waitingForEI=false;e._initPending=false;e._didInit=false;e._didAppend=false;e._appendSuccess=false;e._didInit=false;e._disabled=false;e._waitingforEI=true;e.swfLoaded=false;e.soundIDs={};e.sounds=[];e.o=null;window.setTimeout(function(){soundManager.beginDelayedInit()},20)};this.destruct=function(){e.disable(true)};f=function(h){var i=this;this.sID=h.id;this.url=h.url;this.options=e._mergeObjects(h);this.instanceOptions=this.options;this._iO=this.instanceOptions;this.pan=this.options.pan;this.volume=this.options.volume;this._debug=function(){if(e.debugMode){var l=null;var n=[];var k=null;var m=null;var j=64;for(l in i.options){if(i.options[l]!==null){if(i.options[l] instanceof Function){k=i.options[l].toString();k=k.replace(/\s\s+/g," ");m=k.indexOf("{");n[n.length]=" "+l+": {"+k.substr(m+1,(Math.min(Math.max(k.indexOf("\n")-1,j),j))).replace(/\n/g,"")+"... }"}else{n[n.length]=" "+l+": "+i.options[l]}}}}};this._debug();this.id3={};this.resetProperties=function(j){i.bytesLoaded=null;i.bytesTotal=null;i.position=null;i.duration=null;i.durationEstimate=null;i.loaded=false;i.playState=0;i.paused=false;i.readyState=0;i.muted=false;i.didBeforeFinish=false;i.didJustBeforeFinish=false;i.isBuffering=false;i.instanceOptions={};i.instanceCount=0;i.peakData={left:0,right:0};i.waveformData=[];i.eqData=[]};i.resetProperties();this.load=function(j){if(typeof j!="undefined"){i._iO=e._mergeObjects(j);i.instanceOptions=i._iO}else{j=i.options;i._iO=j;i.instanceOptions=i._iO}if(typeof i._iO.url=="undefined"){i._iO.url=i.url}if(i._iO.url==i.url&&i.readyState!==0&&i.readyState!=2){return false}i.loaded=false;i.readyState=1;i.playState=0;try{if(e.flashVersion==8){e.o._load(i.sID,i._iO.url,i._iO.stream,i._iO.autoPlay,(i._iO.whileloading?1:0))}else{e.o._load(i.sID,i._iO.url,i._iO.stream?true:false,i._iO.autoPlay?true:false);if(i._iO.isMovieStar&&i._iO.autoLoad&&!i._iO.autoPlay){i.pause()}}}catch(k){e.onerror();e.disable()}};this.unload=function(){if(i.readyState!==0){if(i.readyState!=2){i.setPosition(0,true)}e.o._unload(i.sID,e.nullURL);i.resetProperties()}};this.destruct=function(){e.o._destroySound(i.sID);e.destroySound(i.sID,true)};this.play=function(k){if(!k){k={}}i._iO=e._mergeObjects(k,i._iO);i._iO=e._mergeObjects(i._iO,i.options);i.instanceOptions=i._iO;if(i.playState==1){var j=i._iO.multiShot;if(!j){return false}}if(!i.loaded){if(i.readyState===0){i._iO.stream=true;i._iO.autoPlay=true;i.load(i._iO)}else{if(i.readyState==2){return false}}}if(i.paused){i.resume()}else{i.playState=1;if(!i.instanceCount||e.flashVersion==9){i.instanceCount++}i.position=(typeof i._iO.position!="undefined"&&!isNaN(i._iO.position)?i._iO.position:0);if(i._iO.onplay){i._iO.onplay.apply(i)}i.setVolume(i._iO.volume,true);i.setPan(i._iO.pan,true);e.o._start(i.sID,i._iO.loop||1,(e.flashVersion==9?i.position:i.position/1000))}};this.start=this.play;this.stop=function(j){if(i.playState==1){i.playState=0;i.paused=false;if(i._iO.onstop){i._iO.onstop.apply(i)}e.o._stop(i.sID,j);i.instanceCount=0;i._iO={}}};this.setPosition=function(k,j){if(typeof k=="undefined"){k=0}var l=Math.min(i.duration,Math.max(k,0));i._iO.position=l;e.o._setPosition(i.sID,(e.flashVersion==9?i._iO.position:i._iO.position/1000),(i.paused||!i.playState))};this.pause=function(){if(i.paused||i.playState===0){return false}i.paused=true;e.o._pause(i.sID);if(i._iO.onpause){i._iO.onpause.apply(i)}};this.resume=function(){if(!i.paused||i.playState===0){return false}i.paused=false;e.o._pause(i.sID);if(i._iO.onresume){i._iO.onresume.apply(i)}};this.togglePause=function(){if(!i.playState){i.play({position:(e.flashVersion==9?i.position:i.position/1000)});return false}if(i.paused){i.resume()}else{i.pause()}};this.setPan=function(k,j){if(typeof k=="undefined"){k=0}if(typeof j=="undefined"){j=false}e.o._setPan(i.sID,k);i._iO.pan=k;if(!j){i.pan=k}};this.setVolume=function(j,k){if(typeof j=="undefined"){j=100}if(typeof k=="undefined"){k=false}e.o._setVolume(i.sID,(e.muted&&!i.muted)||i.muted?0:j);i._iO.volume=j;if(!k){i.volume=j}};this.mute=function(){i.muted=true;e.o._setVolume(i.sID,0)};this.unmute=function(){i.muted=false;var j=typeof i._iO.volume!="undefined";e.o._setVolume(i.sID,j?i._iO.volume:i.options.volume)};this._whileloading=function(j,k,l){if(!i._iO.isMovieStar){i.bytesLoaded=j;i.bytesTotal=k;i.duration=Math.floor(l);i.durationEstimate=parseInt((i.bytesTotal/i.bytesLoaded)*i.duration,10);if(i.readyState!=3&&i._iO.whileloading){i._iO.whileloading.apply(i)}}else{i.bytesLoaded=j;i.bytesTotal=k;i.duration=Math.floor(l);i.durationEstimate=i.duration;if(i.readyState!=3&&i._iO.whileloading){i._iO.whileloading.apply(i)}}};this._onid3=function(n,k){var o=[];for(var m=0,l=n.length;m<l;m++){o[n[m]]=k[m]}i.id3=e._mergeObjects(i.id3,o);if(i._iO.onid3){i._iO.onid3.apply(i)}};this._whileplaying=function(k,l,j,m){if(isNaN(k)||k===null){return false}i.position=k;if(i._iO.usePeakData&&typeof l!="undefined"&&l){i.peakData={left:l.leftPeak,right:l.rightPeak}}if(i._iO.useWaveformData&&typeof j!="undefined"&&j){i.waveformData=j}if(i._iO.useEQData&&typeof m!="undefined"&&m){i.eqData=m}if(i.playState==1){if(i._iO.whileplaying){i._iO.whileplaying.apply(i)}if(i.loaded&&i._iO.onbeforefinish&&i._iO.onbeforefinishtime&&!i.didBeforeFinish&&i.duration-i.position<=i._iO.onbeforefinishtime){i._onbeforefinish()}}};this._onload=function(j){j=(j==1?true:false);i.loaded=j;i.readyState=j?3:2;if(i._iO.onload){i._iO.onload.apply(i)}};this._onbeforefinish=function(){if(!i.didBeforeFinish){i.didBeforeFinish=true;if(i._iO.onbeforefinish){i._iO.onbeforefinish.apply(i)}}};this._onjustbeforefinish=function(j){if(!i.didJustBeforeFinish){i.didJustBeforeFinish=true;if(i._iO.onjustbeforefinish){i._iO.onjustbeforefinish.apply(i)}}};this._onfinish=function(){if(i._iO.onbeforefinishcomplete){i._iO.onbeforefinishcomplete.apply(i)}i.didBeforeFinish=false;i.didJustBeforeFinish=false;if(i.instanceCount){i.instanceCount--;if(!i.instanceCount){i.playState=0;i.paused=false;i.instanceCount=0;i.instanceOptions={};if(i._iO.onfinish){i._iO.onfinish.apply(i)}}}else{}};this._onmetadata=function(j){if(!j.width&&!j.height){j.width=320;j.height=240}i.metadata=j;i.width=j.width;i.height=j.height;if(i._iO.onmetadata){i._iO.onmetadata.apply(i)}};this._onbufferchange=function(j){if(j==i.isBuffering){return false}i.isBuffering=(j==1?true:false);if(i._iO.onbufferchange){i._iO.onbufferchange.apply(i)}}};if(window.addEventListener){window.addEventListener("focus",e.handleFocus,false);window.addEventListener("load",e.beginDelayedInit,false);window.addEventListener("unload",e.destruct,false);if(e._tryInitOnFocus){window.addEventListener("mousemove",e.handleFocus,false)}}else{if(window.attachEvent){window.attachEvent("onfocus",e.handleFocus);window.attachEvent("onload",e.beginDelayedInit);window.attachEvent("unload",e.destruct)}else{soundManager.onerror();soundManager.disable()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",e.domContentLoaded,false)}}soundManager=new SoundManager();
\ No newline at end of file
+++ /dev/null
-/*!\r
- SoundManager 2: Javascript Sound for the Web\r
- --------------------------------------------\r
- http://schillmania.com/projects/soundmanager2/\r
-\r
- Copyright (c) 2008, Scott Schiller. All rights reserved.\r
- Code licensed under the BSD License:\r
- http://schillmania.com/projects/soundmanager2/license.txt\r
-\r
- V2.94a.20090206\r
-*/\r
-\r
-var soundManager = null;\r
-\r
-function SoundManager(smURL,smID) {\r
- \r
- this.flashVersion = 8; // version of flash to require, either 8 or 9. Some API features require Flash 9.\r
- this.debugMode = true; // enable debugging output (div#soundmanager-debug, OR console if available + configured)\r
- this.useConsole = true; // use firebug/safari console.log()-type debug console if available\r
- this.consoleOnly = false; // if console is being used, do not create/write to #soundmanager-debug\r
- this.waitForWindowLoad = false; // force SM2 to wait for window.onload() before trying to call soundManager.onload()\r
- this.nullURL = 'null.mp3'; // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)\r
- this.allowPolling = true; // allow flash to poll for status update (required for "while playing", peak, sound spectrum functions to work.)\r
- this.useMovieStar = false; // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio + video formats (AAC, M4V, FLV, MOV etc.)\r
- this.bgColor = '#ffffff'; // movie (.swf) background color, useful if showing on-screen for video etc.\r
- this.useHighPerformance = false; // position:fixed flash movie gives increased js/flash speed\r
- this.flashLoadTimeout = 750; // ms to wait for flash movie to load before failing (0 = infinity)\r
-\r
- this.defaultOptions = {\r
- 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)\r
- 'stream': true, // allows playing before entire file has loaded (recommended)\r
- 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)\r
- 'onid3': null, // callback function for "ID3 data is added/available"\r
- 'onload': null, // callback function for "load finished"\r
- 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)\r
- 'onplay': null, // callback for "play" start\r
- 'onpause': null, // callback for "pause"\r
- 'onresume': null, // callback for "resume" (pause toggle)\r
- 'whileplaying': null, // callback during play (position update)\r
- 'onstop': null, // callback for "user stop"\r
- 'onfinish': null, // callback function for "sound finished playing"\r
- 'onbeforefinish': null, // callback for "before sound finished playing (at [time])"\r
- 'onbeforefinishtime': 5000, // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)\r
- 'onbeforefinishcomplete':null, // function to call when said sound finishes playing\r
- 'onjustbeforefinish':null, // callback for [n] msec before end of current sound\r
- 'onjustbeforefinishtime':200, // [n] - if not using, set to 0 (or null handler) and event will not fire.\r
- 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time\r
- 'position': null, // offset (milliseconds) to seek to within loaded sound data.\r
- 'pan': 0, // "pan" settings, left-to-right, -100 to 100\r
- 'volume': 100 // self-explanatory. 0-100, the latter being the max.\r
- };\r
-\r
- this.flash9Options = { // flash 9-only options, merged into defaultOptions if flash 9 is being used\r
- 'onbufferchange': null, // callback for "isBuffering" property change\r
- 'isMovieStar': null, // "MovieStar" MPEG4 audio/video mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL\r
- 'usePeakData': false, // enable left/right channel peak (level) data\r
- 'useWaveformData': false, // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.\r
- 'useEQData': false // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.\r
- };\r
-\r
- this.movieStarOptions = { // flash 9.0r115+ MPEG4 audio/video options, merged into defaultOptions if flash 9 + movieStar mode is enabled\r
- 'onmetadata': null, // callback for when video width/height etc. are received\r
- 'useVideo': false // if loading movieStar content, whether to show video\r
- };\r
-\r
- // jslint global declarations\r
- /*global sm2Debugger, alert, console, document, navigator, setTimeout, window */\r
-\r
- var SMSound = null; // defined later\r
-\r
- var _s = this;\r
- this.version = null;\r
- this.versionNumber = 'V2.94a.20090206';\r
- this.movieURL = null;\r
- this.url = null;\r
- this.altURL = null;\r
- this.swfLoaded = false;\r
- this.enabled = false;\r
- this.o = null;\r
- this.id = (smID||'sm2movie');\r
- this.oMC = null;\r
- this.sounds = {};\r
- this.soundIDs = [];\r
- this.muted = false;\r
- this.wmode = null;\r
- this.isIE = (navigator.userAgent.match(/MSIE/i));\r
- this.isSafari = (navigator.userAgent.match(/safari/i));\r
- this.isGecko = (navigator.userAgent.match(/gecko/i));\r
- this.debugID = 'soundmanager-debug';\r
- this._debugOpen = true;\r
- this._didAppend = false;\r
- this._appendSuccess = false;\r
- this._didInit = false;\r
- this._disabled = false;\r
- this._windowLoaded = false;\r
- this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined');\r
- this._debugLevels = ['log','info','warn','error'];\r
- this._defaultFlashVersion = 8;\r
- this._oRemoved = null;\r
- this._oRemovedHTML = null;\r
-\r
- var _$ = function(sID) {\r
- return document.getElementById(sID);\r
- };\r
-\r
- this.filePatterns = {\r
- flash8: /\.mp3(\?.*)?$/i,\r
- flash9: /\.mp3(\?.*)?$/i\r
- };\r
-\r
- this.netStreamTypes = ['aac','flv','mov','mp4','m4v','f4v','m4a','mp4v','3gp','3g2']; // Flash v9.0r115+ "moviestar" formats\r
- this.netStreamPattern = new RegExp('\\.('+this.netStreamTypes.join('|')+')(\\?.*)?$','i');\r
-\r
- this.filePattern = null;\r
- this.features = {\r
- buffering: false,\r
- peakData: false,\r
- waveformData: false,\r
- eqData: false,\r
- movieStar: false\r
- };\r
-\r
- this.sandbox = {\r
- 'type': null,\r
- 'types': {\r
- 'remote': 'remote (domain-based) rules',\r
- 'localWithFile': 'local with file access (no internet access)',\r
- 'localWithNetwork': 'local with network (internet access only, no local access)',\r
- 'localTrusted': 'local, trusted (local + internet access)'\r
- },\r
- 'description': null,\r
- 'noRemote': null,\r
- 'noLocal': null\r
- };\r
-\r
- this._setVersionInfo = function() {\r
- if (_s.flashVersion != 8 && _s.flashVersion != 9) {\r
- alert('soundManager.flashVersion must be 8 or 9. "'+_s.flashVersion+'" is invalid. Reverting to '+_s._defaultFlashVersion+'.');\r
- _s.flashVersion = _s._defaultFlashVersion;\r
- }\r
- _s.version = _s.versionNumber+(_s.flashVersion==9?' (AS3/Flash 9)':' (AS2/Flash 8)');\r
- // set up default options\r
- if (_s.flashVersion > 8) {\r
- _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.flash9Options);\r
- _s.features.buffering = true;\r
- }\r
- if (_s.flashVersion > 8 && _s.useMovieStar) {\r
- // flash 9+ support for movieStar formats as well as MP3\r
- _s.defaultOptions = _s._mergeObjects(_s.defaultOptions,_s.movieStarOptions);\r
- _s.filePatterns.flash9 = new RegExp('\\.(mp3|'+_s.netStreamTypes.join('|')+')(\\?.*)?$','i');\r
- _s.features.movieStar = true;\r
- } else {\r
- _s.useMovieStar = false;\r
- _s.features.movieStar = false;\r
- }\r
- _s.filePattern = _s.filePatterns[(_s.flashVersion!=8?'flash9':'flash8')];\r
- _s.movieURL = (_s.flashVersion==8?'soundmanager2.swf':'soundmanager2_flash9.swf');\r
- _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_s.flashVersion==9);\r
- };\r
-\r
- this._overHTTP = (document.location?document.location.protocol.match(/http/i):null);\r
- this._waitingforEI = false;\r
- this._initPending = false;\r
- this._tryInitOnFocus = (this.isSafari && typeof document.hasFocus == 'undefined');\r
- this._isFocused = (typeof document.hasFocus != 'undefined'?document.hasFocus():null);\r
- this._okToDisable = !this._tryInitOnFocus;\r
-\r
- this.useAltURL = !this._overHTTP; // use altURL if not "online"\r
-\r
- var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html';\r
-\r
- // --- public methods ---\r
- \r
- this.supported = function() {\r
- return (_s._didInit && !_s._disabled);\r
- };\r
-\r
- this.getMovie = function(smID) {\r
- return _s.isIE?window[smID]:(_s.isSafari?_$(smID)||document[smID]:_$(smID));\r
- };\r
-\r
- this.loadFromXML = function(sXmlUrl) {\r
- try {\r
- _s.o._loadFromXML(sXmlUrl);\r
- } catch(e) {\r
- _s._failSafely();\r
- return true;\r
- }\r
- };\r
-\r
- this.createSound = function(oOptions) {\r
- if (!_s._didInit) {\r
- throw new Error('soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods');\r
- }\r
- if (arguments.length == 2) {\r
- // function overloading in JS! :) ..assume simple createSound(id,url) use case\r
- oOptions = {'id':arguments[0],'url':arguments[1]};\r
- }\r
- var thisOptions = _s._mergeObjects(oOptions); // inherit SM2 defaults\r
- var _tO = thisOptions; // alias\r
- _s._wD('soundManager.createSound(): '+_tO.id+' ('+_tO.url+')',1);\r
- if (_s._idCheck(_tO.id,true)) {\r
- _s._wD('soundManager.createSound(): '+_tO.id+' exists',1);\r
- return _s.sounds[_tO.id];\r
- }\r
- if (_s.flashVersion > 8 && _s.useMovieStar) {\r
- if (_tO.isMovieStar === null) {\r
- _tO.isMovieStar = (_tO.url.match(_s.netStreamPattern)?true:false);\r
- }\r
- if (_tO.isMovieStar) {\r
- _s._wD('soundManager.createSound(): using MovieStar handling');\r
- }\r
- if (_tO.isMovieStar && (_tO.usePeakData || _tO.useWaveformData || _tO.useEQData)) {\r
- _s._wD('Warning: peak/waveform/eqData features unsupported for non-MP3 formats');\r
- _tO.usePeakData = false;\r
- _tO.useWaveformData = false;\r
- _tO.useEQData = false;\r
- }\r
- }\r
- _s.sounds[_tO.id] = new SMSound(_tO);\r
- _s.soundIDs[_s.soundIDs.length] = _tO.id;\r
- // AS2:\r
- if (_s.flashVersion == 8) {\r
- _s.o._createSound(_tO.id,_tO.onjustbeforefinishtime);\r
- } else {\r
- _s.o._createSound(_tO.id,_tO.url,_tO.onjustbeforefinishtime,_tO.usePeakData,_tO.useWaveformData,_tO.useEQData,_tO.isMovieStar,(_tO.isMovieStar?_tO.useVideo:false));\r
- }\r
- if (_tO.autoLoad || _tO.autoPlay) {\r
- // TODO: does removing timeout here cause problems?\r
- if (_s.sounds[_tO.id]) {\r
- _s.sounds[_tO.id].load(_tO);\r
- }\r
- }\r
- if (_tO.autoPlay) {\r
- _s.sounds[_tO.id].play();\r
- }\r
- return _s.sounds[_tO.id];\r
- };\r
-\r
- this.createVideo = function(oOptions) {\r
- if (arguments.length==2) {\r
- oOptions = {'id':arguments[0],'url':arguments[1]};\r
- }\r
- if (_s.flashVersion >= 9) {\r
- oOptions.isMovieStar = true;\r
- oOptions.useVideo = true;\r
- } else {\r
- _s._wD('soundManager.createVideo(): flash 9 required for video. Exiting.',2);\r
- return false;\r
- }\r
- if (!_s.useMovieStar) {\r
- _s._wD('soundManager.createVideo(): MovieStar mode not enabled. Exiting.',2);\r
- }\r
- return _s.createSound(oOptions);\r
- };\r
-\r
- this.destroySound = function(sID,bFromSound) {\r
- // explicitly destroy a sound before normal page unload, etc.\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- for (var i=0; i<_s.soundIDs.length; i++) {\r
- if (_s.soundIDs[i] == sID) {\r
- _s.soundIDs.splice(i,1);\r
- continue;\r
- }\r
- }\r
- // conservative option: avoid crash with ze flash 8\r
- // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP + flash 8??\r
- // if (_s.flashVersion != 8) {\r
- _s.sounds[sID].unload();\r
- // }\r
- if (!bFromSound) {\r
- // ignore if being called from SMSound instance\r
- _s.sounds[sID].destruct();\r
- }\r
- delete _s.sounds[sID];\r
- };\r
-\r
- this.destroyVideo = this.destroySound;\r
-\r
- this.load = function(sID,oOptions) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].load(oOptions);\r
- };\r
-\r
- this.unload = function(sID) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].unload();\r
- };\r
-\r
- this.play = function(sID,oOptions) {\r
- if (!_s._idCheck(sID)) {\r
- if (typeof oOptions != 'Object') {\r
- oOptions = {url:oOptions}; // overloading use case: play('mySound','/path/to/some.mp3');\r
- }\r
- if (oOptions && oOptions.url) {\r
- // overloading use case, creation + playing of sound: .play('someID',{url:'/path/to.mp3'});\r
- _s._wD('soundController.play(): attempting to create "'+sID+'"',1);\r
- oOptions.id = sID;\r
- _s.createSound(oOptions);\r
- } else {\r
- return false;\r
- }\r
- }\r
- _s.sounds[sID].play(oOptions);\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.setPosition = function(sID,nMsecOffset) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].setPosition(nMsecOffset);\r
- };\r
-\r
- this.stop = function(sID) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD('soundManager.stop('+sID+')',1);\r
- _s.sounds[sID].stop(); \r
- };\r
-\r
- this.stopAll = function() {\r
- _s._wD('soundManager.stopAll()',1);\r
- for (var oSound in _s.sounds) {\r
- if (_s.sounds[oSound] instanceof SMSound) {\r
- _s.sounds[oSound].stop(); // apply only to sound objects\r
- }\r
- }\r
- };\r
-\r
- this.pause = function(sID) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].pause();\r
- };\r
-\r
- this.pauseAll = function() {\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].pause();\r
- }\r
- };\r
-\r
- this.resume = function(sID) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].resume();\r
- };\r
-\r
- this.resumeAll = function() {\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].resume();\r
- }\r
- };\r
-\r
- this.togglePause = function(sID) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].togglePause();\r
- };\r
-\r
- this.setPan = function(sID,nPan) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].setPan(nPan);\r
- };\r
-\r
- this.setVolume = function(sID,nVol) {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s.sounds[sID].setVolume(nVol);\r
- };\r
-\r
- this.mute = function(sID) {\r
- if (typeof sID != 'string') {\r
- sID = null;\r
- }\r
- if (!sID) {\r
- _s._wD('soundManager.mute(): Muting all sounds');\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].mute();\r
- }\r
- _s.muted = true;\r
- } else {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD('soundManager.mute(): Muting "'+sID+'"');\r
- _s.sounds[sID].mute();\r
- }\r
- };\r
-\r
- this.muteAll = function() {\r
- _s.mute();\r
- };\r
-\r
- this.unmute = function(sID) {\r
- if (typeof sID != 'string') {\r
- sID = null;\r
- }\r
- if (!sID) {\r
- _s._wD('soundManager.unmute(): Unmuting all sounds');\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].unmute();\r
- }\r
- _s.muted = false;\r
- } else {\r
- if (!_s._idCheck(sID)) {\r
- return false;\r
- }\r
- _s._wD('soundManager.unmute(): Unmuting "'+sID+'"');\r
- _s.sounds[sID].unmute();\r
- }\r
- };\r
-\r
- this.unmuteAll = function() {\r
- _s.unmute();\r
- };\r
-\r
- this.getMemoryUse = function() {\r
- if (_s.flashVersion == 8) {\r
- // not supported in Flash 8\r
- return 0;\r
- }\r
- if (_s.o) {\r
- return parseInt(_s.o._getMemoryUse(),10);\r
- }\r
- };\r
-\r
- this.setPolling = function(bPolling) {\r
- if (!_s.o || !_s.allowPolling) {\r
- return false;\r
- }\r
- _s.o._setPolling(bPolling);\r
- };\r
-\r
- this.disable = function(bNoDisable) {\r
- // destroy all functions\r
- if (typeof bNoDisable == 'undefined') {\r
- bNoDisable = false;\r
- }\r
- if (_s._disabled) {\r
- return false;\r
- }\r
- _s._disabled = true;\r
- _s._wD('soundManager.disable(): Shutting down',1);\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s._disableObject(_s.sounds[_s.soundIDs[i]]);\r
- }\r
- _s.initComplete(bNoDisable); // fire "complete", despite fail\r
- // _s._disableObject(_s); // taken out to allow reboot()\r
- };\r
-\r
- this.canPlayURL = function(sURL) {\r
- return (sURL?(sURL.match(_s.filePattern)?true:false):null); \r
- };\r
-\r
- this.getSoundById = function(sID,suppressDebug) {\r
- if (!sID) {\r
- throw new Error('SoundManager.getSoundById(): sID is null/undefined');\r
- }\r
- var result = _s.sounds[sID];\r
- if (!result && !suppressDebug) {\r
- _s._wD('"'+sID+'" is an invalid sound ID.',2);\r
- // soundManager._wD('trace: '+arguments.callee.caller);\r
- }\r
- return result;\r
- };\r
-\r
- this.onload = function() {\r
- // window.onload() equivalent for SM2, ready to create sounds etc.\r
- // this is a stub - you can override this in your own external script, eg. soundManager.onload = function() {}\r
- soundManager._wD('<em>Warning</em>: soundManager.onload() is undefined.',2);\r
- };\r
-\r
- this.onerror = function() {\r
- // stub for user handler, called when SM2 fails to load/init\r
- };\r
-\r
- // --- "private" methods ---\r
-\r
- this._idCheck = this.getSoundById;\r
-\r
- var _doNothing = function() {\r
- return false;\r
- };\r
- _doNothing._protected = true;\r
-\r
- this._disableObject = function(o) {\r
- for (var oProp in o) {\r
- if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') {\r
- o[oProp] = _doNothing;\r
- }\r
- }\r
- oProp = null;\r
- };\r
-\r
- this._failSafely = function(bNoDisable) {\r
- // general failure exception handler\r
- if (typeof bNoDisable == 'undefined') {\r
- bNoDisable = false;\r
- }\r
- if (!_s._disabled || bNoDisable) {\r
- _s._wD('soundManager: Failed to initialise.',2);\r
- _s.disable(bNoDisable);\r
- }\r
- };\r
- \r
- this._normalizeMovieURL = function(smURL) {\r
- var urlParams = null;\r
- if (smURL) {\r
- if (smURL.match(/\.swf(\?.*)?$/i)) {\r
- urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?')+4);\r
- if (urlParams) {\r
- return smURL; // assume user knows what they're doing\r
- }\r
- } else if (smURL.lastIndexOf('/') != smURL.length-1) {\r
- smURL = smURL+'/';\r
- }\r
- }\r
- return(smURL && smURL.lastIndexOf('/')!=-1?smURL.substr(0,smURL.lastIndexOf('/')+1):'./')+_s.movieURL;\r
- };\r
-\r
- this._getDocument = function() {\r
- return (document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName('div')[0]));\r
- };\r
-\r
- this._getDocument._protected = true;\r
-\r
- this._createMovie = function(smID,smURL) {\r
- if (_s._didAppend && _s._appendSuccess) {\r
- return false; // ignore if already succeeded\r
- }\r
- if (window.location.href.indexOf('debug=1')+1) {\r
- _s.debugMode = true; // allow force of debug mode via URL\r
- }\r
- _s._didAppend = true;\r
- \r
- // safety check for legacy (change to Flash 9 URL)\r
- _s._setVersionInfo();\r
- var remoteURL = (smURL?smURL:_s.url);\r
- var localURL = (_s.altURL?_s.altURL:remoteURL);\r
- _s.url = _s._normalizeMovieURL(_s._overHTTP?remoteURL:localURL);\r
- smURL = _s.url;\r
-\r
- var specialCase = null;\r
-\r
- if (_s.useHighPerformance && _s.useMovieStar) {\r
- specialCase = 'Note: disabling highPerformance, not applicable with movieStar mode on';\r
- _s.useHighPerformance = false;\r
- }\r
-\r
- _s.wmode = (_s.useHighPerformance && !_s.useMovieStar?'transparent':''); // wmode=opaque seems to break firefox/windows.\r
-\r
- var oEmbed = {\r
- name: smID,\r
- id: smID,\r
- src: smURL,\r
- width: '100%',\r
- height: '100%',\r
- quality: 'high',\r
- allowScriptAccess: 'always',\r
- bgcolor: _s.bgColor,\r
- pluginspage: 'http://www.macromedia.com/go/getflashplayer',\r
- type: 'application/x-shockwave-flash',\r
- wmode: _s.wmode\r
- };\r
-\r
- var oObject = {\r
- id: smID,\r
- data: smURL,\r
- type: 'application/x-shockwave-flash',\r
- width: '100%',\r
- height: '100%',\r
- wmode: _s.wmode\r
- };\r
-\r
- var oObjectParams = {\r
- movie: smURL,\r
- AllowScriptAccess: 'always',\r
- quality: 'high',\r
- bgcolor: _s.bgColor,\r
- wmode: _s.wmode\r
- };\r
-\r
- var oMovie = null;\r
- var tmp = null;\r
-\r
- if (_s.isIE) {\r
- // IE is "special".\r
- oMovie = document.createElement('div');\r
- var movieHTML = '<object id="'+smID+'" data="'+smURL+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+smURL+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(_s.useHighPerformance && !_s.useMovieStar?'<param name="wmode" value="'+_s.wmode+'" /> ':'')+'<param name="bgcolor" value="'+_s.bgColor+'" /><!-- --></object>';\r
- } else {\r
- oMovie = document.createElement('embed');\r
- for (tmp in oEmbed) {\r
- if (oEmbed.hasOwnProperty(tmp)) {\r
- oMovie.setAttribute(tmp,oEmbed[tmp]);\r
- }\r
- }\r
- }\r
-\r
- var oD = document.createElement('div');\r
- oD.id = _s.debugID+'-toggle';\r
- var oToggle = {\r
- position: 'fixed',\r
- bottom: '0px',\r
- right: '0px',\r
- width: '1.2em',\r
- height: '1.2em',\r
- lineHeight: '1.2em',\r
- margin: '2px',\r
- textAlign: 'center',\r
- border: '1px solid #999',\r
- cursor: 'pointer',\r
- background: '#fff',\r
- color: '#333',\r
- zIndex: 10001\r
- };\r
-\r
- oD.appendChild(document.createTextNode('-'));\r
- oD.onclick = _s._toggleDebug;\r
- oD.title = 'Toggle SM2 debug console';\r
-\r
- if (navigator.userAgent.match(/msie 6/i)) {\r
- oD.style.position = 'absolute';\r
- oD.style.cursor = 'hand';\r
- }\r
-\r
- for (tmp in oToggle) {\r
- if (oToggle.hasOwnProperty(tmp)) {\r
- oD.style[tmp] = oToggle[tmp];\r
- }\r
- }\r
-\r
- var appXHTML = 'soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.';\r
-\r
- var oTarget = _s._getDocument();\r
-\r
- if (oTarget) {\r
- \r
- _s.oMC = _$('sm2-container')?_$('sm2-container'):document.createElement('div');\r
-\r
- if (!_s.oMC.id) {\r
- _s.oMC.id = 'sm2-container';\r
- _s.oMC.className = 'movieContainer';\r
- // "hide" flash movie\r
- var s = null;\r
- var oEl = null;\r
- if (_s.useHighPerformance) {\r
- s = {\r
- position: 'fixed',\r
- width: '8px',\r
- height: '8px', // must be at least 6px for flash to run fast. odd? yes.\r
- bottom: '0px',\r
- left: '0px'\r
- // zIndex:-1 // sit behind everything else - potentially dangerous/buggy?\r
- };\r
- } else {\r
- s = {\r
- position: 'absolute',\r
- width: '1px',\r
- height: '1px',\r
- top: '-999px',\r
- left: '-999px'\r
- };\r
- }\r
- var x = null;\r
- for (x in s) {\r
- if (s.hasOwnProperty(x)) {\r
- _s.oMC.style[x] = s[x];\r
- }\r
- }\r
- try {\r
- if (!_s.isIE) {\r
- _s.oMC.appendChild(oMovie);\r
- }\r
- oTarget.appendChild(_s.oMC);\r
- if (_s.isIE) {\r
- oEl = _s.oMC.appendChild(document.createElement('div'));\r
- oEl.className = 'sm2-object-box';\r
- oEl.innerHTML = movieHTML;\r
- }\r
- _s._appendSuccess = true;\r
- } catch(e) {\r
- throw new Error(appXHTML);\r
- }\r
- } else {\r
- // it's already in the document.\r
- _s.oMC.appendChild(oMovie);\r
- if (_s.isIE) {\r
- oEl = _s.oMC.appendChild(document.createElement('div'));\r
- oEl.className = 'sm2-object-box';\r
- oEl.innerHTML = movieHTML;\r
- }\r
- _s._appendSuccess = true;\r
- }\r
-\r
- if (!_$(_s.debugID) && ((!_s._hasConsole||!_s.useConsole)||(_s.useConsole && _s._hasConsole && !_s.consoleOnly))) {\r
- var oDebug = document.createElement('div');\r
- oDebug.id = _s.debugID;\r
- oDebug.style.display = (_s.debugMode?'block':'none');\r
- if (_s.debugMode && !_$(oD.id)) {\r
- try {\r
- oTarget.appendChild(oD);\r
- } catch(e2) {\r
- throw new Error(appXHTML);\r
- }\r
- oTarget.appendChild(oDebug);\r
- }\r
- }\r
- oTarget = null;\r
- }\r
-\r
- if (specialCase) {\r
- _s._wD(specialCase);\r
- }\r
-\r
- _s._wD('-- SoundManager 2 '+_s.version+(_s.useMovieStar?', MovieStar mode':'')+(_s.useHighPerformance?', high performance mode':'')+' --',1);\r
- _s._wD('soundManager._createMovie(): Trying to load '+smURL+(!_s._overHTTP && _s.altURL?'(alternate URL)':''),1);\r
- };\r
-\r
- // aliased to this._wD()\r
- this._writeDebug = function(sText,sType,bTimestamp) {\r
- if (!_s.debugMode) {\r
- return false;\r
- }\r
- if (typeof bTimestamp != 'undefined' && bTimestamp) {\r
- sText = sText + ' | '+new Date().getTime();\r
- }\r
- if (_s._hasConsole && _s.useConsole) {\r
- var sMethod = _s._debugLevels[sType];\r
- if (typeof console[sMethod] != 'undefined') {\r
- console[sMethod](sText);\r
- } else {\r
- console.log(sText);\r
- }\r
- if (_s.useConsoleOnly) {\r
- return true;\r
- }\r
- }\r
- var sDID = 'soundmanager-debug';\r
- try {\r
- var o = _$(sDID);\r
- if (!o) {\r
- return false;\r
- }\r
- var oItem = document.createElement('div');\r
- if (++_s._wdCount%2===0) {\r
- oItem.className = 'sm2-alt';\r
- }\r
- // sText = sText.replace(/\n/g,'<br />');\r
- if (typeof sType == 'undefined') {\r
- sType = 0;\r
- } else {\r
- sType = parseInt(sType,10);\r
- }\r
- oItem.appendChild(document.createTextNode(sText));\r
- if (sType) {\r
- if (sType >= 2) {\r
- oItem.style.fontWeight = 'bold';\r
- }\r
- if (sType == 3) {\r
- oItem.style.color = '#ff3333';\r
- }\r
- }\r
- // o.appendChild(oItem); // top-to-bottom\r
- o.insertBefore(oItem,o.firstChild); // bottom-to-top\r
- } catch(e) {\r
- // oh well\r
- }\r
- o = null;\r
- };\r
- this._writeDebug._protected = true;\r
- this._wdCount = 0;\r
- this._wdCount._protected = true;\r
- this._wD = this._writeDebug;\r
-\r
- this._wDAlert = function(sText) { alert(sText); };\r
-\r
- if (window.location.href.indexOf('debug=alert')+1 && _s.debugMode) {\r
- _s._wD = _s._wDAlert;\r
- }\r
-\r
- this._toggleDebug = function() {\r
- var o = _$(_s.debugID);\r
- var oT = _$(_s.debugID+'-toggle');\r
- if (!o) {\r
- return false;\r
- }\r
- if (_s._debugOpen) {\r
- // minimize\r
- oT.innerHTML = '+';\r
- o.style.display = 'none';\r
- } else {\r
- oT.innerHTML = '-';\r
- o.style.display = 'block';\r
- }\r
- _s._debugOpen = !_s._debugOpen;\r
- };\r
-\r
- this._toggleDebug._protected = true;\r
-\r
- this._debug = function() {\r
- _s._wD('--- soundManager._debug(): Current sound objects ---',1);\r
- for (var i=0,j=_s.soundIDs.length; i<j; i++) {\r
- _s.sounds[_s.soundIDs[i]]._debug();\r
- }\r
- };\r
-\r
- this._debugTS = function(sEventType,bSuccess,sMessage) {\r
- // troubleshooter debug hooks\r
- if (typeof sm2Debugger != 'undefined') {\r
- try {\r
- sm2Debugger.handleEvent(sEventType,bSuccess,sMessage);\r
- } catch(e) {\r
- // oh well \r
- }\r
- }\r
- };\r
-\r
- this._debugTS._protected = true;\r
-\r
- this._mergeObjects = function(oMain,oAdd) {\r
- // non-destructive merge\r
- var o1 = {}; // clone o1\r
- for (var i in oMain) {\r
- if (oMain.hasOwnProperty(i)) {\r
- o1[i] = oMain[i];\r
- }\r
- }\r
- var o2 = (typeof oAdd == 'undefined'?_s.defaultOptions:oAdd);\r
- for (var o in o2) {\r
- if (o2.hasOwnProperty(o) && typeof o1[o] == 'undefined') {\r
- o1[o] = o2[o];\r
- }\r
- }\r
- return o1;\r
- };\r
-\r
- this.createMovie = function(sURL) {\r
- if (sURL) {\r
- _s.url = sURL;\r
- }\r
- _s._initMovie();\r
- };\r
-\r
- this.go = this.createMovie; // nice alias\r
-\r
- this._initMovie = function() {\r
- // attempt to get, or create, movie\r
- if (_s.o) {\r
- return false; // may already exist\r
- }\r
- _s.o = _s.getMovie(_s.id); // (inline markup)\r
- if (!_s.o) {\r
- if (!_s.oRemoved) {\r
- // try to create\r
- _s._createMovie(_s.id,_s.url);\r
- } else {\r
- // try to re-append removed movie after reboot()\r
- if (!_s.isIE) {\r
- _s.oMC.appendChild(_s.oRemoved);\r
- } else {\r
- _s.oMC.innerHTML = _s.oRemovedHTML;\r
- }\r
- _s.oRemoved = null;\r
- _s._didAppend = true;\r
- }\r
- _s.o = _s.getMovie(_s.id);\r
- }\r
- if (_s.o) {\r
- _s._wD('soundManager._initMovie(): Got '+_s.o.nodeName+' element ('+(_s._didAppend?'created via JS':'static HTML')+')',1);\r
- if (_s.flashLoadTimeout>0) {\r
- _s._wD('soundManager._initMovie(): Waiting for ExternalInterface call from Flash..');\r
- }\r
- }\r
- };\r
-\r
- this.waitForExternalInterface = function() {\r
- if (_s._waitingForEI) {\r
- return false;\r
- }\r
- _s._waitingForEI = true;\r
- if (_s._tryInitOnFocus && !_s._isFocused) {\r
- _s._wD('soundManager: Special case: Waiting for focus-related event..');\r
- return false;\r
- }\r
- if (_s.flashLoadTimeout>0) {\r
- if (!_s._didInit) {\r
- _s._wD('soundManager: Getting impatient, still waiting for Flash.. ;)');\r
- }\r
- setTimeout(function() {\r
- if (!_s._didInit) {\r
- _s._wD('soundManager: No Flash response within reasonable time after document load.\nPossible causes: Flash version under 8, no support, or Flash security denying JS-Flash communication.',2);\r
- if (!_s._overHTTP) {\r
- _s._wD('soundManager: Loading this page from local/network file system (not over HTTP?) Flash security likely restricting JS-Flash access. Consider adding current URL to "trusted locations" in the Flash player security settings manager at '+flashCPLink+', or simply serve this content over HTTP.',2);\r
- }\r
- _s._debugTS('flashtojs',false,': Timed out'+(_s._overHTTP)?' (Check flash security)':' (No plugin/missing SWF?)');\r
- }\r
- // if still not initialized and no other options, give up\r
- if (!_s._didInit && _s._okToDisable) {\r
- _s._failSafely(true); // don't disable, for reboot()\r
- }\r
- },_s.flashLoadTimeout);\r
- } else if (!_s.didInit) {\r
- _s._wD('soundManager: Waiting indefinitely for Flash...');\r
- }\r
- };\r
-\r
- this.handleFocus = function() {\r
- if (_s._isFocused || !_s._tryInitOnFocus) {\r
- return true;\r
- }\r
- _s._okToDisable = true;\r
- _s._isFocused = true;\r
- _s._wD('soundManager.handleFocus()');\r
- if (_s._tryInitOnFocus) {\r
- // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented.\r
- window.removeEventListener('mousemove',_s.handleFocus,false);\r
- }\r
- // allow init to restart\r
- _s._waitingForEI = false;\r
- setTimeout(_s.waitForExternalInterface,500);\r
- // detach event\r
- if (window.removeEventListener) {\r
- window.removeEventListener('focus',_s.handleFocus,false);\r
- } else if (window.detachEvent) {\r
- window.detachEvent('onfocus',_s.handleFocus);\r
- }\r
- };\r
-\r
- this.initComplete = function(bNoDisable) {\r
- if (_s._didInit) {\r
- return false;\r
- }\r
- _s._didInit = true;\r
- _s._wD('-- SoundManager 2 '+(_s._disabled?'failed to load':'loaded')+' ('+(_s._disabled?'security/load error':'OK')+') --',1);\r
- if (_s._disabled || bNoDisable) {\r
- _s._wD('soundManager.initComplete(): calling soundManager.onerror()',1);\r
- _s._debugTS('onload',false);\r
- _s.onerror.apply(window);\r
- return false;\r
- } else {\r
- _s._debugTS('onload',true);\r
- }\r
- if (_s.waitForWindowLoad && !_s._windowLoaded) {\r
- _s._wD('soundManager: Waiting for window.onload()');\r
- if (window.addEventListener) {\r
- window.addEventListener('load',_s.initUserOnload,false);\r
- } else if (window.attachEvent) {\r
- window.attachEvent('onload',_s.initUserOnload);\r
- }\r
- return false;\r
- } else {\r
- if (_s.waitForWindowLoad && _s._windowLoaded) {\r
- _s._wD('soundManager: Document already loaded');\r
- }\r
- _s.initUserOnload();\r
- }\r
- };\r
-\r
- this.initUserOnload = function() {\r
- _s._wD('soundManager.initComplete(): calling soundManager.onload()',1);\r
- // call user-defined "onload", scoped to window\r
- _s.onload.apply(window);\r
- _s._wD('soundManager.onload() complete',1);\r
- };\r
-\r
- this.init = function() {\r
- _s._wD('-- soundManager.init() --');\r
- // called after onload()\r
- _s._initMovie();\r
- if (_s._didInit) {\r
- _s._wD('soundManager.init(): Already called?');\r
- return false;\r
- }\r
- // event cleanup\r
- if (window.removeEventListener) {\r
- window.removeEventListener('load',_s.beginDelayedInit,false);\r
- } else if (window.detachEvent) {\r
- window.detachEvent('onload',_s.beginDelayedInit);\r
- }\r
- try {\r
- _s._wD('Attempting to call Flash from JS..');\r
- _s.o._externalInterfaceTest(false); // attempt to talk to Flash\r
- // _s._wD('Flash ExternalInterface call (JS-Flash) OK',1);\r
- if (!_s.allowPolling) {\r
- _s._wD('Polling (whileloading/whileplaying support) is disabled.',1);\r
- }\r
- _s.setPolling(true);\r
- if (!_s.debugMode) {\r
- _s.o._disableDebug();\r
- }\r
- _s.enabled = true;\r
- _s._debugTS('jstoflash',true);\r
- } catch(e) {\r
- _s._debugTS('jstoflash',false);\r
- _s._failSafely(true); // don't disable, for reboot()\r
- _s.initComplete();\r
- return false;\r
- }\r
- _s.initComplete();\r
- };\r
-\r
- this.beginDelayedInit = function() {\r
- _s._wD('soundManager.beginDelayedInit()');\r
- _s._windowLoaded = true;\r
- setTimeout(_s.waitForExternalInterface,500);\r
- setTimeout(_s.beginInit,20);\r
- };\r
-\r
- this.beginInit = function() {\r
- if (_s._initPending) {\r
- return false;\r
- }\r
- _s.createMovie(); // ensure creation if not already done\r
- _s._initMovie();\r
- _s._initPending = true;\r
- return true;\r
- };\r
-\r
- this.domContentLoaded = function() {\r
- _s._wD('soundManager.domContentLoaded()');\r
- if (document.removeEventListener) {\r
- document.removeEventListener('DOMContentLoaded',_s.domContentLoaded,false);\r
- }\r
- _s.go();\r
- };\r
-\r
- this._externalInterfaceOK = function() {\r
- // callback from flash for confirming that movie loaded, EI is working etc.\r
- if (_s.swfLoaded) {\r
- return false;\r
- }\r
- _s._wD('soundManager._externalInterfaceOK()');\r
- _s._debugTS('swf',true);\r
- _s._debugTS('flashtojs',true);\r
- _s.swfLoaded = true;\r
- _s._tryInitOnFocus = false;\r
- if (_s.isIE) {\r
- // IE needs a timeout OR delay until window.onload - may need TODO: investigating\r
- setTimeout(_s.init,100);\r
- } else {\r
- _s.init();\r
- }\r
- };\r
-\r
- this._setSandboxType = function(sandboxType) {\r
- var sb = _s.sandbox;\r
- sb.type = sandboxType;\r
- sb.description = sb.types[(typeof sb.types[sandboxType] != 'undefined'?sandboxType:'unknown')];\r
- _s._wD('Flash security sandbox type: '+sb.type);\r
- if (sb.type == 'localWithFile') {\r
- sb.noRemote = true;\r
- sb.noLocal = false;\r
- _s._wD('Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html',2);\r
- } else if (sb.type == 'localWithNetwork') {\r
- sb.noRemote = false;\r
- sb.noLocal = true;\r
- } else if (sb.type == 'localTrusted') {\r
- sb.noRemote = false;\r
- sb.noLocal = false;\r
- }\r
- };\r
-\r
- this.reboot = function() {\r
- // attempt to reset and init SM2\r
- _s._wD('soundManager.reboot()');\r
- if (_s.soundIDs.length) {\r
- _s._wD('Destroying '+_s.soundIDs.length+' SMSound objects...');\r
- }\r
- for (var i=_s.soundIDs.length; i--;) {\r
- _s.sounds[_s.soundIDs[i]].destruct();\r
- }\r
- // trash ze flash\r
- try {\r
- if (_s.isIE) {\r
- _s.oRemovedHTML = _s.o.innerHTML;\r
- }\r
- _s.oRemoved = _s.o.parentNode.removeChild(_s.o);\r
- _s._wD('Flash movie removed.');\r
- } catch(e) {\r
- // uh-oh.\r
- _s._wD('Warning: Failed to remove flash movie.',2);\r
- }\r
- _s.enabled = false;\r
- _s._didInit = false;\r
- _s._waitingForEI = false;\r
- _s._initPending = false;\r
- _s._didInit = false;\r
- _s._didAppend = false;\r
- _s._appendSuccess = false;\r
- _s._didInit = false;\r
- _s._disabled = false;\r
- _s._waitingforEI = true;\r
- _s.swfLoaded = false;\r
- _s.soundIDs = {};\r
- _s.sounds = [];\r
- _s.o = null;\r
- _s._wD('soundManager: Rebooting...');\r
- window.setTimeout(function() {\r
- soundManager.beginDelayedInit();\r
- },20);\r
- };\r
-\r
- this.destruct = function() {\r
- _s._wD('soundManager.destruct()');\r
- _s.disable(true);\r
- };\r
- \r
- // SMSound (sound object)\r
- \r
- SMSound = function(oOptions) {\r
- var _t = this;\r
- this.sID = oOptions.id;\r
- this.url = oOptions.url;\r
- this.options = _s._mergeObjects(oOptions);\r
- this.instanceOptions = this.options; // per-play-instance-specific options\r
- this._iO = this.instanceOptions; // short alias\r
-\r
- // assign property defaults (volume, pan etc.)\r
- this.pan = this.options.pan;\r
- this.volume = this.options.volume;\r
-\r
- this._debug = function() {\r
- if (_s.debugMode) {\r
- var stuff = null;\r
- var msg = [];\r
- var sF = null;\r
- var sfBracket = null;\r
- var maxLength = 64; // # of characters of function code to show before truncating\r
- for (stuff in _t.options) {\r
- if (_t.options[stuff] !== null) {\r
- if (_t.options[stuff] instanceof Function) {\r
- // handle functions specially\r
- sF = _t.options[stuff].toString();\r
- sF = sF.replace(/\s\s+/g,' '); // normalize spaces\r
- sfBracket = sF.indexOf('{');\r
- msg[msg.length] = ' '+stuff+': {'+sF.substr(sfBracket+1,(Math.min(Math.max(sF.indexOf('\n')-1,maxLength),maxLength))).replace(/\n/g,'')+'... }';\r
- } else {\r
- msg[msg.length] = ' '+stuff+': '+_t.options[stuff];\r
- }\r
- }\r
- }\r
- _s._wD('SMSound() merged options: {\n'+msg.join(', \n')+'\n}');\r
- }\r
- };\r
-\r
- this._debug();\r
-\r
- this.id3 = {\r
- /* \r
- Name/value pairs set via Flash when available - see reference for names:\r
- http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html\r
- (eg., this.id3.songname or this.id3['songname'])\r
- */\r
- };\r
-\r
- this.resetProperties = function(bLoaded) {\r
- _t.bytesLoaded = null;\r
- _t.bytesTotal = null;\r
- _t.position = null;\r
- _t.duration = null;\r
- _t.durationEstimate = null;\r
- _t.loaded = false;\r
- _t.playState = 0;\r
- _t.paused = false;\r
- _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success\r
- _t.muted = false;\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- _t.isBuffering = false;\r
- _t.instanceOptions = {};\r
- _t.instanceCount = 0;\r
- _t.peakData = {\r
- left: 0,\r
- right: 0\r
- };\r
- _t.waveformData = [];\r
- _t.eqData = [];\r
- };\r
-\r
- _t.resetProperties();\r
-\r
- // --- public methods ---\r
-\r
- this.load = function(oOptions) {\r
- if (typeof oOptions != 'undefined') {\r
- _t._iO = _s._mergeObjects(oOptions);\r
- _t.instanceOptions = _t._iO;\r
- } else {\r
- oOptions = _t.options;\r
- _t._iO = oOptions;\r
- _t.instanceOptions = _t._iO;\r
- } \r
- if (typeof _t._iO.url == 'undefined') {\r
- _t._iO.url = _t.url;\r
- }\r
- _s._wD('soundManager.load(): '+_t._iO.url,1);\r
- if (_t._iO.url == _t.url && _t.readyState !== 0 && _t.readyState != 2) {\r
- _s._wD('soundManager.load(): current URL already assigned.',1);\r
- return false;\r
- }\r
- _t.loaded = false;\r
- _t.readyState = 1;\r
- _t.playState = 0; // (oOptions.autoPlay?1:0); // if autoPlay, assume "playing" is true (no way to detect when it actually starts in Flash unless onPlay is watched?)\r
- try {\r
- if (_s.flashVersion==8) {\r
- _s.o._load(_t.sID,_t._iO.url,_t._iO.stream,_t._iO.autoPlay,(_t._iO.whileloading?1:0));\r
- } else {\r
- _s.o._load(_t.sID,_t._iO.url,_t._iO.stream?true:false,_t._iO.autoPlay?true:false); // ,(_tO.whileloading?true:false)\r
- if (_t._iO.isMovieStar && _t._iO.autoLoad && !_t._iO.autoPlay) {\r
- // special case: MPEG4 content must start playing to load, then pause to prevent playing.\r
- _t.pause();\r
- }\r
- }\r
- } catch(e) {\r
- _s._wD('SMSound.load(): Exception: JS-Flash communication failed, or JS error.',2);\r
- _s._debugTS('onload',false);\r
- _s.onerror();\r
- _s.disable();\r
- }\r
-\r
- };\r
-\r
- this.unload = function() {\r
- // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3\r
- // Flash 9/AS3: Close stream, preventing further load\r
- if (_t.readyState !== 0) {\r
- _s._wD('SMSound.unload(): "'+_t.sID+'"');\r
- if (_t.readyState != 2) { // reset if not error\r
- _t.setPosition(0,true); // reset current sound positioning\r
- }\r
- _s.o._unload(_t.sID,_s.nullURL);\r
- // reset load/status flags\r
- _t.resetProperties();\r
- }\r
- };\r
-\r
- this.destruct = function() {\r
- // kill sound within Flash\r
- _s._wD('SMSound.destruct(): "'+_t.sID+'"');\r
- _s.o._destroySound(_t.sID);\r
- _s.destroySound(_t.sID,true); // ensure deletion from controller\r
- };\r
-\r
- this.play = function(oOptions) {\r
- if (!oOptions) {\r
- oOptions = {};\r
- }\r
- _t._iO = _s._mergeObjects(oOptions,_t._iO);\r
- _t._iO = _s._mergeObjects(_t._iO,_t.options);\r
- _t.instanceOptions = _t._iO;\r
- if (_t.playState == 1) {\r
- var allowMulti = _t._iO.multiShot;\r
- if (!allowMulti) {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" already playing (one-shot)',1);\r
- return false;\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" already playing (multi-shot)',1);\r
- }\r
- }\r
- if (!_t.loaded) {\r
- if (_t.readyState === 0) {\r
- _s._wD('SMSound.play(): Attempting to load "'+_t.sID+'"',1);\r
- // try to get this sound playing ASAP\r
- _t._iO.stream = true;\r
- _t._iO.autoPlay = true;\r
- // TODO: need to investigate when false, double-playing\r
- // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here\r
- _t.load(_t._iO); // try to get this sound playing ASAP\r
- } else if (_t.readyState == 2) {\r
- _s._wD('SMSound.play(): Could not load "'+_t.sID+'" - exiting',2);\r
- return false;\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'" is loading - attempting to play..',1);\r
- }\r
- } else {\r
- _s._wD('SMSound.play(): "'+_t.sID+'"');\r
- }\r
- if (_t.paused) {\r
- _t.resume();\r
- } else {\r
- _t.playState = 1;\r
- if (!_t.instanceCount || _s.flashVersion == 9) {\r
- _t.instanceCount++;\r
- }\r
- _t.position = (typeof _t._iO.position != 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);\r
- if (_t._iO.onplay) {\r
- _t._iO.onplay.apply(_t);\r
- }\r
- _t.setVolume(_t._iO.volume,true); // restrict volume to instance options only\r
- _t.setPan(_t._iO.pan,true);\r
- _s.o._start(_t.sID,_t._iO.loop||1,(_s.flashVersion==9?_t.position:_t.position/1000));\r
- }\r
- };\r
-\r
- this.start = this.play; // just for convenience\r
-\r
- this.stop = function(bAll) {\r
- if (_t.playState == 1) {\r
- _t.playState = 0;\r
- _t.paused = false;\r
- // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);\r
- if (_t._iO.onstop) {\r
- _t._iO.onstop.apply(_t);\r
- }\r
- _s.o._stop(_t.sID,bAll);\r
- _t.instanceCount = 0;\r
- _t._iO = {};\r
- // _t.instanceOptions = _t._iO;\r
- }\r
- };\r
-\r
- this.setPosition = function(nMsecOffset,bNoDebug) {\r
- if (typeof nMsecOffset == 'undefined') {\r
- nMsecOffset = 0;\r
- }\r
- var offset = Math.min(_t.duration,Math.max(nMsecOffset,0)); // position >= 0 and <= current available (loaded) duration\r
- _t._iO.position = offset;\r
- if (!bNoDebug) {\r
- _s._wD('SMSound.setPosition('+nMsecOffset+')'+(nMsecOffset != offset?', corrected value: '+offset:''));\r
- }\r
- _s.o._setPosition(_t.sID,(_s.flashVersion==9?_t._iO.position:_t._iO.position/1000),(_t.paused||!_t.playState)); // if paused or not playing, will not resume (by playing)\r
- };\r
-\r
- this.pause = function() {\r
- if (_t.paused || _t.playState === 0) {\r
- return false;\r
- }\r
- _s._wD('SMSound.pause()');\r
- _t.paused = true;\r
- _s.o._pause(_t.sID);\r
- if (_t._iO.onpause) {\r
- _t._iO.onpause.apply(_t);\r
- }\r
- };\r
-\r
- this.resume = function() {\r
- if (!_t.paused || _t.playState === 0) {\r
- return false;\r
- }\r
- _s._wD('SMSound.resume()');\r
- _t.paused = false;\r
- _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)\r
- if (_t._iO.onresume) {\r
- _t._iO.onresume.apply(_t);\r
- }\r
- };\r
-\r
- this.togglePause = function() {\r
- _s._wD('SMSound.togglePause()');\r
- if (!_t.playState) {\r
- _t.play({position:(_s.flashVersion==9?_t.position:_t.position/1000)});\r
- return false;\r
- }\r
- if (_t.paused) {\r
- _t.resume();\r
- } else {\r
- _t.pause();\r
- }\r
- };\r
-\r
- this.setPan = function(nPan,bInstanceOnly) {\r
- if (typeof nPan == 'undefined') {\r
- nPan = 0;\r
- }\r
- if (typeof bInstanceOnly == 'undefined') {\r
- bInstanceOnly = false;\r
- }\r
- _s.o._setPan(_t.sID,nPan);\r
- _t._iO.pan = nPan;\r
- if (!bInstanceOnly) {\r
- _t.pan = nPan;\r
- }\r
- };\r
-\r
- this.setVolume = function(nVol,bInstanceOnly) {\r
- if (typeof nVol == 'undefined') {\r
- nVol = 100;\r
- }\r
- if (typeof bInstanceOnly == 'undefined') {\r
- bInstanceOnly = false;\r
- }\r
- _s.o._setVolume(_t.sID,(_s.muted&&!_t.muted)||_t.muted?0:nVol);\r
- _t._iO.volume = nVol;\r
- if (!bInstanceOnly) {\r
- _t.volume = nVol;\r
- }\r
- };\r
-\r
- this.mute = function() {\r
- _t.muted = true;\r
- _s.o._setVolume(_t.sID,0);\r
- };\r
-\r
- this.unmute = function() {\r
- _t.muted = false;\r
- var hasIO = typeof _t._iO.volume != 'undefined';\r
- _s.o._setVolume(_t.sID,hasIO?_t._iO.volume:_t.options.volume);\r
- };\r
-\r
- // --- "private" methods called by Flash ---\r
-\r
- this._whileloading = function(nBytesLoaded,nBytesTotal,nDuration) {\r
- if (!_t._iO.isMovieStar) {\r
- _t.bytesLoaded = nBytesLoaded;\r
- _t.bytesTotal = nBytesTotal;\r
- _t.duration = Math.floor(nDuration);\r
- _t.durationEstimate = parseInt((_t.bytesTotal/_t.bytesLoaded)*_t.duration,10); // estimate total time (will only be accurate with CBR MP3s.)\r
- if (_t.readyState != 3 && _t._iO.whileloading) {\r
- _t._iO.whileloading.apply(_t);\r
- }\r
- } else {\r
- _t.bytesLoaded = nBytesLoaded;\r
- _t.bytesTotal = nBytesTotal;\r
- _t.duration = Math.floor(nDuration);\r
- _t.durationEstimate = _t.duration;\r
- if (_t.readyState != 3 && _t._iO.whileloading) {\r
- _t._iO.whileloading.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onid3 = function(oID3PropNames,oID3Data) {\r
- // oID3PropNames: string array (names)\r
- // ID3Data: string array (data)\r
- _s._wD('SMSound._onid3(): "'+this.sID+'" ID3 data received.');\r
- var oData = [];\r
- for (var i=0,j=oID3PropNames.length; i<j; i++) {\r
- oData[oID3PropNames[i]] = oID3Data[i];\r
- // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);\r
- }\r
- _t.id3 = _s._mergeObjects(_t.id3,oData);\r
- if (_t._iO.onid3) {\r
- _t._iO.onid3.apply(_t);\r
- }\r
- };\r
-\r
- this._whileplaying = function(nPosition,oPeakData,oWaveformData,oEQData) {\r
- if (isNaN(nPosition) || nPosition === null) {\r
- return false; // Flash may return NaN at times\r
- }\r
- _t.position = nPosition;\r
- if (_t._iO.usePeakData && typeof oPeakData != 'undefined' && oPeakData) {\r
- _t.peakData = {\r
- left: oPeakData.leftPeak,\r
- right: oPeakData.rightPeak\r
- };\r
- }\r
- if (_t._iO.useWaveformData && typeof oWaveformData != 'undefined' && oWaveformData) {\r
- _t.waveformData = oWaveformData;\r
- /*\r
- _t.spectrumData = {\r
- left: oSpectrumData.left.split(','),\r
- right: oSpectrumData.right.split(',')\r
- }\r
- */\r
- }\r
- if (_t._iO.useEQData && typeof oEQData != 'undefined' && oEQData) {\r
- _t.eqData = oEQData;\r
- }\r
- if (_t.playState == 1) {\r
- if (_t._iO.whileplaying) {\r
- _t._iO.whileplaying.apply(_t); // flash may call after actual finish\r
- }\r
- if (_t.loaded && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration-_t.position <= _t._iO.onbeforefinishtime) {\r
- _s._wD('duration-position <= onbeforefinishtime: '+_t.duration+' - '+_t.position+' <= '+_t._iO.onbeforefinishtime+' ('+(_t.duration-_t.position)+')');\r
- _t._onbeforefinish();\r
- }\r
- }\r
- };\r
-\r
- this._onload = function(bSuccess) {\r
- bSuccess = (bSuccess==1?true:false);\r
- _s._wD('SMSound._onload(): "'+_t.sID+'"'+(bSuccess?' loaded.':' failed to load? - '+_t.url),(bSuccess?1:2));\r
- if (!bSuccess) {\r
- if (_s.sandbox.noRemote === true) {\r
- _s._wD('SMSound._onload(): Reminder: Flash security is denying network/internet access',1);\r
- }\r
- if (_s.sandbox.noLocal === true) {\r
- _s._wD('SMSound._onload(): Reminder: Flash security is denying local access',1);\r
- }\r
- }\r
- _t.loaded = bSuccess;\r
- _t.readyState = bSuccess?3:2;\r
- if (_t._iO.onload) {\r
- _t._iO.onload.apply(_t);\r
- }\r
- };\r
-\r
- this._onbeforefinish = function() {\r
- if (!_t.didBeforeFinish) {\r
- _t.didBeforeFinish = true;\r
- if (_t._iO.onbeforefinish) {\r
- _s._wD('SMSound._onbeforefinish(): "'+_t.sID+'"');\r
- _t._iO.onbeforefinish.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onjustbeforefinish = function(msOffset) {\r
- // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187)\r
- if (!_t.didJustBeforeFinish) {\r
- _t.didJustBeforeFinish = true;\r
- if (_t._iO.onjustbeforefinish) {\r
- _s._wD('SMSound._onjustbeforefinish(): "'+_t.sID+'"');\r
- _t._iO.onjustbeforefinish.apply(_t);\r
- }\r
- }\r
- };\r
-\r
- this._onfinish = function() {\r
- // sound has finished playing\r
-\r
- // TODO: calling user-defined onfinish() should happen after setPosition(0)\r
- // OR: onfinish() and then setPosition(0) is bad.\r
-\r
- if (_t._iO.onbeforefinishcomplete) {\r
- _t._iO.onbeforefinishcomplete.apply(_t);\r
- }\r
- // reset some state items\r
- _t.didBeforeFinish = false;\r
- _t.didJustBeforeFinish = false;\r
- if (_t.instanceCount) {\r
- _t.instanceCount--;\r
- if (!_t.instanceCount) {\r
- // reset instance options\r
- // _t.setPosition(0);\r
- _t.playState = 0;\r
- _t.paused = false;\r
- _t.instanceCount = 0;\r
- _t.instanceOptions = {};\r
- if (_t._iO.onfinish) {\r
- _s._wD('SMSound._onfinish(): "'+_t.sID+'"');\r
- _t._iO.onfinish.apply(_t);\r
- }\r
- }\r
- } else {\r
- // _t.setPosition(0);\r
- }\r
- };\r
-\r
- this._onmetadata = function(oMetaData) {\r
- // movieStar mode only\r
- _s._wD('SMSound.onmetadata()');\r
- // Contains a subset of metadata. Note that files may have their own unique metadata.\r
- // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html\r
- if (!oMetaData.width && !oMetaData.height) {\r
- _s._wD('No width/height given, assuming defaults');\r
- oMetaData.width = 320;\r
- oMetaData.height = 240;\r
- }\r
- _t.metadata = oMetaData; // potentially-large object from flash\r
- _t.width = oMetaData.width;\r
- _t.height = oMetaData.height;\r
- if (_t._iO.onmetadata) {\r
- _s._wD('SMSound._onmetadata(): "'+_t.sID+'"');\r
- _t._iO.onmetadata.apply(_t);\r
- }\r
- _s._wD('SMSound.onmetadata() complete');\r
- };\r
-\r
- this._onbufferchange = function(bIsBuffering) {\r
- if (bIsBuffering == _t.isBuffering) {\r
- // ignore initial "false" default, if matching\r
- return false;\r
- }\r
- _t.isBuffering = (bIsBuffering==1?true:false);\r
- if (_t._iO.onbufferchange) {\r
- _s._wD('SMSound._onbufferchange(): '+bIsBuffering);\r
- _t._iO.onbufferchange.apply(_t);\r
- }\r
- };\r
-\r
- }; // SMSound()\r
-\r
- // register a few event handlers\r
- if (window.addEventListener) {\r
- window.addEventListener('focus',_s.handleFocus,false);\r
- window.addEventListener('load',_s.beginDelayedInit,false);\r
- window.addEventListener('unload',_s.destruct,false);\r
- if (_s._tryInitOnFocus) {\r
- window.addEventListener('mousemove',_s.handleFocus,false); // massive Safari focus hack\r
- }\r
- } else if (window.attachEvent) {\r
- window.attachEvent('onfocus',_s.handleFocus);\r
- window.attachEvent('onload',_s.beginDelayedInit);\r
- window.attachEvent('unload',_s.destruct);\r
- } else {\r
- // no add/attachevent support - safe to assume no JS -> Flash either.\r
- _s._debugTS('onload',false);\r
- soundManager.onerror();\r
- soundManager.disable();\r
- }\r
-\r
- if (document.addEventListener) {\r
- document.addEventListener('DOMContentLoaded',_s.domContentLoaded,false);\r
- }\r
-\r
-} // SoundManager()\r
-\r
-soundManager = new SoundManager();
\ No newline at end of file
+++ /dev/null
-{eztelemetadata_set('eztelemeta_player', true)}
-<div class="view-embed">
- <div class="content-media">
- {include uri="design:content/datatype/view/eztelemetaitem.tpl"
- attribute=$object.data_map.item}
- </div>
-</div>
-
+++ /dev/null
-{* Telemeta Item - Full view *}
-
-<div class="content-view-full">
- <div class="class-telemetaitem">
-
- <h2>{$node.data_map.item.content.title|wash}</h2>
-
- <div class="content-media">
- {include uri="design:content/datatype/view/eztelemetaitem.tpl"
- attribute=$node.data_map.item}
- </div>
-
- </div>
-</div>
+++ /dev/null
-/*
- * eZTelemeta default CSS rules
- *
- * Copyright (c) 2009 Samalyse
- * Author: Olivier Guilyardi <olivier samalyse com>
- * License: CeCILL Free Software License Agreement
- */
-
-/* Core styles
- *
- * These style rules are quite neutral in regard to visual appearance, and
- * are meant to provide basic ergonomic enhancements such as:
- * - play/pause icons
- * - sound load blinking
- * - position hiding when stopped
- */
-
-.telemeta-item { text-align: left; }
-
-.telemeta-item .telemeta-sound a {
- display: block;
- background: url('../images/play.gif') no-repeat left top;
- padding-left: 29px;
- height: 22px;
- padding-top: 0.5ex;
-}
-.telemeta-item .telemeta-position, .telemeta-item .telemeta-separator { display: none; }
-.telemeta-playing .telemeta-sound a { background-image: url('../images/stop.gif'); }
-.telemeta-playing .telemeta-position, .telemeta-playing .telemeta-separator { display: inline; }
-.telemeta-loading .telemeta-position { text-decoration: blink; }
-
-/* Compact box styles
- *
- * While remaining quite visually neutral, these rules are meant to make telemeta
- * items more appealing and compact, and may not fit with all designs.
- */
-
-.telemeta-item {
- position: relative;
- background: #EEEEEE;
- padding: 0.3ex 1.3ex 1.3ex 1.3ex;
- border: solid 1px #DDDDDD;
-}
-
-.telemeta-item dd { margin-left: 0; }
-
-.telemeta-item dt.telemeta-sound, .telemeta-item dt.telemeta-duration,
-.telemeta-item dt.telemeta-description { display: none; }
-
-.telemeta-item .telemeta-sound { padding-right: 8.3em; }
-
-.telemeta-item .telemeta-sound a {
- text-decoration: none;
- font-weight: bold;
- color: #000066;
- outline: none;
- padding-bottom: 0.6ex;
-}
-
-.telemeta-item dd.telemeta-duration {
- position: absolute;
- right: 0.7ex;
- top: 1.4ex;
- font-size: 80%;
- color: #000066;
- padding: 0.4ex 0.7ex 0.3ex 0.7ex;
- border-bottom: solid 1px #E0E0E0;
- border-top: solid 1px #DDDDDD;
- font-weight: bold;
-}
-
-.telemeta-item .telemeta-sound a:hover, .telemeta-playing dd.telemeta-duration { color: #0000AA; }
-.telemeta-playing .telemeta-position { color: #AA0000; }
-.telemeta-item dd.telemeta-description { font-style: italic; margin-left: 0.2em; }
-.telemeta-item .telemeta-creator, .telemeta-item .telemeta-rights { font-size: 90%; margin-bottom: 1px; }
-
-.telemeta-item dt.telemeta-creator, .telemeta-item dt.telemeta-rights {
- float: left;
- padding-right: 1ex;
- position: relative;
- margin-left: 0.2em;
-}
-
-.telemeta-item .telemeta-clear { clear: both; }
-.telemeta-item .telemeta-position, .telemeta-item .telemeta-separator { display: inline; }
-
+++ /dev/null
-{* DO NOT EDIT THIS FILE! Use an override template instead. *}
-{default attribute_base=ContentObjectAttribute}
-
-<div class="block">
-<label>{'Telemeta URL'|i18n( 'design/standard/content/datatype' )}:</label>
-<input class="box ezcc-{$attribute.object.content_class.identifier} ezcca-{$attribute.object.content_class.identifier}_{$attribute.contentclass_attribute_identifier}" type="text" name="{$attribute_base}_url_{$attribute.id}" value="{$attribute.content.url}" />
-</div>
-
-<div class="block">
-<label>{'Item Identifier'|i18n( 'design/standard/content/datatype' )}:</label>
-<input class="box ezcc-{$attribute.object.content_class.identifier} ezcca-{$attribute.object.content_class.identifier}_{$attribute.contentclass_attribute_identifier}" type="text" name="{$attribute_base}_itemid_{$attribute.id}" value="{$attribute.content.id}" />
-</div>
+++ /dev/null
-{eztelemetadata_set('eztelemeta_player', true)}
-{def $item=$attribute.content}
-<div class="telemeta-item">
- <dl>
- <dt class="telemeta-sound">{'Sound'|i18n('eztelemeta')} :</dt>
- <dd class="telemeta-sound"><a href="{$item.mp3}">{$item.title|wash}</a></dd>
-
- <dt class="telemeta-duration">{'Duration'|i18n('eztelemeta')} :</dt>
- <dd class="telemeta-duration">
- <span class="telemeta-position">00:00:00</span>
- <span class="telemeta-separator"> / </span>
- {$item.duration_str}
- </dd>
-
- {if $item.description }
- <dt class="telemeta-description">{'Description'|i18n('eztelemeta')} :</dt>
- <dd class="telemeta-description">{$item.description|wash}</dd>
- {/if}
-
- {if $item.creator }
- <dt class="telemeta-creator">{'Creator'|i18n('eztelemeta')} :</dt>
- <dd class="telemeta-creator">{$item.creator|wash}</dd>
- {/if}
-
- {if $item.rights }
- <dt class="telemeta-rights">{'Legal rights'|i18n('eztelemeta')} :</dt>
- <dd class="telemeta-rights">{$item.rights|wash}</dd>
- {/if}
- </dl>
- <div class="telemeta-clear"></div>
-</div>
-{undef}
+++ /dev/null
-{if is_set( $module_result.content_info.persistent_variable.eztelemeta_player )}
-<style type="text/css">
- @import url({"stylesheets/eztelemeta.css"|ezdesign});
-</style>
-<script language="JavaScript" type="text/javascript" src={"javascript/soundmanager2-nodebug-jsmin.js"|ezdesign}></script>
-<script language="JavaScript" type="text/javascript" src={"javascript/eztelemeta-player.js"|ezdesign}></script>
-<script language="JavaScript" type="text/javascript">
-/* SoundManager2 configuration */
-soundManager.url = {'swf/'|ezdesign};
-
-telemetaPlayer = new TelemetaPlayer();
-
-{literal}
-soundManager.onload = function() {
- telemetaPlayer.setSoundManager(soundManager);
-}
-{/literal}
-</script>
-{/if}
+++ /dev/null
-VERSION := $(shell cat ../VERSION)
-DOCS=README.fr.html README.fr.pdf README.fr README.fr.latex
-
-doc: $(DOCS)
-
-README.fr.html: README.fr doc.css player.png
- cat README.fr | sed 's/:scale: .*/:scale: 100/' | \
- rst2html -lfr --stylesheet=doc.css --link-stylesheet - $@
-
-README.fr.pdf: README.fr.latex
- pdflatex $^
- pdflatex $^ # Double run is sometimes needed
-
-README.fr.latex: README.fr player.png
- rst2latex -lfr README.fr $@
-
-README.fr: README.fr.in ../VERSION
- cat README.fr.in | sed "s/EZTVERSION/$(VERSION)/g" > $@
-
-clean:
- rm -f $(DOCS) README.fr.aux README.fr.out README.fr.log
-
-# vim: set noexpandtab: ts=2: sw=2:
+++ /dev/null
-=============================================
-eZTelemeta |version| - Mise en place et usage
-=============================================
-
-:Auteur: Olivier Guilyardi <olivier samalyse com>
-:Date: |today|
-
-.. contents:: **Table des matières**
-.. sectnum::
-
-----
-
-Introduction
-~~~~~~~~~~~~
-
-Le présent document décrit les procédures de mise en place et d'usage
-de l'extension eZPublish eZTelemeta |version|. Cette extension a pour but
-de permettre l'intégration dynamique d'éléments sonores en provenance
-du logiciel Telemeta.
-
-Pré-requis
-~~~~~~~~~~
-
-- Système Linux ou FreeBSD:
-- PHP version 5.2 ou supérieur
-- Apache version 1.3 ou supérieur
-- eZPublish 4.1.0
-- l'accès distant à une installation Telemeta
-
-Mise en place
-~~~~~~~~~~~~~
-
-Installation de l'extension
----------------------------
-
-eZTelemeta |version| est distribuée sous la forme d'une archive .tar.gz,
-contenant le répertoire ``eztelemeta``, à placer dans le répertoire
-``extension`` de l'installation eZPublish.
-
-Puis activer l'extension dans l'administration, onglet Setup/Extensions,
-et régénerer les données de chargement automatique (``Regenerate
-autoload arrays for extensions``)
-
-Création de la classe principale
---------------------------------
-
-eZTelemeta définit un nouveau type de données, appelé ``Telemeta
-Item``. Les utilisateur avancés de eZPublish peuvent envisager
-différents scénarios d'utilisation de ce type de données. La procédure
-décrite ici consiste à créer une classe qui ne contiendra qu'un
-seul attribut, de type ``Telemeta Item``. Il est fortement recommandé
-de procéder ainsi lors d'une première mise en place, notamment pour
-intégrer facilement le lecteur audio aux pages publiques.
-
-Dans l'administration, dans Setup/Classes, dans le groupe Media, créer
-une classe avec les paramètres suivants::
-
- - Name: Telemeta Audio Item
- - Identifier: telemetaitem
- - Object name pattern: <item>
-
-Ajouter un attribut de type ``Telemeta Item``, avec pour paramètres (*respecter
-la casse*)::
-
- - Name: Item
- - Identifier: item
- - Required: activé
- - Searchable: activé
-
-Cliquer sur OK pour enregistrer la nouvelle classe.
-
-Réglage des permissions
------------------------
-
-Pour pouvoir afficher les items sur les pages publiques, il faut autoriser
-leur accès aux utilisateurs *anonymes*.
-
-Dans l'espace d'administration, onglet Setup, dans Roles and policies:
-
-1. Éditer le rôle ``Anonymous``
-2. Cliquer sur ``New policy``
-3. Choisir le module ``content`` puis cliquer sur ``Grant access to one function``
-4. Choisir la fonction ``read`` puis cliquer sur ``Grant limited access``
-5. Choisir la classe ``Telemeta Audio Item`` puis cliquer en bas de page sur OK
-6. De retour sur le role, cliquer à nouveau sur OK
-
-Création d'un objet de contenu
-------------------------------
-
-Il est maintenant possible de créer un objet de contenu (une instance)
-à partir de cette classe, par exemple dans l'onglet Media Library,
-dossier Multimedia, créer un objet de type Telemeta Audio Item avec
-pour paramètres::
-
- - Telemeta URL: L'url de l'installation Telemeta distante.
- (exemple: http://mucem.telemeta.org)
-
- - Item Identifier: La cote de l'item. Celle-ci peut être trouvée
- en accédant à l'interface web de Telemeta, sur
- la page de l'item choisi.
-
-Puis enregistrer les modifications (``Send for publishing``).
-
-**Remarque**: au moment de l'enregistrement, eZTelemeta établit
-une connexion avec l'installation Telemeta distante, en utilisant le
-protocole OAI-PMH via HTTP. Si la cote de l'item est invalide, ou
-si la connexion HTTP ne peut-être établi à cause d'un mauvais URL,
-l'item ne sera pas enregistré, et une erreur s'affichera. Dans ce cas
-vérifiez bien votre saisie.
-
-Intégration de l'objet de contenu dans un article
--------------------------------------------------
-
-Maintenant que nous disposons d'un objet de contenu Telemeta, il est facile
-de l'intégrer à un article. Pour ce faire, lors de l'édition d'un article:
-
-1. Cliquer sur l'icône représentant un *trombone* (``Insérer/modifier un objet``)
-2. Une fenêtre DHTML doit s'ouvrir, cliquer sur Parcourir, Media puis sur Multimedia
-3. Sélectionner l'item Telemeta à insérer, un aperçu (lien, titre, etc...) doit s'afficher
-4. Cliquer sur OK
-
-L'item doit maintenant être intégré au corps de l'article, sous la
-forme d'une liste de définition HTML (``<dl>...</dl>``), affichant le
-titre de l'item sous la forme d'un lien vers le fichier son hébergé
-sur le serveur Telemeta, la durée (HH:MM:SS) de l'item, et suivant les
-informations qui sont disponibles, un ou plusieurs éléments parmi les
-suivants: Auteur/Collecteur, Description, Droits d'usage.
-
-L'intégration sous la forme d'une liste de définition HTML a plusieurs avantages:
-
-- en terme de contenu, c'est la construction HTML la plus adaptée à une liste de méta-données
-- la présentation est facilement personnalisable avec des feuilles de styles CSS.
-- elle est accessible, facilitant par exemple la consultation à l'aide de périphériques de type lecteur
- d'écran destinés aux mal-voyants
-
-Intégration du lecteur audio
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Remarques générales sur le lecteur
-----------------------------------
-
-eZTelemeta inclut un lecteur audio web employant javascript et flash de
-façon dîte *dégradable*: si flash ou javascript sont absents, le lien
-HTML vers le fichier son (mp3) est laissé intacte, et la lecture reste
-donc possible à l'aide d'un module externe au navigateur (Windows Media
-Player, iTunes, VLC, etc...).
-
-Cependant, la plupart des utilisateurs pourront profiter du lecteur audio
-permettant la lecture interactive du son sans quitter la page en cours,
-à la condition que le lecteur Adobe Flash 8 soit installé, et javascript
-activé, sous:
-
-- Internet Explorer 6 et 7
-- Firefox 2 et 3
-- Safari 3
-- Opera 9
-
-Voici un aperçu du lecteur :
-
-.. image:: player.png
- :scale: 75
-
-Dans le respect des règles de l'art du web actuel, les routines
-javascript sont séparées de façon stricte du contenu HTML. L'affichage
-interactif du lecteur est entièrement personnalisable via CSS et/ou
-modification des templates eZPublish. Flash est utilisé de façon
-invisible, via la librairie SoundManager2, offrant une API javascript
-dédiée au son.
-
-Plusieurs items peuvent être placés arbitrairement dans la page,
-s'intégrant bien au flot du contenu HTML. Lorsqu'on clique sur
-l'un deux, si la lecture d'un autre item est déjà en cours, elle
-s'interrompt, de façon à éviter la lecture accidentelle simultanée
-de plusieurs sons.
-
-**Remarque :** Pour simplifier la mise en place du lecteur, il est
-recommandé d'utiliser une classe de contenu eZPublish dont l'identifiant
-est ``telemetaitem`` comme indiqué à la section `Création de la classe
-principale`_.
-
-Chargement des dépendances
---------------------------
-
-Le lecteur possède des dépendances CSS et Javascript qui doivent êtres
-chargées dans la section ``<head/>`` des pages du site. Pour ce faire
-eZTelemeta contient un template qui doit être inclut dans cette section,
-en personnalisant le template ``pagelayout.tpl``, qui est utilisé
-par eZPublish pour construire toutes les pages.
-
-Pour ce faire, se rendre dans l'onglet Design de l'espace
-d'administration eZPublish, et (si ce n'est déjà fait) y créer
-un ``override`` du template ``pagelayout.tpl`` pour le ou les sites
-concernés. Il est également recommandé de créer un tel ``override``
-pour le template ``pagelayout.tpl`` de la partie administrative.
-
-Puis, dans chacun des templates ``pagelayout.tpl`` concernés, inclure
-le template d'initialisation en plaçant l'expression suivante dans la section
-``<head/>``::
-
-{include uri="design:eztelemeta_head.tpl"}
-
-Enfin, vider le cache eZPublish. Le lecteur audio doit maintenant être actif
-à la fois sur les pages publiques intégrant un item Telemeta, et lors de la
-pré-visualisation d'un article dans l'espace administratif.
-
-**Remarque**: le fait d'inclure le template ``eztelemeta_head.tpl`` dans toutes
-les pages du site via la personnalisation de ``pagelayout.tpl``, n'alourdit pas
-inutilement le chargement des pages. Les dépendances CSS, JS et Flash ne sont
-chargées que si la page en cours contient effectivement un item Telemeta.
-
-Personnalisation à l'aide de feuilles de style
-----------------------------------------------
-
-Comme indiqué à la section `Remarques générales sur le lecteur`_
-l'apparence du lecteur audio repose intégralement sur HTML et CSS,
-contrairement à un lecteur possédant une interface utilisateur flash,
-et peut donc facilement être personnalisée.
-
-Dans la majorité des cas, la personnalisation peut être effectuée à l'aide règles
-de style CSS.
-
-Par défaut, l'affichage d'un item par défaut a la structure suivante::
-
- <div class="telemeta-item">
- <dl>
- <dt class="telemeta-sound">Son :</dt>
- <dd class="telemeta-sound"><a href="...">...</a></dd>
-
- <dt class="telemeta-duration">Durée :</dt>
- <dd class="telemeta-duration">
- <span class="telemeta-position">...</span>
- <span class="telemeta-separator"> / </span>
- ...
- </dd>
-
- <dt class="telemeta-description">Description :</dt>
- <dd class="telemeta-description">...</dd>
-
- <dt class="telemeta-creator">Auteur / Collecteur :</dt>
- <dd class="telemeta-creator">...</dd>
-
- <dt class="telemeta-rights">Droits d'usage :</dt>
- <dd class="telemeta-rights">...</dd>
- </dl>
- <div class="telemeta-clear"></div>
- </div>
-
-Lorsque la lecture est en cours, la classe ``telemeta-playing`` est
-ajoutée automatiquement (par la classe javascript ``TelemetaPlayer``)
-à l'élément ``div``::
-
- <div class="telemeta-item telemeta-playing">
- ...
- </div>
-
-Si la lecture est activée, mais que le son ne peut-être joué car il est
-en cours de chargement (mise en tampon), la classe ``telemeta-loading``
-est ajoutée à l'élément ``div``::
-
- <div class="telemeta-item telemeta-playing telemeta-loading">
- ...
- </div>
-
-La feuille de style par défaut est quant à elle localisée dans::
-
- eztelemeta/design/standard/stylesheets/eztelemeta.css
-
-Cette feuille de style contient deux sections:
-
- - Core styles: ces règles laisse la liste de définition HTML ``<dl/>``
- quasiment intacte, ajoutant simplement l'icône play/pause au lien,
- et un effet de clignotement en cours de chargement.
- - Compact box styles: ces règles, légèrement plus intrusives, donne son
- apparence plus compacte au lecteur, avec couleur de fond, etc...
-
-Personnalisation des Templates
-------------------------------
-
-Pour une personnalisation plus poussée de l'apparence du lecteur il est possible
-de modifier les templates HTML. Pour ce faire, comme ailleurs dans eZPublish, il
-est recommandé de créer des ``override`` de template, et non de modifier
-directement les templates. Se reporter à la documentation de eZPublish pour plus
-de détails.
-
-Le code HTML du lecteur réside essentiellement dans le template de vue du type
-de donnée ``Telemeta Item``::
-
- eztelemeta/design/standard/templates/content/datatype/view/eztelemetaitem.tpl
-
-Cependant, d'autres templates sont nécessaires suivant le contexte d'affichage.
-Mais, pour éviter la redondance ils *incluent* le template ci-dessus. De cette
-façon, la modification de ce template se répercutent automatiquement dans les
-différents contextes. Néanmoins, dans certains cas, il peut-être utile d'éviter
-ce mécanisme d'inclusion pour une personnalisation plus poussée, ce qui reste
-possible via le système de surcharge (``override``) de eZPublish.
-
-Ces templates annexes, qui incluent le template principal sont::
-
- - template d'imbrication (dans un article, etc...) :
- eztelemeta/design/standard/override/templates/embed/eztelemetaitem.tpl
-
- - template de vue autonome (résultat de recherche, etc...) :
- eztelemeta/design/standard/override/templates/full/eztelemetaitem.tpl
-
-Par ailleurs, le chargement des dépendances et l'initialisation du
-lecteur sont réalisés dans::
-
- eztelemeta/design/standard/templates/eztelemeta_head.tpl
-
-
-Mise à jour dynamique et gestion du cache
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Contenu dynamique
------------------
-
-Contrairement à la grande majorité des contenus gérés dans eZPublish,
-les items sont susceptibles de changer depuis l'extérieur, c'est à
-dire dans le contexte de Telemeta lui-même.
-
-L'une des raisons d'être de eZTelemeta est la répercussion automatique
-de ces changements (titre, son, auteur, etc...), sans qu'il soit
-nécessaire d'intervenir dans l'espace d'administration de eZPublish.
-
-Cette fonctionnalité est rendue possible grâce au lien OAI-PMH établi
-avec Telemeta, et la gestion du cache eZPublish.
-
-Gestion du cache
-----------------
-
-L'établissement d'une connexion avec le serveur distant Telemeta ne peut
-bien évidemment pas être effectuée à chaque affichage d'un item,
-ce serait trop lourd.
-
-Cependant, eZTelemeta n'inclut pas de système de gestion de cache spécifique.
-C'est le cache standard de eZPublish qui est utilisé.
-
-Ainsi, il convient que l'administrateur vérifie les réglages du cache,
-de façon à ce qu'il soit vidé périodiquement, pour recharger les
-méta-données des items Telemeta.
-
-Cette opération peut notamment être réalisée via un cronjob appelant régulièrement
-le script eZPublish suivant::
-
- php bin/php/ezcache.php --clear-tag=content
-
-Cette opération entraînera effectivement le rafraîchissement de l'ensemble des
-méta-données des items, affichées dans le lecteur audio.
-
-Cependant, le nom des objets de contenu n'est pas mis à jour par la
-purge du cache. C'est une limitation de eZPublish, qui est légèrement
-problématique dans le contexte de la gestion d'objets distants comme
-les items Telemeta.
-
-Les noms d'objets contiennent le titre d'item et apparaissent:
-
-- dans le titre HTML de la page lors de la vue autonome d'un item Telemeta
-- dans la liste des résultats de recherche
-- dans la liste d'objets de contenu dans l'espace d'administration
-
-Aucune opération de purge de cache ne met à jour ces noms d'objets, il faut soit
-modifier l'item, soit avoir recours au script eZPublish suivant, via un cronjob
-par exemple (il est recommandé de faire une sauvegarde avant le premier lancement
-de ce script)::
-
- php update/common/scripts/updatecontentobjectname.php
-
-
-.. |version| replace:: EZTVERSION
-.. |today| date::
-.. vim: set ft=rst:
+++ /dev/null
-body { font-size: 90%; }
-h1 a, h2 a { text-decoration: none; color: black; }
-h1 a { border-bottom: solid 2px #BBBBBB; }
-h1 a:hover, h2 a:hover { border-bottom: solid 2px #990000; }
-h1 { font-size: 150%; }
-h2 { font-size: 110%; }
-h1.title { border-bottom: solid 2px #990000; font-size: 170%; }
-tt.literal, pre.literal-block { background: #EEEEEE; }
-.contents a { color: #880000; }
+++ /dev/null
-[DataTypeSettings]
-ExtensionDirectories[]=eztelemeta
-AvailableDataTypes[]=eztelemetaitem
-
+++ /dev/null
-[ExtensionSettings]
-DesignExtensions[]=eztelemeta
-
+++ /dev/null
-[telemetaitem_full]
-Source=node/view/full.tpl
-MatchFile=full/eztelemetaitem.tpl
-Subdir=templates
-Match[class_identifier]=telemetaitem
-
-[embed_telemetaitem]
-Source=content/view/embed.tpl
-MatchFile=embed/eztelemetaitem.tpl
-Subdir=templates
-Match[class_identifier]=telemetaitem
+++ /dev/null
-[TemplateSettings]
-ExtensionAutoloadPath[]=eztelemeta
-
-[RegionalSettings]
-TranslationExtensions[]=eztelemeta
-
+++ /dev/null
-<!DOCTYPE TS><TS>
-<defaultcodec></defaultcodec>
-<context>
- <name>eztelemeta</name>
- <message>
- <source>Sound</source>
- <translation>Son</translation>
- </message>
- <message>
- <source>Duration</source>
- <translation>Durée</translation>
- </message>
- <message>
- <source>Description</source>
- <translation>Description</translation>
- </message>
- <message>
- <source>Creator</source>
- <translation>Auteur / Collecteur</translation>
- </message>
- <message>
- <source>Legal rights</source>
- <translation>Droits d'usage</translation>
- </message>
-</context>
-</TS>
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-"""
-Vérifier que les nouvelles cotes d'item :
-
-- correspondent toutes à la collection décrite par le fichier .csv
- (le fichier .csv est nommé d'après la nouvelle cote de collection)
-
-- sont uniques dans le fichiers .csv
-
-- ont un des formats suivant :
- - soit CNRSMH_I_aaaa_nnn_mmm
- - soit CNRSMH_I_aaaa_nnn_mmm_tt
- - soit CNRSMH_I_aaaa_nnn_mmm_tt_pp
- - soit CNRSMH_E_aaaa_nnn_mmm_tt
- - soit CNRSMH_E_aaaa_nnn_mmm_tt_pp
-
-- correspondent à fichier .wav (et qu'il n'y a pas de fichiers .wav
- supplémentaire)
-
-Vérifier que le répertoire est nommé d'apprès la nouvelle cote de collection
-
-Vérifier que la nouvelle cote de collection a l'un des formats suivant :
- - soit CNRSMH_I_aaaa_nnn
- - soit CNRSMH_E_aaaa_nnn_mmm
-
-Vérifier que les fichiers .wav sont lisibles, ont une durée et sont identifés
-comme WAV par audiolab.
-"""
-
-
-import os
-import re
-import sys
-import csv
-import xlrd
-import datetime
-import logging
-import shutil
-
-COLLECTION_OLD_PATTERN = [
- { 'format': 'BM.aaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'},
- { 'format': 'BM.aaaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'BM.aaaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
- { 'format': 'BM.aaaa.nnn.mmm/', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/$'},
- { 'format': 'BM.aaaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'},
- { 'format': 'BM.aaaa.nnn.mm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{2})/[0-9]{2}$'},
- { 'format': 'BM.aaaa.nnn', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})$'},
- { 'format': 'BM.aaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'BM.aaa.nnn FANTOME', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3}) FANTOME$'},
- { 'format': 'BM.aaa.nnn', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})$'},
- { 'format': 'BM.aaa.nnnBISoo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})BIS([0-9]{2})/[0-9]{2}$'},
- { 'format': 'BM.aaa.nnn.mmm.ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})\.[0-9]{3}$'},
- { 'format': 'BM.aaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'},
- { 'format': 'BM.aaa.nnn/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'BM.aaa.nnn-BIS.ooo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})-BIS\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'BM.aaaa.nnn.mmm/NN', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/NN$'},
- { 'format': 'BM.aaa.nnn.mmm/pp-DEPOT', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}-DEPOT$'},
- { 'format': 'BM.aaa.nnn.mmm-o>p', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]>[0-9]$'},
- { 'format': 'CY.aaaa.nnn', 'regex': r'^(CY)\.([0-9]{4})\.([0-9]{3})$'},
- { 'format': 'DI.aaaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
- { 'format': 'DI.aaaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'DI.aaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'},
- { 'format': 'DI.aaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'},
- { 'format': 'DI.aaa.nnn.mmm-o/p', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]/[0-9]$'},
- { 'format': 'FANTOME 2*', 'regex': r'FANTOME 2\*$'},
-
- ## yomguy
- { 'format': 'BM.aaaa.nnn.mm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'},
- #{ 'format': 'BM.aaaa.nnn.mmm/pp:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/([0-9]{2})\:([0-9]{2})\-([0-9]{2})$'},
- #{ 'format': 'BM.aaaa.nnn.mmm/ppp:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/([0-9]{2})\:([0-9]{2})\-([0-9]{2})$'},
- #{ 'format': 'BM.aaaa.nnn.mmm:ii-jj', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3}):([0-9]{2})\-([0-9]{2})$'},
- ]
-
-ITEM_NEW_PATTERN = [
- { 'format': 'CNRSMH_I_aaaa_nnn_mmm', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})$'},
- { 'format': 'CNRSMH_I_aaaa_nnn_mmm_tt', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})$'},
- { 'format': 'CNRSMH_I_aaaa_nnn_mmm_tt_pp', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})_([0-9]{2})$'},
- { 'format': 'CNRSMH_E_aaaa_nnn_mmm_tt', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2})$'},
- { 'format': 'CNRSMH_E_aaaa_nnn_mmm_tt_pp', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})_([0-9]{2,3})_([0-9]{2})$'},
-
- # yomguy
- { 'format': 'CNRSMH_I_aaaa_nnn_mm', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})_([0-9]{2})$'},
- ]
-
-COLLECTION_PATTERN = [
- { 'format': 'CNRSMH_I_aaaa_nnn', 'regex': r'^(CNRSMH)_I_([0-9]{4})_([0-9]{3})$'},
- { 'format': 'CNRSMH_E_aaaa_nnn_mmm', 'regex': r'^(CNRSMH)_E_([0-9]{4})_([0-9]{3})_([0-9]{3})$'},
- ]
-
-
-def check_name(patterns, name):
- match = False
- for pattern in patterns:
- match = re.match(pattern['regex'], name)
- if match:
- break
- return match
-
-
-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 CremCollection:
-
- def __init__(self, dir, logger):
- self.dir = dir
- self.dir_name = self.dir.split(os.sep)[-1]
- self.file_list = os.listdir(self.dir)
- self.logger = logger
-
- def xls_list(self):
- file_list = []
- for file in self.file_list:
- filename = os.path.basename(file)
- ext = os.path.splitext(file)[1]
- if not '.' == filename[0] and (ext == '.xls' or ext == '.XLS'):
- file_list.append(file)
- print file_list
- return file_list
-
- def wav_list(self):
- list = []
- for file in self.file_list:
- filename = os.path.basename(file)
- ext = os.path.splitext(file)[1]
- if not '.' == filename[0] and (ext == '.wav' or ext == '.WAV'):
- list.append(file)
- elif '.' == filename[0]:
- self.logger.write_error(file, 'Warning : fichier caché présent !')
- return list
-
-
-class CremCSV:
-
- def __init__(self, file):
- self.csv_file = open(file, 'w')
- self.csv = csv.writer(self.csv_file, delimiter=';')
-
- def close(self):
- self.csv_file.close()
-
-class CremXLS:
-
- def __init__(self, file):
- self.first_row = 8
- self.original_col = 0
- self.new_col = 1
- self.book = xlrd.open_workbook(file)
- self.sheet = self.book.sheet_by_index(0)
- self.original_refs = self.original_refs()
- self.new_refs = self.new_refs()
- #print len(self.new_refs)
- while True:
- if len(self.original_refs) == 0 or len(self.new_refs) == 0:
- break
- else:
- if not 'CNRS' in self.new_refs[0].encode('utf8') \
- and not self.original_refs[0].encode('utf8') == '':
- self.original_refs = self.original_refs[1:]
- self.new_refs = self.new_refs[1:]
- else:
- break
-
- self.size = max(len(self.new_refs), len(self.original_refs))
-
- def original_refs(self):
- col = self.sheet.col(self.original_col)
- list = []
- for cell in col[self.first_row:]:
- if cell.ctype == 1:
- list.append(cell.value)
- return list
-
- def new_refs(self):
- col = self.sheet.col(self.new_col)
- list = []
- for cell in col[self.first_row:]:
- if cell.ctype == 1:
- list.append(cell.value)
- return list
-
-
-class CremItemFile:
-
- def __init__(self):
- self.media = ''
-
- def set_media(self, media):
- self.media = media
-
- def properties(self):
- self.frames = self.audio_file.get_nframes()
- self.samplerate = self.audio_file.get_samplerate()
- self.channels = self.audio_file.get_channels()
- self.format = self.audio_file.get_file_format()
- self.encoding = self.audio_file.get_encoding()
-
-
-class CremCheck:
-
- def __init__(self, root_dir, log_file):
- self.root_dir = root_dir
- self.logger = Logger(log_file)
- dir_list = os.listdir(self.root_dir)
- list = []
- for dir in dir_list:
- if not dir[0] == '.':
- list.append(dir)
- self.dir_list = list
-
- def check_new_refs(self):
- for name in self.new_refs:
- return check_name(ITEM_PATTERN, name)
-
- def check(self):
- for dir in self.dir_list:
- collection = CremCollection(self.root_dir + dir, self.logger)
- msg = '************************ ' + collection.dir_name + ' ******************************'
- self.logger.write_info(collection.dir, msg[:70])
-
- xls_list = collection.xls_list()
- wav_list = collection.wav_list()
-
- if not check_name(COLLECTION_PATTERN, dir):
- self.logger.write_error(collection.dir, 'Le dossier de la collection est mal nommé -> SORTIE')
- elif len(xls_list) == 0:
- self.logger.write_error(collection.dir, 'PAS de fichier XLS dans le dossier collection -> SORTIE')
- elif len(xls_list) > 1:
- self.logger.write_error(collection.dir, 'Plusieurs fichiers XLS dans le dossier collection -> SORTIE')
-
- else:
- xls = CremXLS(self.root_dir + os.sep + dir + os.sep + xls_list[0])
- self.logger.write_info(collection.dir, 'XLS : ' + xls_list[0] + ' - Feuille : ' + xls.sheet.name.encode('utf8'))
- self.logger.write_info(collection.dir, 'Nombre d\'items détectés : ' + str(xls.size))
- csv_file = CremCSV(self.root_dir + dir + os.sep + collection.dir_name + '.csv')
-
- if len(wav_list) != xls.size:
- self.logger.write_error(collection.dir, \
- 'Le nombre de références du fichier XLS (' + str(xls.size) + ') diffère du nombre de fichiers (' + str(len(wav_list)) + ')')
-
- temp_list = []
- item_file = CremItemFile()
-
- for i in range(0,xls.size):
- error = False
-
- try:
- item_old = xls.original_refs[i]
- #self.logger.write_error(collection.dir, item_old)
- except:
- item_old = ''
- msg = 'Ligne ' + str(i+xls.first_row+1) + ' : l\'ancienne référence d\'item est inexistante'
- self.logger.write_error(collection.dir, msg)
- error = True
- continue
-
- try:
- item = xls.new_refs[i]
- #self.logger.write_error(collection.dir, item)
- except:
- item = ''
- msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la nouvelle référence d\'item est inexistante'
- self.logger.write_error(collection.dir, msg)
- error = True
- continue
-
- if not item in temp_list:
- temp_list.append(item)
- else:
- msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la référence d\'item ' + item.encode('utf8') + ' est multiple'
- self.logger.write_error(collection.dir, msg)
- error = True
-
- #if not check_name(ITEM_OLD_PATTERN, item_old):
- #msg = 'Ligne ' + str(i+xls.first_row+1) + ' : l\'ancienne référence d\'item ' + item_old.encode('utf8') + ' est mal formatée'
- #self.logger.write_error(collection.dir, msg)
-
- if not check_name(ITEM_NEW_PATTERN, item):
- msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la nouvelle référence d\'item ' + item.encode('utf8') + ' est mal formatée'
- self.logger.write_error(collection.dir, msg)
- error = True
-
- if not collection.dir_name in item:
- msg = 'Ligne ' + str(i+xls.first_row+1) + ' : la référence d\'item ' + item.encode('utf8') + ' ne correspond pas à celle de la collection'
- self.logger.write_error(collection.dir, msg)
- error = True
-
- name_wav = item.encode('utf8') + '.wav'
- if not name_wav in wav_list:
- self.logger.write_error(collection.dir, 'Le fichier ' + item.encode('utf8') + '.wav n\'existe pas')
- else:
- item_file.set_media(collection.dir + os.sep + name_wav)
- #if not item_file.is_wav():
- # self.logger.write_error(collection.dir, 'Le fichier ' + item.encode('utf8') + '.wav n\'est pas valide')
- # error = True
-
- if not error:
- csv_file.csv.writerow([xls.original_refs[i], xls.new_refs[i]])
-
- csv_file.close()
-
- for filename in wav_list:
- if not check_name(ITEM_NEW_PATTERN, os.path.splitext(filename)[0]):
- self.logger.write_error(collection.dir, 'Le nom du fichier ' + str(os.path.splitext(filename)[0]) + ' est mal formaté')
-
- msg = '********************************************************************************'
- self.logger.write_info(collection.dir, msg[:70])
-
-
-def main():
- log_file = sys.argv[-1]
- root_dir = sys.argv[-2]
- log_tmp = log_file+'.tmp'
-
- c = CremCheck(root_dir, log_tmp)
- c.check()
-
- date = datetime.datetime.now().strftime("%x-%X").replace('/','_')
- shutil.copy(log_tmp,log_file+'-'+date+'.log')
- shutil.move(log_tmp,log_file)
-
-if __name__ == '__main__':
- main()
-
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-# for python2.5
-
-version = '0.5'
-
-
-import os
-import sys
-import time
-import shutil
-import datetime
-import timeside
-
-# soon with python2.6
-#from multiprocessing import Process
-
-from django.core.management import setup_environ
-from django.core.files.base import ContentFile
-import cgi
-fs = cgi.FieldStorage()
-
-
-orig_media_dir = '/mnt/awdiomusic/musicbase'
-project_dir = '/mnt/awdio'
-log_file = project_dir + '/logs/process.log'
-sys.path.append('/home/awdio/apps/telemeta-awdio')
-
-
-class GrapherScheme:
-
- def __init__(self):
- self.color = 255
- self.color_scheme = {
- 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
- (self.color,self.color,self.color)
-# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
- ],
- 'spectrogram': [
- (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
- ]}
-
- # Grapher id
- self.id = 'waveform_awdio'
-
- # Width of the image
- self.width = 1800
-
- # Height of the image
- self.height = 233
-
- # Background color
- self.bg_color = None
-
- # Force computation. By default, the class doesn't overwrite existing image files.
- self.force = False
-
- # Nb of threads
- # FIXME: memory leak for > 1 !
- self.threads = 1
-
-
-class TelemetaPreprocessImport(object):
-
- def __init__(self, root_dir, dest_dir, log_file):
- from telemeta.cache import TelemetaCache as Cache
- from telemeta.util.logger import Logger
- self.media_item_dir = 'items'
- self.root_dir = root_dir + 'items'
- self.dest_dir = dest_dir
- self.threads = 1
- self.logger = Logger(log_file)
- self.counter = 0
- self.force = 0
- self.cache = Cache(self.dest_dir)
-
- self.scheme = GrapherScheme()
- self.width = self.scheme.width
- self.height = self.scheme.height
- self.bg_color = self.scheme.bg_color
- self.color_scheme = self.scheme.color_scheme
- self.force = self.scheme.force
- self.threads = self.scheme.threads
- self.logger = Logger(log_file)
- self.counter = 0
- self.collection_name = 'awdio'
- self.collection = self.set_collection(self.collection_name)
-
- self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
- self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
- height=self.height,
- bg_color=self.bg_color,
- color_scheme=self.color_scheme)
-
-
- def set_collection(self, collection_name):
- import telemeta.models
- collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
- if not collections:
- c = telemeta.models.media.MediaCollection(code=collection_name)
- c.title = collection_name
- c.save()
- msg = 'added'
- self.logger.logger.info(collection_name, msg)
- collection = c
- else:
- collection = collections[0]
- return collection
-
- def process(self):
- import telemeta.models
- keys = fs.keys()
- if keys[0] == 'file':
- filename = fs['file'].value
- media_orig = orig_media_dir + os.sep + filename
- media = self.root_dir + os.sep + filename
-
- if not os.path.exists(media):
- shutil.copy(media_orig, media)
- os.system('chmod 644 ' + media)
-
- name, ext = os.path.splitext(filename)
- size = str(self.width) + '_' + str(self.height)
- image_name = name + '.' + self.scheme.id + '.' + size + '.png'
- image = self.dest_dir + os.sep + image_name
- xml = name + '.xml'
-
- if not self.cache.exists(image_name) or not self.cache.exists(xml):
- mess = 'Processing ' + media
- self.logger.logger.info(mess)
-
- print "Content-type: text/plain\n"
- print mess
- decoder = timeside.decoder.FileDecoder(media)
- pipe = decoder | self.grapher
- analyzers = []
- analyzers_sub = []
- for analyzer in self.analyzers:
- subpipe = analyzer()
- analyzers_sub.append(subpipe)
- pipe = pipe | subpipe
- pipe.run()
-
- mess = 'Rendering ' + image
- self.logger.logger.info(mess)
- self.grapher.render(output=image)
-
- mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
- self.logger.logger.info(mess)
-
- for analyzer in analyzers_sub:
- value = analyzer.result()
- if analyzer.id() == 'duration':
- 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, xml)
-
- item = telemeta.models.media.MediaItem.objects.filter(code=name)
-
- if not item:
- item = telemeta.models.media.MediaItem(collection=self.collection, code=name)
- item.title = name
- item.file = self.media_item_dir + os.sep + filename
- item.save()
- msg = 'added item : ' + filename
- self.logger.logger.info(self.collection_name, msg)
-
- pipe = 0
- decoder = 0
-
- print "OK"
-
- #except:
- #pipe = 0
- #decoder = 0
- #mess = 'Could NOT process : ' + media
- #self.logger.logger.error(mess)
- #print mess
-
- else:
- mess = "Nothing to do with file : " + media
- self.logger.logger.info(mess)
- print "Content-type: text/plain\n"
- print mess
-
- else:
- print "Content-type: text/plain\n"
- print "No file given !"
-
-
-if __name__ == '__main__':
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- media_dir = settings.MEDIA_ROOT
- data_dir = settings.TELEMETA_DATA_CACHE_DIR
- t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
- t.process()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 Samalyse 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.
-
-# This software is governed by the CeCILL license under French law and
-# abiding by the rules of distribution of free software. You can use,
-# modify and/ or redistribute the software under the terms of the CeCILL
-# license as circulated by CEA, CNRS and INRIA at the following URL
-# "http://www.cecill.info".
-
-# As a counterpart to the access to the source code and rights to copy,
-# modify and redistribute granted by the license, users are provided only
-# with a limited warranty and the software's author, the holder of the
-# economic rights, and the successive licensors have only limited
-# liability.
-
-# In this respect, the user's attention is drawn to the risks associated
-# with loading, using, modifying and/or developing or reproducing the
-# software by the user in light of its specific status of free software,
-# that may mean that it is complicated to manipulate, and that also
-# therefore means that it is reserved for developers and experienced
-# professionals having in-depth computer knowledge. Users are therefore
-# encouraged to load and test the software's suitability as regards their
-# requirements in conditions enabling the security of their systems and/or
-# data to be ensured and, more generally, to use and operate it in the
-# same conditions as regards security.
-
-# 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>
-
-import os
-import sys
-import time
-from django.core.management import setup_environ
-
-def print_usage(toolname):
- print "Usage: " + toolname + " <project_dir> <backup_dir>"
- print " project_dir: the directory of the Django project which hosts Telemeta"
- print " backup_dir: the destination backup folder (must exist)"
-
-def write_readme(dest_dir, coll_num):
- readme = open(dest_dir + "/" + "README", "w")
- timestr = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
- readme.write("Telemeta Backup\n\n")
- readme.write("- date: " + timestr + "\n")
- readme.write("- number of collections: " + str(coll_num) + "\n\n")
- readme.close()
-
-def backup(dest_dir):
- from telemeta.models import MediaCollection
- from telemeta.backup import CollectionSerializer
-
- collections = MediaCollection.objects.order_by('id')
- count = collections.count()
-
- print "Writing README file..",
- write_readme(dest_dir, count)
- print "Done."
-
- i = 0
- for collection in collections:
- if i % 100 == 0:
- set_dir = dest_dir + ("/collections-%d-%d" % (i+1, i+100))
- os.mkdir(set_dir)
- i += 1
- print "Processing collection %d/%d (%d%%) with id: %s.. " \
- % (i, count, i*100/count, collection.id),
- sys.stdout.flush()
- serializer = CollectionSerializer(collection)
- serializer.backup(set_dir)
- print "Done"
-
-def run():
- if len(sys.argv) != 3:
- print_usage(os.path.basename(sys.argv[0]))
- sys.exit(1)
- else:
- project_dir = sys.argv[1]
- backup_dir = sys.argv[2]
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- backup(backup_dir)
-
-if __name__ == '__main__':
- run()
+++ /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()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2010 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 csv
-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 info(self, prefix, message):
- self.logger.info(' ' + prefix + ' : ' + message.decode('utf8'))
-
- def error(self, prefix, message):
- self.logger.error(prefix + ' : ' + message.decode('utf8'))
-
-
-class TelemetaWavImport:
-
- def __init__(self, source_dir, log_file, pattern, domain):
- from django.contrib.auth.models import User
- self.logger = Logger(log_file)
- self.source_dir = source_dir
- self.collections = os.listdir(self.source_dir)
- self.pattern = pattern
- self.user = User.objects.filter(username='admin')[0]
- self.domain = domain
-
- def write_file(self, item, wav_file, overwrite=False):
- filename = wav_file.split(os.sep)[-1]
- if os.path.exists(wav_file):
- if not item.file or overwrite:
-# f = open(wav_file, 'r')
-# file_content = ContentFile(f.read())
-# item.file.save(filename, file_content)
-# f.close()
- item.save()
- item.set_revision(self.user)
- else:
- msg = item.code + ' : fichier ' + item.file.name + ' deja inscrit dans la base de donnees !'
- self.logger.error('item', msg)
- else:
- msg = item.code + ' : fichier audio ' + filename + ' inexistant dans le dossier !'
- self.logger.error('item', msg)
-
- def wav_import(self):
- from telemeta.models import MediaItem, MediaCollection
-
- collections = []
- for collection in self.collections:
- collection_dir = self.source_dir + os.sep + collection
- collection_files = os.listdir(collection_dir)
-
-
- if not '/.' in collection_dir and self.pattern in collection_dir:
- collection_name = collection.split(os.sep)[-1]
- collections.append(collection_name)
- c = MediaCollection.objects.filter(code=collection_name)
-
- if not c and collection + '.csv' in collection_files:
- msg = collection + ' collection NON présente dans la base de données, SORTIE '
- self.logger.error(collection, msg)
- sys.exit(msg)
- elif not c:
- msg = 'collection NON présente dans la base de données, CREATION '
- self.logger.info(collection, msg)
- c = MediaCollection(code=collection_name)
- c.save()
- c.set_revision(self.user)
- else:
- msg = 'collection présente dans la base de données, SELECTION'
- self.logger.info(collection, msg)
-
- for collection in collections:
- collection_dir = self.source_dir + os.sep + collection
- collection_name = collection
- collection_files = os.listdir(collection_dir)
- msg = '************************ ' + collection + ' ******************************'
- self.logger.info(collection, msg[:70])
- overwrite = True
- csv_file = ''
- rows = {}
-
- if collection + '.csv' in collection_files:
- csv_file = self.source_dir + os.sep + collection + os.sep + collection + '.csv'
- csv_data = csv.reader(open(csv_file), delimiter=';')
- for row in csv_data:
- rows[row[1].strip()] = row[0].strip()
- msg = collection + ' import du fichier CSV de la collection'
- self.logger.info(collection, msg[:70])
- else:
- msg = collection + ' pas de fichier CSV dans la collection'
- self.logger.info(collection, msg[:70])
-
- c = MediaCollection.objects.filter(code=collection_name)
- if not c:
- c = MediaCollection(code=collection_name)
- c.save()
- msg = ' collection NON présente dans la BDD, CREATION '
- self.logger.info(c.code, msg)
- else:
- c = c[0]
- msg = ' id = '+str(c.id)
- self.logger.info(c.code, msg)
-
- audio_files = []
- for file in collection_files:
- ext = ['WAV', 'wav']
- if file.split('.')[-1] in ext:
- audio_files.append(file)
-
- audio_files.sort()
- nb_items = c.items.count()
- counter = 0
-
- for file in audio_files:
- code = file.split('.')[0]
- wav_file = self.source_dir + os.sep + collection + os.sep + file
-
- if len(audio_files) <= nb_items:
- items = MediaItem.objects.filter(code=code)
-
- old_ref = ''
- if code in rows and not items:
- old_ref = rows[code]
- items = MediaItem.objects.filter(old_code=old_ref)
-
- if items:
- item = items[0]
- msg = code + ' : ' + item.old_code + ' : Cas 1 ou 2 : id = ' + str(item.id)
- self.logger.info('item', msg)
- item.code = code
- item.save()
- else:
- item = MediaItem(code=code, collection=c)
- msg = code + ' : ' + old_ref + ' : Cas 1 ou 2 : item NON présent dans la base de données, CREATION'
- self.logger.info('item', msg)
-
- self.write_file(item, wav_file, overwrite)
-
- elif nb_items == 1 and len(audio_files) > 1:
- if counter == 0:
- msg = code + ' : Cas 3a : item n°01 présent dans la base de données, PASSE'
- self.logger.info('item', msg)
- else:
- item = MediaItem(code=code, collection=c)
- msg = code + ' : Cas 3a : item NON présent dans la base de données, CREATION'
- self.logger.info('item', msg)
- self.write_file(item, wav_file, overwrite)
-
- elif nb_items > 1 and nb_items < len(audio_files):
- msg = code + ' : Cas 3b : nb items < nb de fichiers audio, PAS de creation'
- self.logger.info('item', msg)
-
- counter += 1
-
- msg = 'Liste des URLs des collections importées :'
- self.logger.info('INFO', msg)
- for collection in collections:
- msg = 'http://'+self.domain+'/collections/'+collection
- self.logger.info(collection, msg)
-
-
-def print_usage(tool_name):
- print "Usage: "+tool_name+" <project_dir> <source_dir> <pattern> <log_file> <domain>"
- print " project_dir: the directory of the Django project which hosts Telemeta"
- print " source_dir: the directory containing the wav files to include"
- print " pattern: a pattern to match the collection names"
- print " log_file: a log file to write logs"
- print " domain: root domain for collections"
-
-def run():
- if len(sys.argv) < 3:
- print_usage(os.path.basename(sys.argv[0]))
- sys.exit(1)
- else:
- project_dir = sys.argv[-5]
- source_dir = sys.argv[-4]
- pattern = sys.argv[-3]
- log_file = sys.argv[-2]
- url = sys.argv[-1]
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- t = TelemetaWavImport(source_dir, log_file, pattern, url)
- t.wav_import()
-
-if __name__ == '__main__':
- run()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2010 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 csv
-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 info(self, prefix, message):
- self.logger.info(' ' + prefix + ' : ' + message.decode('utf8'))
-
- def error(self, prefix, message):
- self.logger.error(prefix + ' : ' + message.decode('utf8'))
-
-
-class TelemetaWavImport:
-
- def __init__(self, source_dir, log_file, pattern, domain):
- from django.contrib.auth.models import User
- self.logger = Logger(log_file)
- self.source_dir = source_dir
- self.collections = os.listdir(self.source_dir)
- self.pattern = pattern
- self.user = User.objects.filter(username='admin')[0]
- self.domain = domain
-
- def write_file(self, item, wav_file, overwrite=False):
- filename = wav_file.split(os.sep)[-1]
- if os.path.exists(wav_file):
- if not item.file or overwrite:
- f = open(wav_file, 'r')
- file_content = ContentFile(f.read())
- item.file.save(filename, file_content)
- f.close()
- item.save()
- item.set_revision(self.user)
- else:
- msg = item.code + ' : fichier ' + item.file.name + ' deja inscrit dans la base de donnees !'
- self.logger.error('item', msg)
- else:
- msg = item.code + ' : fichier audio ' + filename + ' inexistant dans le dossier !'
- self.logger.error('item', msg)
-
- def wav_import(self):
- from telemeta.models import MediaItem, MediaCollection
-
- collections = []
- for collection in self.collections:
- collection_dir = self.source_dir + os.sep + collection
- collection_files = os.listdir(collection_dir)
-
-
- if not '/.' in collection_dir and self.pattern in collection_dir:
- collection_name = collection.split(os.sep)[-1]
- collections.append(collection_name)
- c = MediaCollection.objects.filter(code=collection_name)
-
- if not c and collection + '.csv' in collection_files:
- msg = collection + ' collection NON présente dans la base de données, SORTIE '
- self.logger.error(collection, msg)
- sys.exit(msg)
- elif not c:
- msg = 'collection NON présente dans la base de données, CREATION '
- self.logger.info(collection, msg)
- c = MediaCollection(code=collection_name, title=collection_name)
- c.save()
- c.set_revision(self.user)
- else:
- msg = 'collection présente dans la base de données, SELECTION'
- self.logger.info(collection, msg)
-
- for collection in collections:
- collection_dir = self.source_dir + os.sep + collection
- collection_name = collection
- collection_files = os.listdir(collection_dir)
- msg = '************************ ' + collection + ' ******************************'
- self.logger.info(collection, msg[:70])
- overwrite = True
- csv_file = ''
- rows = {}
-
- if collection + '.csv' in collection_files:
- csv_file = self.source_dir + os.sep + collection + os.sep + collection + '.csv'
- csv_data = csv.reader(open(csv_file), delimiter=';')
- for row in csv_data:
- rows[row[1].strip()] = row[0].strip()
- msg = collection + ' import du fichier CSV de la collection'
- self.logger.info(collection, msg[:70])
- else:
- msg = collection + ' pas de fichier CSV dans la collection'
- self.logger.info(collection, msg[:70])
-
- c = MediaCollection.objects.filter(code=collection_name)
- if not c:
- c = MediaCollection(code=collection_name)
- c.save()
- msg = ' collection NON présente dans la BDD, CREATION '
- self.logger.info(c.code, msg)
- else:
- c = c[0]
- msg = ' id = '+str(c.id)
- self.logger.info(c.code, msg)
-
- audio_files = []
- for file in collection_files:
- ext = ['WAV', 'wav']
- if file.split('.')[-1] in ext and file[0] != '.':
- audio_files.append(file)
-
- audio_files.sort()
- nb_items = c.items.count()
- counter = 0
-
- for file in audio_files:
- code = file.split('.')[0]
- wav_file = self.source_dir + os.sep + collection + os.sep + file
-
- if len(audio_files) <= nb_items:
- items = MediaItem.objects.filter(code=code)
-
- old_ref = ''
- if code in rows and not items:
- old_ref = rows[code]
- items = MediaItem.objects.filter(old_code=old_ref)
-
- if items:
- item = items[0]
- msg = code + ' : ' + item.old_code + ' : Cas 1 ou 2 : id = ' + str(item.id)
- self.logger.info('item', msg)
- item.code = code
- item.save()
- else:
- item = MediaItem(code=code, collection=c)
- msg = code + ' : ' + old_ref + ' : Cas 1 ou 2 : item NON présent dans la base de données, CREATION'
- self.logger.info('item', msg)
-
- self.write_file(item, wav_file, overwrite)
-
- elif nb_items == 1 and len(audio_files) > 1:
- if counter == 0:
- msg = code + ' : Cas 3a : item n°01 présent dans la base de données, PASSE'
- self.logger.info('item', msg)
- else:
- item = MediaItem(code=code, collection=c)
- msg = code + ' : Cas 3a : item NON présent dans la base de données, CREATION'
- self.logger.info('item', msg)
- self.write_file(item, wav_file, overwrite)
-
- elif nb_items > 1 and nb_items < len(audio_files):
- msg = code + ' : Cas 3b : nb items < nb de fichiers audio, PAS de creation'
- self.logger.info('item', msg)
-
- counter += 1
-
- msg = 'Liste des URLs des collections importées :'
- self.logger.info('INFO', msg)
- for collection in collections:
- msg = 'http://'+self.domain+'/archives/collections/'+collection
- self.logger.info(collection, msg)
-
-
-def print_usage(tool_name):
- print "Usage: "+tool_name+" <project_dir> <source_dir> <pattern> <log_file> <domain>"
- print " project_dir: the directory of the Django project which hosts Telemeta"
- print " source_dir: the directory containing the wav files to include"
- print " pattern: a pattern to match the collection names"
- print " log_file: a log file to write logs"
- print " domain: root domain for collections"
-
-def run():
- if len(sys.argv) < 3:
- print_usage(os.path.basename(sys.argv[0]))
- sys.exit(1)
- else:
- project_dir = sys.argv[-5]
- source_dir = sys.argv[-4]
- pattern = sys.argv[-3]
- log_file = sys.argv[-2]
- url = sys.argv[-1]
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- t = TelemetaWavImport(source_dir, log_file, pattern, url)
- t.wav_import()
-
-if __name__ == '__main__':
- run()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2010 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 re
-import sys
-import logging
-import datetime
-import timeside
-from django.core.management import setup_environ
-from django.core.files.base import ContentFile
-
-mapping = {
- 'title': 'title',
- 'album': 'collection',
- 'date': 'recorded_from_date',
- 'artist': 'author',
- 'track-number': 'track',
- 'encoder': 'comment',
- 'genre': 'generic_style',
- 'audio-codec': 'comment',
- 'container-format': 'comment',
- }
-
-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 TelemetaMediaImport:
-
- def __init__(self, media_dir, log_file):
- self.logger = Logger(log_file)
- self.media_dir = media_dir
- self.medias = self.get_medias()
-
- def get_medias(self):
- os.chdir(self.media_dir)
- file_list = []
- for root, dirs, files in os.walk('.'):
- for file in files:
- path = root + os.sep + file
- if not os.sep+'.' in path:
- file_list.append({'root': root, 'file': file})
- return file_list
-
- def set_collection(self, collection_name):
- if not collection_name:
- collection_name = 'Unkown'
- code = collection_name.replace(' ','_')
- code = re.sub(r'\W+', '_', code)
- from telemeta.models.media import MediaCollection
- collections = MediaCollection.objects.filter(code=code)
- if not collections:
- collection = MediaCollection(code=code,title=collection_name)
- collection.save()
- msg = 'created'
- self.logger.write_info('collection ' + collection_name, msg)
- else:
- collection = collections[0]
- return collection
-
- def media_import(self):
- from telemeta.models.media import MediaItem
- for media in self.medias:
- path = media['root'] + os.sep + media['file']
- print 'checking ' + path
- filename, ext = os.path.splitext(media['file'])
- item = MediaItem.objects.filter(code=filename)
- if not item:
- print 'importing ' + path
- decoder = timeside.decoder.FileDecoder(path)
- try:
- metadata = decoder.metadata()
- print metadata
- collection = self.set_collection(metadata['album'])
- item = MediaItem(collection=collection)
- item.code = re.sub(r'\W+', '_', metadata['title'])
- for tag in mapping.keys():
- try:
- if tag == 'date':
- date = metadata[tag].split(' ')[1].split('/')
- metadata[tag] = date[2]+'-'+date[1]+'-'+date[0]
- if mapping[tag] == 'comment':
- item[mapping[tag]] = item[mapping[tag]] + '\n' + metadata[tag]
- else:
- item[mapping[tag]] = metadata[tag]
- except:
- continue
- item.file = path
- item.save()
- msg = 'added item : ' + path
- self.logger.write_info(collection.code, msg)
- except:
- continue
-
-
-def run():
- project_dir = sys.argv[-2]
- log_file = sys.argv[-1]
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- media_dir = settings.MEDIA_ROOT
- t = TelemetaMediaImport(media_dir, log_file)
- t.media_import()
-
-if __name__ == '__main__':
- run()
+++ /dev/null
-#!/usr/bin/python
-
-import os, sys, string
-import logging
-
-class Logger:
- """A logging object"""
-
- def __init__(self, file):
- self.logger = logging.getLogger('myapp')
- self.hdlr = logging.FileHandler(file)
- self.formatter = logging.Formatter('%(message)s')
- self.hdlr.setFormatter(self.formatter)
- self.logger.addHandler(self.hdlr)
- self.logger.setLevel(logging.INFO)
-
-log_file = 'thumbs.log'
-logger = Logger(log_file)
-root_dir = sys.argv[-1]
-args = sys.argv[1:-1]
-source_format = 'webm'
-done = []
-preview_tc = '00:00:05'
-
-if os.path.exists(log_file):
- f = open(log_file, 'r')
- for line in f.readlines():
- done.append(line[:-1])
- f.close()
-
-for root, dirs, files in os.walk(root_dir):
- for file in files:
- path = os.path.abspath(root + os.sep + file)
- name, ext = os.path.splitext(file)
- if ext[1:] == source_format:
- dest = os.path.abspath(root + os.sep + name + '.png')
- if not dest in done or '--force' in args:
- command = 'ffmpeg -ss '+ preview_tc + ' -i ' + path + ' -y ' + dest
- os.system(command)
- logger.logger.info(dest)
-
-print "DONE!"
+++ /dev/null
-#!/usr/bin/python
-
-import os, sys, psutil
-import datetime
-from ebml.utils.ebml_data import *
-
-class FixCheckMedia(object):
-
- def __init__(self, dir, tmp_dir):
- self.dir = dir
- self.tmp_dir = tmp_dir
- if not os.path.exists(self.tmp_dir):
- os.makedirs(self.tmp_dir)
-
- def process(self):
- webm_fixed_log = 'webm.fixed'
- webm_tofix_log = 'webm.tofix'
- mp3_fixed_log = 'mp3.fixed'
- mp3_tofix_log = 'mp3.tofix'
-
- for root, dirs, files in os.walk(self.dir):
- for filename in files:
- source = root + os.sep + filename
- name = os.path.splitext(filename)[0]
- ext = os.path.splitext(filename)[1][1:]
-
- if ext == 'webm' and os.path.getsize(source):
- dir_files = os.listdir(root)
-
- if not webm_fixed_log in dir_files:
- print source
- self.fix_webm(source)
- f = open(root + os.sep + webm_fixed_log, 'w')
- f.close()
- if os.path.exists(root + os.sep + webm_tofix_log):
- os.remove(root + os.sep + webm_tofix_log)
-
- if mp3_tofix_log in dir_files or not mp3_fixed_log in dir_files:
- for file in dir_files:
- dest_ext = os.path.splitext(file)[1][1:]
- if dest_ext == 'mp3':
- dest = root + os.sep + file
- print dest
- self.fix_mp3(source, dest)
- f = open(root + os.sep + mp3_fixed_log, 'w')
- f.close()
- if os.path.exists(root + os.sep + mp3_tofix_log):
- os.remove(root + os.sep + mp3_tofix_log)
- #break
-
-
- def hard_fix_webm(self, path):
- try:
- tmp_file = self.tmp_dir + 'out.webm '
- command = 'ffmpeg -loglevel 0 -i "'+ path + '" -vcodec libvpx -vb 500k -acodec libvorbis -aq 7 -f webm -y "' + tmp_file + '" > /dev/null'
- print command
- os.system(command)
- command = 'mv ' + tmp_file + path
- os.system(command)
- except:
- pass
-
-
- def fix_webm(self, path):
- try:
- tmp_file = self.tmp_dir + 'out.webm'
- command = '/usr/local/bin/ffmpeg -loglevel 0 -i "' + path + '" -vcodec copy -acodec copy -f webm -y "' + tmp_file + '" > /dev/null'
- print command
- os.system(command)
- ebml_obj = EBMLData(tmp_file)
- offset = ebml_obj.get_first_cluster_seconds()
- command = '/usr/local/bin/ffmpeg -loglevel 0 -ss ' + str(offset) + ' -i "' + tmp_file + '" -vcodec copy -acodec copy -f webm -y "' + path + '" > /dev/null'
- print command
- os.system(command)
- except:
- pass
-
- def fix_mp3(self, source, path):
- try:
- command = '/usr/local/bin/ffmpeg -loglevel 0 -i "'+ source + '" -vn -aq 6 -y "' + path + '" > /dev/null'
- print command
- os.system(command)
- except:
- pass
-
-def get_pids(name, args=None):
- """Get a process pid filtered by arguments and uid"""
- pids = []
- for proc in psutil.process_iter():
- if proc.cmdline:
- if name == proc.name:
- if args:
- if args in proc.cmdline:
- pids.append(proc.pid)
- else:
- pids.append(proc.pid)
- return pids
-
-dir = sys.argv[-2]
-tmp_dir = sys.argv[-1]
-
-path = os.path.abspath(__file__)
-pids = get_pids('python2.6',args=path)
-
-print datetime.datetime.now()
-if len(pids) <= 1:
- print 'starting process...'
- f = FixCheckMedia(dir, tmp_dir)
- f.process()
- print 'process finished.\n'
-else:
- print 'already started !\n'
-
+++ /dev/null
-#!/usr/bin/python
-
-import os, sys, string
-import logging
-
-
-class Logger:
- """A logging object"""
-
- def __init__(self, file):
- self.logger = logging.getLogger('myapp')
- self.hdlr = logging.FileHandler(file)
- self.formatter = logging.Formatter('%(asctime)s %(message)s')
- self.hdlr.setFormatter(self.formatter)
- self.logger.addHandler(self.hdlr)
- self.logger.setLevel(logging.INFO)
-
-
-source_format = 'webm'
-preview_tc = '00:00:05'
-threads = 4
-
-ffmpeg_args = {
- 'mp3' : '-i "%s" -vn -acodec libmp3lame -aq 6 -ac 2',
- 'ogg' : '-i "%s" -vn -acodec copy',
- 'mp4' : '-i "%s" -vcodec libx264 -threads ' + str(threads) + \
- ' -c:v libx264 -crf 17 -maxrate 1100k -bufsize 1835k -acodec libfaac -ab 96k -ac 2',
- 'png' : '-ss ' + preview_tc + ' -i "%s"',
- }
-
-args = sys.argv[1:]
-log_file = args[-1]
-root_dir = args[-2]
-logger = Logger(log_file)
-
-for root, dirs, files in os.walk(root_dir):
- for file in files:
- path = os.path.abspath(root + os.sep + file)
- name, ext = os.path.splitext(file)
- if ext[1:] == source_format:
- for format in ffmpeg_args.keys():
- local_file = name + '.' + format
- dest = os.path.abspath(root + os.sep + local_file)
- local_files = os.listdir(root)
- if not local_file in local_files or '--force' in args:
- command = 'ffmpeg -loglevel 0 ' + ffmpeg_args[format] % path + ' -y "' + dest + '"'
- logger.logger.info(command)
- if not '--dry-run' in args:
- os.system(command)