diff options
Diffstat (limited to 'olpcfr/tools')
-rw-r--r-- | olpcfr/tools/__init__.py | 2 | ||||
-rw-r--r-- | olpcfr/tools/_logger.py | 10 | ||||
-rw-r--r-- | olpcfr/tools/_obj.py | 9 | ||||
-rw-r--r-- | olpcfr/tools/image.py | 110 | ||||
-rw-r--r-- | olpcfr/tools/registry.py | 48 | ||||
-rw-r--r-- | olpcfr/tools/sound.py | 111 | ||||
-rw-r--r-- | olpcfr/tools/storage.py | 150 |
7 files changed, 440 insertions, 0 deletions
diff --git a/olpcfr/tools/__init__.py b/olpcfr/tools/__init__.py new file mode 100644 index 0000000..071fee0 --- /dev/null +++ b/olpcfr/tools/__init__.py @@ -0,0 +1,2 @@ +from olpcfr.tools._obj import obj +from olpcfr.tools._logger import logger diff --git a/olpcfr/tools/_logger.py b/olpcfr/tools/_logger.py new file mode 100644 index 0000000..f8bb9bd --- /dev/null +++ b/olpcfr/tools/_logger.py @@ -0,0 +1,10 @@ + +# flask logger +from olpcfr.flask import app, APP_NAME +if app: + logger = app.logger +# std logger +else: + import logging + logger = logging.getLogger(APP_NAME) + logger.setLevel(logging.DEBUG) diff --git a/olpcfr/tools/_obj.py b/olpcfr/tools/_obj.py new file mode 100644 index 0000000..85c461a --- /dev/null +++ b/olpcfr/tools/_obj.py @@ -0,0 +1,9 @@ + +class obj(object): + + def __init__(self, d): + for a, b in d.items(): + if isinstance(b, (list, tuple)): + setattr(self, a, [obj(x) if isinstance(x, dict) else x for x in b]) + else: + setattr(self, a, obj(b) if isinstance(b, dict) else b) diff --git a/olpcfr/tools/image.py b/olpcfr/tools/image.py new file mode 100644 index 0000000..cffc156 --- /dev/null +++ b/olpcfr/tools/image.py @@ -0,0 +1,110 @@ + +# python import +import logging, os, struct, StringIO + +# atoideweb import +from atoideweb.tools import registry + + +def compute_width_height(width, height, max_width, max_height, use_max=False): + # compute ratio + _ratio_scr = max_width / float(max_height) + _ratio_img = width / float(height) + # .. + if width > max_width\ + or height > max_height: + if _ratio_img > _ratio_scr: + width = max_width + height = int(max_width / _ratio_img) + elif _ratio_img < _ratio_scr: + width = int(max_height * _ratio_img) + height = max_height + else: + width = max_width + height = max_height + # .. + return width, height + # .. + elif use_max is True: + return max_width, max_height + # .. + else: + return width, height + + +def get_image_info(path): + """Tricky method found on Internet that returns the image info from a given + raw image data. + """ + # little check + _info = registry.InfoRegistry().get_info(path) + # already exist + if _info is not None: + return _info + elif os.path.exists(path): + pass + else: + return None, 0, 0 + # read file + _f = open(path) + _data = _f.read() + _f.close() + # + size = len(_data) + height = 0 + width = 0 + content_type = None + + # handle GIFs + if (size >= 10) and _data[:6] in ('GIF87a', 'GIF89a'): + # Check to see if content_type is correct + content_type = 'image/gif' + w, h = struct.unpack("<HH", _data[6:10]) + width = int(w) + height = int(h) + + # See PNG 2. Edition spec (http://www.w3.org/TR/PNG/) + # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR' + # and finally the 4-byte width, height + elif ((size >= 24) and _data.startswith('\211PNG\r\n\032\n') + and (_data[12:16] == 'IHDR')): + content_type = 'image/png' + w, h = struct.unpack(">LL", _data[16:24]) + width = int(w) + height = int(h) + + # Maybe this is for an older PNG version. + elif (size >= 16) and _data.startswith('\211PNG\r\n\032\n'): + # Check to see if we have the right content type + content_type = 'image/png' + w, h = struct.unpack(">LL", _data[8:16]) + width = int(w) + height = int(h) + + # handle JPEGs + elif (size >= 2) and _data.startswith('\377\330'): + content_type = 'image/jpeg' + jpeg = StringIO.StringIO(_data) + jpeg.read(2) + b = jpeg.read(1) + try: + while (b and ord(b) != 0xDA): + while (ord(b) != 0xFF): b = jpeg.read(1) + while (ord(b) == 0xFF): b = jpeg.read(1) + if (ord(b) >= 0xC0 and ord(b) <= 0xC3): + jpeg.read(3) + h, w = struct.unpack(">HH", jpeg.read(4)) + break + else: + jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2) + b = jpeg.read(1) + width = int(w) + height = int(h) + except struct.error: + pass + except ValueError: + pass + # udpate registry + registry.InfoRegistry().set_info(path, (content_type, width, height)) + # .. + return content_type, width, height diff --git a/olpcfr/tools/registry.py b/olpcfr/tools/registry.py new file mode 100644 index 0000000..7e575c3 --- /dev/null +++ b/olpcfr/tools/registry.py @@ -0,0 +1,48 @@ + +# python import +import logging + + +class Registry(object): + + class __Singleton: + """Our singleton object. + """ + + def __init__(self): + """Create the new singleton for a simple use. + """ + # ensure config + self.__dict = dict() + + def get_info(self, path): + # .. + if path in self.__dict: + return self.__dict[path] + else: + return None + + def set_info(self, path, info): + # clear previous + if path in self.__dict: + del self.__dict[path] + else: + pass + # ... + self.__dict[path] = info + + # singleton instance + instance = None + + def __new__(c, force=False): + """Singleton new init. + """ + # if doesn't already initialized + if not Registry.instance \ + or force is True: + # create a new instance + Registry.instance = Registry.__Singleton() + else: + pass + # return the manager object + return Registry.instance diff --git a/olpcfr/tools/sound.py b/olpcfr/tools/sound.py new file mode 100644 index 0000000..7ac6a57 --- /dev/null +++ b/olpcfr/tools/sound.py @@ -0,0 +1,111 @@ + +# python import +import gst +# .. +from datetime import timedelta + + +class Player(object): + + def __init__(self, loop=False): + # playing flag + self.playing = False + self.loop = loop + # player object + self.player = None + self._init_player() + # file to play + self._soundfile = None + + def _reload_cb(self, bus, message): + if self.loop is True: + self.player.set_state(gst.STATE_READY) + self.player.set_state(gst.STATE_PLAYING) + else: + pass + + def _error_cb(self, bus, message): + self.player.set_state(gst.STATE_NULL) + + def _init_player(self): + # make player + self.player = gst.element_factory_make("playbin", "player") + # video fake + _fakesink = gst.element_factory_make('fakesink', "my-fakesink") + self.player.set_property("video-sink", _fakesink) + # bus .. + bus = self.player.get_bus() + bus.add_signal_watch() + bus.connect('message::eos', self._reload_cb) + bus.connect('message::error', self._error_cb) + + def serialize(self): + # little check + if self._soundfile is None: + return None + else: + return file(self._soundfile, 'r').read() + + def load(self, soundfile): + # file to play + self._soundfile = soundfile + # little check + if self._soundfile is None: + pass + else: + # load sound file + self.player.set_state(gst.STATE_NULL) + self.player.set_property('uri', 'file://' + self._soundfile) + + def get_position(self): + # little check + if self._soundfile is None: + return None + else: + # ... + _position = self.player.query_duration(gst.FORMAT_TIME)[0] + # ... + return timedelta(seconds=(_position / gst.SECOND)) + + def get_duration(self): + # little check + if self._soundfile is None: + return None + else: + # _duration = self.player.query_duration(gst.FORMAT_TIME)[0] + # .. + _parser = gst.parse_launch("filesrc name=source ! decodebin2 ! fakesink") + # .. + _source = _parser.get_by_name("source") + _source.set_property("location", self._soundfile) + # .. + _parser.set_state(gst.STATE_PLAYING) + _parser.get_state() + # .. + _format = gst.Format(gst.FORMAT_TIME) + _duration = _parser.query_duration(_format)[0] + _parser.set_state(gst.STATE_NULL) + # .. + return timedelta(seconds=(_duration / gst.SECOND)) + + def seek(self, time): + # little check + if self._soundfile is None: + return + else: + # format time + _seek = time * 1000000000 + # do seek + self.player.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, _seek) + + def play(self): + self.playing = True + self.player.set_state(gst.STATE_PLAYING) + + def pause(self): + self.playing = False + self.player.set_state(gst.STATE_PAUSED) + + def stop(self): + self.playing = False + self.player.set_state(gst.STATE_NULL) diff --git a/olpcfr/tools/storage.py b/olpcfr/tools/storage.py new file mode 100644 index 0000000..3e6ebbf --- /dev/null +++ b/olpcfr/tools/storage.py @@ -0,0 +1,150 @@ +# python import +import os + +# olpcfr import +from olpcfr import BUNDLE, ROOT + + +ACTIVITY_NAMES = { + 'paint': 'org.laptop.Oficina', + 'record': 'org.laptop.RecordActivity', + } + + +def check_dir(path): + if os.path.exists(path): + pass + else: + os.mkdir(path) + + +def check_file(path): + if os.path.exists(path): + pass + else: + _f = open(path, 'wb') + _f.write('') + _f.close() + + +def get_path(path=None, bundle=True): + # .. + path = 'static' if path is None else path + # .. + if bundle is True: + return os.path.join(BUNDLE, path) + else: + return os.path.join(ROOT, path) + + +def list_dir(path=None, bundle=True): + # .. + path = get_path(path=path, bundle=bundle) + # .. + return os.listdir(path) + + +def get_sound_path(filename, path=None, bundle=True, ext=None): + # .. + path = get_path(path=path, bundle=bundle) + filename = filename if ext is None else '%s.%s' % (filename, ext) + # .. + return os.path.join(path, filename) + + +def get_sound_path(filename, path=None, bundle=True, ext='ogg'): + # .. + return get_sound_path(filename, path=path, bundle=bundle, ext=ext) + + +def get_image_path(filename, path=None, bundle=True, ext='png'): + # .. + return get_sound_path(filename, path=path, bundle=bundle, ext=ext) + + +def __do_query(query): + from sugar.datastore import datastore + # find in ds + _results, _count = datastore.find(query, sorting='timestamp') + for _r in _results: + # get meta + _m = _r.get_metadata() + if 'activity' in query: + yield _r + elif _m['activity'] == '': + yield _r + else: + continue + + +def get_journal_objects(activity_name=None, mime_type=None): + # init + _query = dict() + # prepare query name + if activity_name is None\ + and mime_type is None: + return [] + elif mime_type is None: + return __do_query({'activity': ACTIVITY_NAMES[activity_name]}) + else: + return __do_query({'mime_type': mime_type}) + + +def list_info_from_journal(activity_name=None, mime_type=None): + # get objects first + _objs = get_journal_objects(activity_name=activity_name, mime_type=mime_type) + # make unique titles + _titles = {} + # return infos + for _o in _objs: + # get meta + _m = _o.get_metadata() + # get title + _t = _m['title'] + # ensure description + _d = _m['description'] if 'description' in _m else '' + _p = _m['preview'] if 'preview' in _m else None + # little check + if _t in _titles: + # udpate reg + _titles[_t] += 1 + # update value to show + _t = '%s (%s)' % (_t, _titles[_t]) + # init title reg + else: + _titles[_t] = 1 + # ensure info + yield { + 'activity_id' : _m['activity_id'], + 'description' : _d, + 'timestamp' : _m['timestamp'], + 'preview' : _p, + 'title' : _t, + } + + +def list_files_from_journal(activity_name=None, mime_type=None): + # get objects first + _objs = get_journal_objects(activity_name=activity_name, + mime_type=mime_type) + # return paths + for _o in _objs: + # TODO open the files + yield _o.get_file_path() + + +def get_path_from_journal(timestamp, mime_type): + from sugar.datastore import datastore + # .. + _query = { + 'timestamp': int(timestamp), + 'mime_type': mime_type + } + # find in ds + _results, _count = datastore.find(_query) + # .. + if _count == 1: + # get path + return _results[0].get_file_path() + else: + return None |