Fix stuck button highlighting in overlay
[raemote.git] / usr / lib / hildon-desktop / raemote.py
blobfa3926ca7ea6294a0c5f2f96584cc0cbeecb7a06
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 # RæMote for Maemo
4 # Copyright (c) 2010-03-08 Thomas Perl <thpinfo.com/about>
5 # Licensed under the terms of the GNU GPL v3 or later
7 import os
8 import subprocess
9 import gtk
10 import gobject
11 import cairo
12 import hildondesktop
13 import osso
15 def restart_lirc():
16 subprocess.Popen(['sudo', '/etc/init.d/lirc', 'restart'])
18 def send_ir(remote, code):
19 subprocess.Popen(['sudo', 'irsend', 'SEND_ONCE', remote, code])
21 class Rectangle(object):
22 def __init__(self, action, x1, y1, x2, y2):
23 self.action = action
24 self.x1 = int(x1)
25 self.y1 = int(y1)
26 self.x2 = int(x2)
27 self.y2 = int(y2)
29 def has_point(self, x, y):
30 return x >= self.x1 and x <= self.x2 and y >= self.y1 and y <= self.y2
32 class RaeMote(hildondesktop.HomePluginItem):
33 DEBUG_RECTANGLES = False
34 BASEDIR = '/opt/raemote/'
35 REMOTE = 'apple'
37 def __init__(self):
38 hildondesktop.HomePluginItem.__init__(self)
40 self.set_settings(True)
41 self.connect('show-settings', self.on_settings)
43 name_file = os.path.join(self.BASEDIR, self.REMOTE, 'name')
44 rect_file = os.path.join(self.BASEDIR, self.REMOTE, 'rects')
45 image_file = os.path.join(self.BASEDIR, self.REMOTE, 'bg.png')
47 self.remote_name = open(name_file).read().strip()
48 self.rectangles = self.load_rectangles(rect_file)
49 self.image = cairo.ImageSurface.create_from_png(image_file)
51 screen = self.get_screen()
52 colormap = screen.get_rgba_colormap()
53 self.set_colormap(colormap)
55 self.overlay = None
56 self._clear_overlay_source_id = None
57 self.set_size_request(self.image.get_width(),
58 self.image.get_height())
60 self.connect('expose-event', self.on_expose_event)
61 self.connect('button-press-event', self.on_button_press)
62 self.connect('button-release-event', self.on_button_release)
63 self.set_events(gtk.gdk.BUTTON_PRESS_MASK | \
64 gtk.gdk.BUTTON_RELEASE_MASK)
66 # Make sure lircd is running
67 restart_lirc()
69 def load_rectangles(self, filename):
70 result = []
71 for rect_def in open(filename).read().strip().splitlines():
72 if rect_def and not rect_def.startswith('#'):
73 result.append(Rectangle(*(rect_def.split())))
74 return result
76 def load_overlay(self, action):
77 overlay_file = os.path.join(self.BASEDIR, self.REMOTE, action+'.png')
78 return cairo.ImageSurface.create_from_png(overlay_file)
80 def on_settings(self, widget):
81 dialog = gtk.Dialog()
82 dialog.set_title('About RaeMote')
83 dialog.add_button('Visit website', 1)
84 dialog.add_button('Report bug', 2)
85 dialog.add_button('Donate', 3)
86 dialog.vbox.add(gtk.Label('Version 1.1 (2010-03-18)'))
87 dialog.vbox.add(gtk.Label('Copyright (c) 2010 Thomas Perl <http://thpinfo.com>'))
88 dialog.show_all()
89 result = dialog.run()
90 dialog.destroy()
91 if result >= 1 and result <= 3:
92 ctx = osso.Context('com.thpinfo.raemote', '1.0', False)
93 rpc = osso.Rpc(ctx)
94 if result == 1:
95 rpc.rpc_run_with_defaults('osso_browser', 'open_new_window',
96 ('http://thpinfo.com/2010/raemote',))
97 elif result == 2:
98 rpc.rpc_run_with_defaults('osso_browser', 'open_new_window',
99 ('http://talk.maemo.org/showthread.php?t=46870',))
100 elif result == 3:
101 rpc.rpc_run_with_defaults('osso_browser', 'open_new_window',
102 ('http://thpinfo.com/2010/raemote/donate',))
104 def on_button_press(self, widget, event):
105 if self.overlay is None:
106 for rectangle in self.rectangles:
107 if rectangle.has_point(event.x, event.y):
108 self.overlay = self.load_overlay(rectangle.action)
109 self.queue_draw()
110 send_ir(self.remote_name, rectangle.action)
112 # Remove the overlay after 100ms
113 self._clear_overlay_source_id = \
114 gobject.timeout_add(100, self.on_button_release)
115 return
117 def on_button_release(self, widget=None, event=None):
118 if self._clear_overlay_source_id is not None:
119 gobject.source_remove(self._clear_overlay_source_id)
120 self.overlay = None
121 self.queue_draw()
122 self._clear_overlay_source_id = None
124 return False
126 def on_expose_event(self, widget, event):
127 cr = widget.window.cairo_create()
128 cr.set_operator(cairo.OPERATOR_SOURCE)
129 cr.rectangle(0, 0, self.image.get_width(),
130 self.image.get_height())
131 cr.set_source_rgba(0, 0, 0, 0)
132 cr.fill()
134 cr.rectangle(0, 0, self.image.get_width(),
135 self.image.get_height())
136 cr.set_source_surface(self.image)
137 cr.fill()
139 cr.set_operator(cairo.OPERATOR_OVER)
140 if self.DEBUG_RECTANGLES:
141 for rectangle in self.rectangles:
142 cr.set_source_rgba(1, 0, 1, .5)
143 cr.rectangle(rectangle.x1, rectangle.y1,
144 rectangle.x2-rectangle.x1,
145 rectangle.y2-rectangle.y1)
146 cr.fill()
148 if self.overlay is not None:
149 cr.set_operator(cairo.OPERATOR_OVER)
150 cr.rectangle(0, 0, self.overlay.get_width(),
151 self.overlay.get_height())
152 cr.set_source_surface(self.overlay)
153 cr.fill()
155 return True
157 hd_plugin_type = RaeMote
159 if __name__ == '__main__':
160 gobject.type_register(hd_plugin_type)
161 obj = gobject.new(hd_plugin_type, \
162 plugin_id=hd_plugin_type.__class__.__name__)
163 obj.show_all()
164 gtk.main()