long_description = open('README.rst').read(),
author = ["Guillaume Pellerin", "Olivier Guilyardi", "Riccardo Zaccarelli", "Paul Brossier"],
author_email = ["yomguy@parisson.com","olivier@samalyse.com", "riccardo.zaccarelli@gmail.com", "piem@piem.org"],
- version = '0.4.1',
+ version = '0.4.2',
install_requires = [
'setuptools',
'numpy',
from max_level import *
from mean_level import *
from dc import *
-#from duration import *
+
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 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>
-
-from timeside.core import Processor, implements, interfacedoc, FixedSizeInputAdapter
-from timeside.analyzer.core import *
-from timeside.api import IValueAnalyzer
-
-
-class Duration(Processor):
- """A rather useless duration analyzer. Its only purpose is to test the
- nframes characteristic."""
- implements(IValueAnalyzer)
-
- @interfacedoc
- def setup(self, channels, samplerate, blocksize=None, totalframes=None):
- super(Duration, self).setup(channels, samplerate, blocksize, totalframes)
- if not totalframes:
- raise Exception("nframes argument required")
-
- @staticmethod
- @interfacedoc
- def id():
- return "duration"
-
- @staticmethod
- @interfacedoc
- def name():
- return "Duration"
-
- @staticmethod
- @interfacedoc
- def unit():
- return "seconds"
-
- def __str__(self):
- return "%s %s" % (str(self.value), unit())
-
- def process(self, frames, eod=False):
- return frames, eod
-
- def result(self):
- return self.input_nframes / float(self.input_samplerate)
-
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2007-2009 Parisson
+# Copyright (C) 2007-2012 Parisson SARL
# Copyright (c) 2007 Olivier Guilyardi <olivier@samalyse.com>
# Copyright (c) 2007-2009 Guillaume Pellerin <pellerin@parisson.com>
#
_processors = {}
+
class MetaProcessor(MetaComponent):
"""Metaclass of the Processor class, used mainly for ensuring that processor
id's are wellformed and unique"""
return new_class
+
class Processor(Component):
"""Base component class of all processors"""
__metaclass__ = MetaProcessor
def __or__(self, other):
return ProcessPipe(self, other)
+
class FixedSizeInputAdapter(object):
"""Utility to make it easier to write processors which require fixed-sized
input buffers."""
return _processors[processor_id]
+
class ProcessPipe(object):
"""Handle a pipe of processors"""
source = self.processors[0]
items = self.processors[1:]
-
- # setup/reset processors and configure channels and samplerate throughout the pipe
source.setup()
+
#FIXME: wait for decoder mainloop
time.sleep(0.1)
last = source
+ # setup/reset processors and configure properties throughout the pipe
for item in items:
item.setup(channels = last.channels(),
samplerate = last.samplerate(),
self.chunk = self.app.emit('pull-buffer')
return frames, eod
-from timeside.core import *
-import subprocess
-
-class SubProcessPipe(object):
- """Read media and stream data through a generator.
- Taken from Telemeta (see http://telemeta.org)"""
-
- def __init__(self, command, stdin=None):
- self.buffer_size = 0xFFFF
- if not stdin:
- stdin = subprocess.PIPE
-
- self.proc = subprocess.Popen(command.encode('utf-8'),
- shell = True,
- bufsize = self.buffer_size,
- stdin = stdin,
- stdout = subprocess.PIPE,
- close_fds = True)
-
- self.input = self.proc.stdin
- self.output = self.proc.stdout
-
-
-class EncoderSubProcessCore(Processor):
- """Defines the main parts of the encoding tools :
- paths, metadata parsing, data streaming thru system command"""
-
- def core_process(self, command, stdin):
- """Encode and stream audio data through a generator"""
-
- proc = SubProcessPipe(command, stdin)
-
- while True:
- __chunk = proc.output.read(proc.buffer_size)
- #status = proc.poll()
- #if status != None and status != 0:
- #raise EncodeProcessError('Command failure:', command, proc)
- if len(__chunk) == 0:
- break
- yield __chunk
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2007 Parisson SARL
-# Copyright (c) 2006-2007 Guillaume Pellerin <pellerin@parisson.com>
+# Copyright (C) 2007-2012 Parisson SARL
+# Copyright (c) 2006-2012 Guillaume Pellerin <pellerin@parisson.com>
+# Copyright (c) 2010-2012 Paul Brossier <piem@piem.org>
+# Copyright (c) 2009-2010 Olivier Guilyardi <olivier@samalyse.com>
+
# This file is part of TimeSide.
except:
raise IOError('EncoderError: cannot write tags')
-class Mp3EncoderSubprocess(object):
- """MP3 encoder in a subprocess pipe"""
-
-# implements(IEncoder)
-
- def __init__(self):
- import os
- import string
- import subprocess
- self.bitrate_default = '192'
- self.dub2id3_dict = {'title': 'TIT2', #title2
- 'creator': 'TCOM', #composer
- 'creator': 'TPE1', #lead
- 'identifier': 'UFID', #Unique ID...
- 'identifier': 'TALB', #album
- 'type': 'TCON', #genre
- 'publisher': 'TPUB', #comment
- #'date': 'TYER', #year
- }
- self.dub2args_dict = {'title': 'tt', #title2
- 'creator': 'ta', #composerS
- 'relation': 'tl', #album
- #'type': 'tg', #genre
- 'publisher': 'tc', #comment
- 'date': 'ty', #year
- }
-
- @interfacedoc
- def setup(self, channels=None, samplerate=None, nframes=None):
- self.channels = channels
- super(Mp3EncoderSubprocess, self).setup(channels, samplerate, nframes)
-
- @staticmethod
- @interfacedoc
- def id():
- return "subprocess_mp3_enc"
-
- @staticmethod
- @interfacedoc
- def description():
- return "MP3 subprocess based encoder"
-
- @staticmethod
- @interfacedoc
- def format():
- return "MP3"
-
- @staticmethod
- @interfacedoc
- def file_extension():
- return "mp3"
-
- @staticmethod
- @interfacedoc
- def mime_type():
- return "audio/mpeg"
-
- @interfacedoc
- def set_metadata(self, metadata):
- self.metadata = metadata
-
- def get_file_info(self):
- try:
- file_out1, file_out2 = os.popen4('mp3info "'+self.dest+'"')
- info = []
- for line in file_out2.readlines():
- info.append(clean_word(line[:-1]))
- self.info = info
- return self.info
- except:
- raise IOError('EncoderError: file does not exist.')
-
- def write_tags(self):
- """Write all ID3v2.4 tags by mapping dub2id3_dict dictionnary with the
- respect of mutagen classes and methods"""
- from mutagen import id3
- id3 = id3.ID3(self.dest)
- 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('EncoderError: cannot tag "'+tag+'"')
- try:
- id3.save()
- except:
- raise IOError('EncoderError: cannot write tags')
-
- def get_args(self):
- """Get process options and return arguments for the encoder"""
- args = []
- if not self.options is None:
- 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 --tt "unknown" -o')
-
- for tag in self.metadata:
- name = tag[0]
- value = clean_word(tag[1])
- if name in self.dub2args_dict.keys():
- arg = self.dub2args_dict[name]
- args.append('--' + arg + ' "' + value + '"')
- return args
-
- def process(self, source, metadata, options=None):
- self.metadata = metadata
- self.options = options
- args = self.get_args()
- args = ' '.join(args)
- command = 'lame %s - -' % args
-
- stream = self.core_process(command, source)
- for __chunk in stream:
- yield __chunk
from timeside.core import *
import subprocess
+
class SubProcessPipe(object):
"""Read media and stream data through a generator.
Taken from Telemeta (see http://telemeta.org)"""