- MetaProcessor now ensures that all id's are wellformed and unique and raise an exception otherwise
- add id() to all encoders and decoders, and make it static in analyzers and graphers
- remove underscores and shorten a couple of id's, see the doc of IProcessor.id()
class IAnalyzer(IProcessor):
"""Media item analyzer driver interface"""
- @staticmethod
- def id():
- """Return a short id alphanumeric, lower-case string."""
-
@staticmethod
def name():
"""Return the analyzer name, such as "Mean Level", "Max level",
implements(IAnalyzer)
- def id(self):
- return "nb_channels"
+ @staticmethod
+ def id():
+ return "nchannels"
def name(self):
return "Channels"
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "dc"
def name(self):
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "duration"
def name(self):
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "encoding"
def name(self):
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "format"
def name(self):
implements(IAnalyzer)
- def id(self):
- return "max_level"
+ @staticmethod
+ def id():
+ return "maxlevel"
def name(self):
return "Maximum peak level"
def render(self, media_item, options=None):
self.pre_process(media_item)
samples = self.get_samples()
- return numpy.round(20*numpy.log10(numpy.max(samples)),2)
\ No newline at end of file
+ return numpy.round(20*numpy.log10(numpy.max(samples)),2)
implements(IAnalyzer)
- def id(self):
- return "mean_level"
+ @staticmethod
+ def id():
+ return "meanlevel"
def name(self):
return "Mean RMS level"
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "resolution"
def name(self):
if '32' in self.encoding:
return 32
else:
- return ''
\ No newline at end of file
+ return ''
implements(IAnalyzer)
- def id(self):
+ @staticmethod
+ def id():
return "samplerate"
def name(self):
from timeside.component import Interface
class IProcessor(Interface):
- pass
+
+ @staticmethod
+ def id():
+ """Return a short alphanumeric, lower-case string which uniquely
+ identify this processor. Only letters and digits are allowed.
+ An exception will be raised by MetaProcessor if the id is malformed or
+ not unique amongst registered processors.
+
+ Typically this identifier is likely to be used during HTTP requests
+ and be passed as a GET parameter. Thus it should be as short as possible."""
from timeside.component import *
from timeside.api import IProcessor
+import re
__all__ = ['Processor', 'Component', 'implements', 'processors', 'TimeSideError']
"""Exception base class for errors in TimeSide."""
# FIXME: is this redundant with Django's error handling ?
-_processors = []
+_processors = {}
class MetaProcessor(MetaComponent):
- """Metaclass of the Processor class, used mainly for ensuring uniqueness of
- processor id's"""
+ """Metaclass of the Processor class, used mainly for ensuring that processor
+ id's are wellformed and unique"""
+
+ valid_id = re.compile("^[a-z][a-z0-9]*$")
+
def __new__(cls, name, bases, d):
new_class = MetaComponent.__new__(cls, name, bases, d)
- id = "fixme"
- _processors.append((id, new_class))
+ if new_class in implementations(IProcessor):
+ id = str(new_class.id())
+ if _processors.has_key(id):
+ raise TimeSideError("%s and %s have the same id: '%s'"
+ % (new_class.__name__, _processors[id].__name__, id))
+ if not MetaProcessor.valid_id.match(id):
+ raise TimeSideError("%s has a malformed id: '%s'"
+ % (new_class.__name__, id))
+
+
+ _processors[id] = new_class
+
return new_class
class Processor(Component):
self.output = self.proc.stdout
-class DecoderCore(Component):
+class DecoderCore(Processor):
"""Defines the main parts of the decoding tools :
paths, metadata parsing, data streaming thru system command"""
implements(IDecoder)
+ @staticmethod
+ def id():
+ return "flacdec"
+
def format(self):
return 'FLAC'
def __init__(self):
self.command = 'sox -t mp3 "%s" -q -b 16 -r 44100 -t wav -c2 - '
+ @staticmethod
+ def id():
+ return "mp3dec"
+
def format(self):
return 'MP3'
implements(IDecoder)
+ @staticmethod
+ def id():
+ return "oggdec"
+
def format(self):
return 'OggVorbis'
implements(IDecoder)
+ @staticmethod
+ def id():
+ return "wavdec"
+
def format(self):
return 'WAV'
'relation': 'album'
}
+ @staticmethod
+ def id():
+ return "flacenc"
+
def format(self):
return 'FLAC'
'publisher': 'tc', #comment
'date': 'ty', #year
}
+
+ @staticmethod
+ def id():
+ return "mp3enc"
+
def format(self):
return 'MP3'
'relation': 'album'
}
+ @staticmethod
+ def id():
+ return "oggenc"
+
def format(self):
return 'OggVorbis'
def __init__(self):
pass
+ @staticmethod
+ def id():
+ return "wavenc"
+
def format(self):
return 'WAV'
class IGrapher(IProcessor):
"""Media item visualizer driver interface"""
- @staticmethod
- def id():
- """Return a short id alphanumeric, lower-case string."""
-
@staticmethod
def name():
"""Return the graph name, such as "Waveform", "Spectral view",
bg_color = None
color_scheme = None
- def id(self):
- return "spectrogram_audiolab"
+ @staticmethod
+ def id():
+ #FIXME: too long + underscore discouraged
+ return "spectrogram"
def name(self):
return "Spectrogram (audiolab)"
bg_color = None
color_scheme = None
- def id(self):
- return "waveform_audiolab"
+ @staticmethod
+ def id():
+ #FIXME: too long + underscore discouraged
+ return "waveform"
def name(self):
return "Waveform (audiolab)"
list_processors(i, prefix + " ")
processors = timeside.processors(interface, False)
for p in processors:
- print prefix + " " + p.__name__
+ print prefix + " %s [%s]" % (p.__name__, p.id())
list_processors(timeside.api.IProcessor)