# -*- 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"
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