From 800e3caabcd9c85b0b2ae9299217ea31d0309545 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Sun, 28 Oct 2007 09:45:28 +0000 Subject: Initial import --- (limited to 'util') diff --git a/util/__init__.py b/util/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/util/__init__.py diff --git a/util/audioplayer.py b/util/audioplayer.py new file mode 100644 index 0000000..911fa42 --- /dev/null +++ b/util/audioplayer.py @@ -0,0 +1,132 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import os +import gst +import logging + +from globals import Globals + +from util.decorators import Property + + +class AudioPlayer(object): + + def __init__(self): + pass + + + @Property + def uri(): + def get(self): return self.__uri + def set(self, value): + if value is None or not os.path.exists(value): + logging.error('AudioPlayer- Invalid URI: %r', value) + return + self.__uri = value + size = os.path.getsize(self.__uri) + self.pipeline.get_by_name('source').set_property('location', self.__uri) + self.pipeline.get_by_name('source').set_property('mmapsize', size) + + + @Property + def raw(): + def get(self): + if self.uri is None: + logging.error('AudioPlayer - No data') + return None + f = open(self.uri, 'r') + raw = f.read() + f.close() + return raw + def set(self, value): + temp = Globals.temporary_filename() + f = open(temp, 'w') + f.write(value) + f.close() + #self.source.set_property('location', temp) + #self.source.set_property('mmapsize', len(value)) + self.uri = temp + logging.debug('AudioPlayer - set_raw wrote %d bytes to %s', len(value), temp) + + + @Property + def pipeline(): + def get(self): + if self.__pipeline is None: + self.__pipeline = self.__build_pipeline() + return self.__pipeline + + + def play(self): + logging.debug('AudioPlayer - started playing sound') + self.pipeline.set_state(gst.STATE_PLAYING) + logging.debug('AudioPlayer - finished playing sound') + + + + def __build_pipeline(self): + # pipeline + pipeline = gst.Pipeline('pipeline') + + # add source + source = gst.element_factory_make('filesrc', 'source') + pipeline.add(source) + + # add decoder + decoder = gst.element_factory_make('decodebin', 'decoder') + decoder.connect("new-decoded-pad", self.__new_decoded_pad) #, converter) + pipeline.add(decoder) + source.link(decoder) + + # add converter + converter = gst.element_factory_make("audioconvert", "converter") + pipeline.add(converter) + + # add output + sink = gst.element_factory_make('autoaudiosink', 'sink') + pipeline.add(sink) + converter.link(sink) + + bus = pipeline.get_bus() + bus.add_signal_watch() + bus.connect('message', self.__on_audio_message) + + return pipeline + + + + # callbacks ################################################################## + + def __new_decoded_pad(self, dbin, pad, islast): #, converter) + converter = self.pipeline.get_by_name('converter') # TODO - pass by arg + pad.link(converter.get_pad("sink")) + + + def __on_audio_message(self, bus, message): + t = message.type + #logging.debug('message: %r' % t) + if t == gst.MESSAGE_EOS: + self.pipeline.set_state(gst.STATE_NULL) + logging.debug('AudioPlayer - EOS') + elif t == gst.MESSAGE_ERROR: + self.pipeline.set_state(gst.STATE_NULL) + err, debug = message.parse_error() + logging.debug('AudioPlayer - Error: %r %r', err, debug) + + + # Not used + def __on_source_handoff(self, source, buffer, pad): + logging.debug('on_source_handoff(%r, %r, %r)', source, buffer, pad) diff --git a/util/decorators.py b/util/decorators.py new file mode 100644 index 0000000..cd00afc --- /dev/null +++ b/util/decorators.py @@ -0,0 +1,64 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import sys + + +# Courtesy of: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/465427 +DecoratorWithArgs = \ + lambda decorator: lambda *args, **kwargs: lambda func: decorator(func, *args, **kwargs) + + + +def Property(function): + '''Property Decorator + Adapted from: http://wiki.python.org/moin/PythonDecoratorLibrary + + Example: + + class Foo(object): + @Property + def my_property(): + def get(self): return self.__my_property + def set(self, value): self.__my_property = value # (optional) + def default(self): return 'some default value' # (optional) + ''' + + keys = 'set', 'del' + func_locals = {'doc':function.__doc__} + + def fgetter(obj, name, getter, fdef): + attr_name = '_' + obj.__class__.__name__ + '__' + name + if not hasattr(obj, attr_name): + setattr(obj, attr_name, fdef(obj)) + return getter(obj) + + def introspect(frame, event, arg): + if event == 'return': + locals = frame.f_locals + func_locals.update(dict(('f' + k,locals.get(k)) for k in keys)) + if locals.has_key('default'): + func_locals['fget'] = lambda obj : fgetter(obj, function.__name__, locals['get'], locals['default']) + else: + func_locals['fget'] = lambda obj : fgetter(obj, function.__name__, locals['get'], lambda x : None) + + sys.settrace(None) + return introspect + + sys.settrace(introspect) + function() + + return property(**func_locals) + diff --git a/util/journalpickler.py b/util/journalpickler.py new file mode 100644 index 0000000..36f9311 --- /dev/null +++ b/util/journalpickler.py @@ -0,0 +1,47 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import pickle # TODO -> why does cPickle bitch about needing persistence.Jokebook etc ? + + +class JournalPickler: + '''Works with util.Persistence to persist objects to the Sugar Journal''' + + def __init__(self, obj = None): + pass + + def __set_dirty(self, obj, is_dirty): + obj.__dirty__ = False + for name, prop in obj.__properties__: + if prop.fget(obj).__class__ is list: + for item in prop.fget(obj): + if hasattr(item, '__dirty__'): + self.__set_dirty(item, is_dirty) + + + def dumps(self, obj, deep_dump): + self.__set_dirty(obj, False) + pickled = pickle.dumps(obj) + return pickled + + + def loads(self, pickled): + obj = pickle.loads(pickled) + self.__set_dirty(obj, False) + return obj + + +dumps = lambda obj, deep=False : JournalPickler(obj).dumps(obj, deep) +loads = JournalPickler().loads diff --git a/util/persistence.py b/util/persistence.py new file mode 100644 index 0000000..e73879b --- /dev/null +++ b/util/persistence.py @@ -0,0 +1,81 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +import sys + + +class Persistent(type): + '''Metaclass providing object persistence''' + def __init__(cls, name, bases, dct): + super(Persistent, cls).__init__(name, bases, dct) + + setattr(cls, '__dirty__', False) + setattr(cls, '__properties__', filter(_is_persistent, dct.iteritems())) + + from util.journalpickler import dumps, loads + setattr(cls, 'dumps', dumps) + setattr(cls, 'loads', loads) + + + +def PersistentProperty(function): + '''Decorator to set up persistent properties + Adapted from: http://wiki.python.org/moin/PythonDecoratorLibrary + ''' + + func_locals = {'doc':function.__doc__} + + def fgetter(obj, name, getter, fdef): + attr_name = '_' + obj.__class__.__name__ + '__' + name + if not hasattr(obj, attr_name): + setattr(obj, attr_name, fdef(obj)) + return getter(obj) + + def fsetter(obj, name, setter, value): + setattr(obj, '__dirty__', True) # TODO -> Propogate dirty flag up to any + # parent objects ? + return setter(obj, value) + + def introspect(frame, event, arg): + if event == 'return': + locals = frame.f_locals + if locals.has_key('delete'): + func_locals['fdel'] = locals['delete'] + if locals.has_key('set'): + func_locals['fset'] = \ + lambda obj, value : fsetter(obj, function.__name__, locals['set'], value) + if locals.has_key('default'): + get_function = lambda obj : fgetter(obj, function.__name__, locals['get'], locals['default']) + else: + get_function = lambda obj : fgetter(obj, function.__name__, locals['get'], lambda x : None) + get_function.__decorator__ = PersistentProperty # tag the getter so we can id the + # decorator. Yeah, it's ugly. + func_locals['fget'] = get_function + sys.settrace(None) + return introspect + sys.settrace(introspect) + function() + return property(**func_locals) + + +# a wee bit ugly +def _is_persistent(item): + '''check if property is decorated with PersistentProperty decorator''' + prop = item[1] + return type(prop) is property and \ + hasattr(prop.fget, '__decorator__') and \ + prop.fget.__decorator__ is PersistentProperty + + diff --git a/util/persistence.py.args b/util/persistence.py.args new file mode 100644 index 0000000..1aa235f --- /dev/null +++ b/util/persistence.py.args @@ -0,0 +1,81 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + + +import sys + +from util.decorators import DecoratorWithArgs + + +class Persistent(type): + '''Metaclass providing object persistence''' + def __init__(cls, name, bases, dct): + super(Persistent, cls).__init__(name, bases, dct) + + setattr(cls, '__dirty__', False) + setattr(cls, '__properties__', filter(_is_persistent, dct.iteritems())) + + from util.journalpickler import dumps, loads + setattr(cls, 'dumps', dumps) + setattr(cls, 'loads', loads) + + +@DecoratorWithArgs +def PersistentProperty(function, default = None): + '''Decorator to set persistent properties''' + keys = 'fset', 'fdel' + func_locals = {'doc':function.__doc__} + + def fgetter(obj, name, getter, default_value): + attr_name = '_' + obj.__class__.__name__ + '__' + name + if not hasattr(obj, attr_name): + setattr(obj, attr_name, default_value(obj)) + return getter(obj) + + def fsetter(obj, name, setter, value): + setattr(obj, '__dirty__', True) + return setter(obj, value) + + def introspect(frame, event, arg): + if event == 'return': + locals = frame.f_locals + func_locals.update(dict((k,locals.get(k)) for k in keys)) + if locals.has_key('fset'): + func_locals['fset'] = \ + lambda obj, value : fsetter(obj, function.__name__, locals['fset'], value) + if default != None: + get_function = \ + lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : default) + else: + get_function = \ + lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : None) + get_function.decorator = PersistentProperty # tag the getter so we can id + # the decorator. Yeah, it's ugly. + func_locals['fget'] = get_function + sys.settrace(None) + return introspect + + sys.settrace(introspect) + function() + return property(**func_locals) + + +# a wee bit ugly +def _is_persistent(item): + '''check if property is decorated with PersistentProperty decorator''' + prop = item[1] + return type(prop) is property and \ + hasattr(prop.fget, 'decorator') and \ + prop.fget.decorator is PersistentProperty diff --git a/util/persistence.py.noargs b/util/persistence.py.noargs new file mode 100644 index 0000000..bf982af --- /dev/null +++ b/util/persistence.py.noargs @@ -0,0 +1,75 @@ +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + + +import sys + + +def is_persistent(item): + prop = item[1] + return type(prop) is property and \ + hasattr(prop.fget, 'decorator') and \ + prop.fget.decorator is PersistentProperty + + +class Persistent(type): + def __init__(cls, name, bases, dct): + # is_dirty + setattr(cls, '__dirty__', False) + + # properties + setattr(cls, '__properties__', filter(is_persistent, dct.iteritems())) + + super(Persistent, cls).__init__(name, bases, dct) + + +def PersistentProperty(function): + function.decorator = PersistentProperty + + keys = 'fset', 'fdel' + func_locals = {'doc':function.__doc__} + + def fgetter(obj, name, getter, fdef): + attr_name = '_' + obj.__class__.__name__ + '__' + name + if not hasattr(obj, attr_name): + setattr(obj, attr_name, fdef(obj)) + return getter(obj) + + def fsetter(obj, name, setter, value): + setattr(obj, '__dirty__', True) + return setter(obj, value) + + def probe_function(frame, event, arg): + if event == 'return': + locals = frame.f_locals + func_locals.update(dict((k,locals.get(k)) for k in keys)) + + if locals.has_key('fset'): + func_locals['fset'] = lambda obj, value : fsetter(obj, function.__name__, locals['fset'], value) + + if locals.has_key('fdef'): + f = lambda obj : fgetter(obj, function.__name__, locals['fget'], locals['fdef']) + else: + f = lambda obj : fgetter(obj, function.__name__, locals['fget'], lambda x : None) + f.decorator = PersistentProperty # tag the getter + func_locals['fget'] = f + + sys.settrace(None) + return probe_function + sys.settrace(probe_function) + function() + return property(**func_locals) + + -- cgit v0.9.1