A set of tools for configuring the Logitech G19 keyboard. Based in: https://github.com/Gnome15/gnome15
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

204 lines
7.8 KiB

#!/usr/bin/env python2
# Gnome15 - Suite of tools for the Logitech G series keyboards and headsets
# Copyright (C) 2011 Brett Smith <tanktarta@blueyonder.co.uk>
#
# 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.
#
# 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, see <http://www.gnu.org/licenses/>.
"""
Simple tool to draw an image on the framebuffer
"""
import sys
import os
import glib
import cairo
import array
from PIL import Image
from PIL import ImageMath
from cStringIO import StringIO
# Allow running from local path
path = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), ".."))
if os.path.exists(path):
sys.path.insert(0, path)
import gnome15.util.g15convert as g15convert
import gnome15.util.g15cairo as g15cairo
import gnome15.drivers.fb as fb
if __name__ == "__main__":
import optparse
parser = optparse.OptionParser()
parser.add_option("-s", "--scale", dest="scale", metavar="stretch,zoom,tile,center,scale",
default="zoom" , help="Scale type")
parser.add_option("-d", "--device", dest="device",
default="/dev/fb0" , help="Framebuffer device")
(options, args) = parser.parse_args()
bg_style = options.scale
# Check arguments
if len(args) != 1:
sys.stderr.write("You must provide a single image filenanme")
sys.exit(1)
# Locate and configure the framebuffer
fb_dev = fb.fb_device(options.device)
var_info = fb_dev.get_var_info()
fixed_info = fb_dev.get_fixed_info()
screen_size = ( var_info.xres, var_info.yres )
width, height = screen_size
# Create an empty string buffer for use with monochrome LCD
empty_buf = ""
for i in range(0, fixed_info.smem_len):
empty_buf += chr(0)
# Load the image
bg_img = args[0]
if g15cairo.is_url(bg_img) or os.path.exists(bg_img):
img_surface = g15cairo.load_surface_from_file(bg_img)
if img_surface is not None:
sx = float(width) / img_surface.get_width()
sy = float(height) / img_surface.get_height()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
context = cairo.Context(surface)
context.save()
if bg_style == "zoom":
scale = max(sx, sy)
context.scale(scale, scale)
context.set_source_surface(img_surface)
context.paint()
elif bg_style == "stretch":
context.scale(sx, sy)
context.set_source_surface(img_surface)
context.paint()
elif bg_style == "scale":
x = ( width - img_surface.get_width() * sy ) / 2
context.translate(x, 0)
context.scale(sy, sy)
context.set_source_surface(img_surface)
context.paint()
elif bg_style == "center":
x = ( width - img_surface.get_width() ) / 2
y = ( height - img_surface.get_height() ) / 2
context.translate(x, y)
context.set_source_surface(img_surface)
context.paint()
elif bg_style == "tile":
context.set_source_surface(img_surface)
context.paint()
y = 0
x = img_surface.get_width()
while y < height + img_surface.get_height():
if x >= height + img_surface.get_width():
x = 0
y += img_surface.get_height()
context.restore()
context.save()
context.translate(x, y)
context.set_source_surface(img_surface)
context.paint()
x += img_surface.get_width()
context.restore()
else:
sys.stderr.write("Failed to load image file %s." % bg_img)
sys.exit(1)
else:
sys.stderr.write("Image path %s is not a URL or an existing file." % bg_img)
sys.exit(1)
# Convert the image to the required format for this device
if var_info.bits_per_pixel == 16:
try:
back_surface = cairo.ImageSurface (4, width, height)
except Exception as e:
logger.debug("Could not create ImageSurface. Trying alternative method", exc_info = e)
# Earlier version of Cairo
back_surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height)
back_context = cairo.Context (back_surface)
back_context.set_source_surface(surface, 0, 0)
back_context.set_operator (cairo.OPERATOR_SOURCE);
back_context.paint()
if back_surface.get_format() == cairo.FORMAT_ARGB32:
"""
If the creation of the type 4 image failed (i.e. earlier version of Cairo)
then we have to convert it ourselves. This is slow.
TODO Replace with C routine
"""
file_str = StringIO()
data = back_surface.get_data()
for i in range(0, len(data), 4):
r = ord(data[i + 2])
g = ord(data[i + 1])
b = ord(data[i + 0])
file_str.write(g15convert.rgb_to_uint16(r, g, b))
buf = file_str.getvalue()
else:
buf = str(back_surface.get_data())
else:
arrbuf = array.array('B', empty_buf)
argb_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
argb_context = cairo.Context(argb_surface)
argb_context.set_source_surface(surface)
argb_context.paint()
'''
Now convert the ARGB to a PIL image so it can be converted to a 1 bit monochrome image, with all
colours dithered. It would be nice if Cairo could do this :( Any suggestions?
'''
pil_img = Image.frombuffer("RGBA", (width, height), argb_surface.get_data(), "raw", "RGBA", 0, 1)
pil_img = ImageMath.eval("convert(pil_img,'1')",pil_img=pil_img)
pil_img = ImageMath.eval("convert(pil_img,'P')",pil_img=pil_img)
pil_img = pil_img.point(lambda i: i >= 250,'1')
# Invert the screen if required
if options.invert:
pil_img = pil_img.point(lambda i: 1^i)
# Data is 160x43, 1 byte per pixel. Will have value of 0 or 1.
data = list(pil_img.getdata())
v = 0
b = 1
# TODO Replace with C routine
for row in range(0, height):
for col in range(0, width):
if data[( row * width ) + col]:
v += b
b = b << 1
if b == 256:
# Full byte
b = 1
i = row * fixed_info.line_length + col / 8
if row > 7 and col < 96:
'''
????? This was discovered more by trial and error rather than any
understanding of what is going on
'''
i -= 12 + ( 7 * fixed_info.line_length )
arrbuf[i] = v
v = 0
buf = arrbuf.tostring()
# Write to buffer
fb_dev.buffer[0:len(buf)] = buf