# -*- coding: utf-8 -*-
from xmltodict import *
from PyRSS2Gen import *
+from mp3 import *
+from ogg import *
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2006-2009 Guillaume Pellerin <pellerin@parisson.com>
+# 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 <pellerin@parisson.com>
+
+import os
+import string
+from mutagen.easyid3 import EasyID3
+from mutagen.mp3 import MP3
+
+EasyID3.valid_keys["comment"]="COMM::'XXX'"
+
+class Mp3:
+ """An MP3 file object"""
+
+ def __init__(self, media):
+ self.media = media
+ self.item_id = ''
+ self.source = self.media
+ self.options = {}
+ self.bitrate_default = '192'
+ self.cache_dir = os.sep + 'tmp'
+ self.keys2id3 = {'title': 'TIT2',
+ 'artist': 'TPE1',
+ 'album': 'TALB',
+ 'date': 'TDRC',
+ 'comment': 'COMM',
+ 'genre': 'TCON',
+ }
+ self.metadata = self.get_metadata()
+ self.description = self.get_description()
+ self.mime_type = self.get_mime_type()
+ self.extension = self.get_file_extension()
+ #self.args = self.get_args()
+
+ def get_format(self):
+ return 'MP3'
+
+ def get_file_extension(self):
+ return 'mp3'
+
+ def get_mime_type(self):
+ return 'audio/mpeg'
+
+ def get_description(self):
+ return "MPEG audio Layer III"
+
+ def get_metadata(self):
+ m = MP3(self.media, ID3=EasyID3)
+ metadata = {}
+ for key in self.keys2id3.keys():
+ try:
+ metadata[key] = m[key][0]
+ except:
+ pass
+ return metadata
+
+ def decode(self):
+ try:
+ os.system('sox "'+self.media+'" -s -q -r 44100 -t wav "' \
+ +self.cache_dir+os.sep+self.item_id+'"')
+ return self.cache_dir+os.sep+self.metadata['title']+'.wav'
+ except:
+ raise IOError('ExporterError: decoder is not compatible.')
+
+ def write_tags(self):
+ """Write all ID3v2.4 tags by mapping dub2id3_dict dictionnary with the
+ respect of mutagen classes and methods"""
+ id3 = id3.ID3(self.media)
+ for tag in self.metadata.keys():
+ if tag in self.dub2id3_dict.keys():
+ frame_text = self.dub2id3_dict[tag]
+ value = self.metadata[tag]
+ frame = mutagen.id3.Frames[frame_text](3,value)
+ try:
+ id3.add(frame)
+ except:
+ raise IOError('ExporterError: cannot tag "'+tag+'"')
+ try:
+ id3.save()
+ except:
+ raise IOError('ExporterError: cannot write tags')
+
+ def get_args(self, options=None):
+ """Get process options and return arguments for the encoder"""
+ args = []
+ if not options is None:
+ self.options = options
+ if not ( 'verbose' in self.options and self.options['verbose'] != '0' ):
+ args.append('-S')
+ if 'mp3_bitrate' in self.options:
+ args.append('-b ' + self.options['mp3_bitrate'])
+ else:
+ args.append('-b '+self.bitrate_default)
+ #Copyrights, etc..
+ args.append('-c -o')
+ else:
+ args.append('-S -c -o')
+
+ for tag in self.metadata.keys():
+ if tag in self.dub2args_dict.keys():
+ arg = self.dub2args_dict[tag]
+ value = self.metadata[tag]
+ args.append('--' + arg)
+ args.append('"' + value + '"')
+
+ return args
+
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007 Parisson SARL
+# Copyright (c) 2006-2007 Guillaume Pellerin <pellerin@parisson.com>
+# 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 <pellerin@parisson.com>
+
+import os
+import string
+import subprocess
+
+from telemeta.export.core import *
+from telemeta.export.api import IExporter
+from mutagen.oggvorbis import OggVorbis
+
+class OggExporter(ExporterCore):
+ """Defines methods to export to OGG Vorbis"""
+
+ implements(IExporter)
+
+ def __init__(self):
+ self.item_id = ''
+ self.metadata = {}
+ self.description = ''
+ self.info = []
+ self.source = ''
+ self.dest = ''
+ self.options = {}
+ self.bitrate_default = '192'
+ self.buffer_size = 0xFFFF
+ self.dub2args_dict = {'creator': 'artist',
+ 'relation': 'album'
+ }
+
+ def get_format(self):
+ return 'OGG'
+
+ def get_file_extension(self):
+ return 'ogg'
+
+ def get_mime_type(self):
+ return 'application/ogg'
+
+ def get_description(self):
+ return 'FIXME'
+
+ def get_file_info(self):
+ try:
+ file_out1, file_out2 = os.popen4('ogginfo "'+self.dest+'"')
+ info = []
+ for line in file_out2.readlines():
+ info.append(clean_word(line[:-1]))
+ self.info = info
+ return self.info
+ except:
+ raise IOError('ExporterError: file does not exist.')
+
+ def set_cache_dir(self,path):
+ self.cache_dir = path
+
+ def decode(self):
+ try:
+ os.system('oggdec -o "'+self.cache_dir+os.sep+self.item_id+
+ '.wav" "'+self.source+'"')
+ return self.cache_dir+os.sep+self.item_id+'.wav'
+ except:
+ raise IOError('ExporterError: decoder is not compatible.')
+
+ def write_tags(self):
+ media = OggVorbis(self.dest)
+ for tag in self.metadata.keys():
+ media[tag] = str(self.metadata[tag])
+ media.save()
+
+ def get_args(self,options=None):
+ """Get process options and return arguments for the encoder"""
+ args = []
+ if not options is None:
+ self.options = options
+ if not ('verbose' in self.options and self.options['verbose'] != '0'):
+ args.append('-Q ')
+ if 'ogg_bitrate' in self.options:
+ args.append('-b '+self.options['ogg_bitrate'])
+ elif 'ogg_quality' in self.options:
+ args.append('-q '+self.options['ogg_quality'])
+ else:
+ args.append('-b '+self.bitrate_default)
+ else:
+ args.append('-Q -b '+self.bitrate_default)
+
+ for tag in self.metadata.keys():
+ value = clean_word(self.metadata[tag])
+ args.append('-c %s="%s"' % (tag, value))
+ if tag in self.dub2args_dict.keys():
+ arg = self.dub2args_dict[tag]
+ args.append('-c %s="%s"' % (arg, value))
+
+ return args
+
+ def process(self, item_id, source, metadata, options=None):
+ self.item_id = item_id
+ self.source = source
+ self.metadata = metadata
+ self.args = self.get_args(options)
+ self.ext = self.get_file_extension()
+ self.args = ' '.join(self.args)
+ self.command = 'sox "%s" -s -q -r 44100 -t wav -c2 - | oggenc %s -' % (self.source, self.args)
+
+ # Pre-proccessing
+ self.dest = self.pre_process(self.item_id,
+ self.source,
+ self.metadata,
+ self.ext,
+ self.cache_dir,
+ self.options)
+
+ # Processing (streaming + cache writing)
+ stream = self.core_process(self.command, self.buffer_size, self.dest)
+ for chunk in stream:
+ yield chunk
+
+ # Post-proccessing
+ #self.post_process(self.item_id,
+ #self.source,
+ #self.metadata,
+ #self.ext,
+ #self.cache_dir,
+ #self.options)
+
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@parisson.com>
+# 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/deefuzz/wiki/DefuzzLicense.
+#
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+import os
+import re
+import sys
+import time
+import datetime
+import string
+import random
+
+def clean_word(word) :
+ """ Return the word without excessive blank spaces, underscores and
+ characters causing problem to exporters"""
+ word = re.sub("^[^\w]+","",word) #trim the beginning
+ word = re.sub("[^\w]+$","",word) #trim the end
+ word = re.sub("_+","_",word) #squeeze continuous _ to one _
+ word = re.sub("^[^\w]+","",word) #trim the beginning _
+ #word = string.replace(word,' ','_')
+ #word = string.capitalize(word)
+ dict = '&[];"*:,'
+ for letter in dict:
+ word = string.replace(word,letter,'_')
+ return word
\ No newline at end of file