# -*- coding: utf-8 -*- #Copyright (c) 2011 Walter Bender # 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 3 of the License, or # (at your option) any later version. # # You should have received a copy of the GNU General Public License # along with this library; if not, write to the Free Software # Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA from gi.repository import GdkPixbuf import os import subprocess from gettext import gettext as _ XO1 = 'xo1' XO15 = 'xo1.5' XO175 = 'xo1.75' UNKNOWN = 'unknown' def play_audio_from_file(file_path): """ Audio media """ command_line = ['gst-launch', 'filesrc', 'location=' + file_path, '! oggdemux', '! vorbisdec', '! audioconvert', '! alsasink'] subprocess.call(command_line) def get_hardware(): """ Determine whether we are using XO 1.0, 1.5, or "unknown" hardware """ product = _get_dmi('product_name') if product is None: if os.path.exists('/sys/devices/platform/lis3lv02d/position'): return XO175 # FIXME: temporary check for XO 1.75 elif os.path.exists('/etc/olpc-release') or \ os.path.exists('/sys/power/olpc-pm'): return XO1 else: return UNKNOWN if product != 'XO': return UNKNOWN version = _get_dmi('product_version') if version == '1': return XO1 elif version == '1.5': return XO15 else: return XO175 def _get_dmi(node): ''' The desktop management interface should be a reliable source for product and version information. ''' path = os.path.join('/sys/class/dmi/id', node) try: return open(path).readline().strip() except: return None def get_path(activity, subpath): """ Find a Rainbow-approved place for temporary files. """ try: return(os.path.join(activity.get_activity_root(), subpath)) except: # Early versions of Sugar didn't support get_activity_root() return(os.path.join(os.environ['HOME'], ".sugar/default", "org.sugarlabs.PortfolioActivity", subpath)) def _luminance(color): ''' Calculate luminance value ''' return int(color[1:3], 16) * 0.3 + int(color[3:5], 16) * 0.6 + \ int(color[5:7], 16) * 0.1 def lighter_color(colors): ''' Which color is lighter? Use that one for the text background ''' if _luminance(colors[0]) > _luminance(colors[1]): return 0 return 1 def svg_str_to_pixbuf(svg_string): ''' Load pixbuf from SVG string ''' pl = GdkPixbuf.PixbufLoader() pl.write(svg_string) pl.close() pixbuf = pl.get_pixbuf() return pixbuf def svg_rectangle(width, height, colors): ''' Generate a rectangle frame in two colors ''' return \ '\ \ \ \ \ \ ' % (width, height, width - 5, height - 5, colors[1], width - 15, height - 15, colors[0]) def load_svg_from_file(file_path, width, height): '''Create a pixbuf from SVG in a file. ''' return GdkPixbuf.Pixbuf.new_from_file_at_size(file_path, width, height) def file_to_base64(activity, path): ''' Given a file, convert its contents to base64 ''' base64 = os.path.join(get_path(activity, 'instance'), 'base64tmp') cmd = 'base64 <' + path + ' >' + base64 subprocess.check_call(cmd, shell=True) file_handle = open(base64, 'r') data = file_handle.read() file_handle.close() os.remove(base64) return data def pixbuf_to_base64(activity, pixbuf, width=100, height=75): ''' Convert pixbuf to base64-encoded data ''' png_file = os.path.join(get_path(activity, 'instance'), 'imagetmp.png') if pixbuf != None: pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.NEAREST) pixbuf.save(png_file, "png") data = file_to_base64(activity, png_file) os.remove(png_file) return data def base64_to_file(activity, data, path): ''' Given a file, convert its contents from base64 ''' base64 = os.path.join(get_path(activity, 'instance'), 'base64tmp') file_handle = open(base64, 'w') file_handle.write(data) file_handle.close() cmd = 'base64 -d <' + base64 + '>' + path subprocess.check_call(cmd, shell=True) os.remove(base64) def base64_to_pixbuf(activity, data, width=300, height=225): ''' Convert base64-encoded data to a pixbuf ''' png_file = os.path.join(get_path(activity, 'instance'), 'imagetmp.png') base64_to_file(activity, data, png_file) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(png_file, width, height) os.remove(png_file) return pixbuf def get_pixbuf_from_journal(dsobject, w, h): """ Load a pixbuf from a Journal object. """ pixbufloader = \ GdkPixbuf.PixbufLoader.new_with_mime_type('image/png') pixbufloader.set_size(min(300, int(w)), min(225, int(h))) try: pixbufloader.write(dsobject.metadata['preview']) pixbuf = pixbufloader.get_pixbuf() except: pixbuf = None pixbufloader.close() return pixbuf def get_pixbuf_from_file(file_path, w, h): """ Load a pixbuf from a file. """ return GdkPixbuf.Pixbuf.new_from_file_at_size(file_path, w, h) def genblank(w, h, colors, stroke_width=1.0): svg = SVG() svg.set_colors(colors) svg.set_stroke_width(stroke_width) svg_string = svg.header(w, h) svg_string += svg.footer() return svg_string class SVG: ''' SVG generators ''' def __init__(self): self._scale = 1 self._stroke_width = 1 self._fill = '#FFFFFF' self._stroke = '#FFFFFF' def _svg_style(self, extras=""): return "%s%s%s%s%s%f%s%s%s" % ("style=\"fill:", self._fill, ";stroke:", self._stroke, ";stroke-width:", self._stroke_width, ";", extras, "\" />\n") def _svg_rect(self, w, h, rx, ry, x, y): svg_string = " \n" svg_string += "\n" svg_string += "\n") svg_string += "%s%f%s%f%s" % ("\n") if background: svg_string += self._background(w, h, scale) return svg_string def footer(self): svg_string = "\n" svg_string += "\n" return svg_string def set_scale(self, scale=1.0): self._scale = scale def set_colors(self, colors): self._stroke = colors[0] self._fill = colors[1] def set_stroke_width(self, stroke_width=1.0): self._stroke_width = stroke_width