├── lcdproc ├── __init__.py ├── server.py ├── screen.py └── widgets.py ├── .gitignore ├── setuptools-0.6c11-py2.6.egg ├── README.textile ├── setup.py ├── LICENSE ├── examples.py └── ez_setup.py /lcdproc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .pydevproject 3 | dist 4 | *.egg-info 5 | *.pyc 6 | -------------------------------------------------------------------------------- /setuptools-0.6c11-py2.6.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jinglemansweep/lcdproc/HEAD/setuptools-0.6c11-py2.6.egg -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h2. LCDproc 2 | 3 | h3. Installing 4 | 5 | h4. Python 2: 6 | 7 | bc. sudo apt-get install python-setuptools 8 | sudo easy_install lcdproc 9 | 10 | h4. Python 3: 11 | 12 | bc. sudo apt-get install python3-setuptools 13 | sudo easy_install3 lcdproc 14 | 15 | Alternatively, you could use pip to install the package instead of easy_install. 16 | 17 | h3. Example Usage 18 | 19 | See *examples.py* 20 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #import ez_setup, os 2 | #ez_setup.use_setuptools() 3 | import os, sys 4 | from setuptools import setup, find_packages 5 | 6 | extra = {} 7 | if sys.version_info >= (3,): 8 | extra['use_2to3'] = True 9 | 10 | setup( 11 | name = "lcdproc", 12 | version = "0.03", 13 | author = "JingleManSweep", 14 | author_email = "jinglemansweep@gmail.com", 15 | description = "Python OOP Wrapper Library for LCDproc Telnet API", 16 | url = "http://github.com/jingleman/lcdproc", 17 | packages = find_packages(), 18 | scripts = [], 19 | include_package_data = True, 20 | **extra 21 | ) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, JingleManSweep 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | import datetime 5 | 6 | from lcdproc.server import Server 7 | 8 | def main(): 9 | 10 | lcd = Server("media", debug=False) 11 | lcd.start_session() 12 | 13 | screen1 = lcd.add_screen("Screen1") 14 | screen1.set_heartbeat("off") 15 | screen1.set_duration(10) 16 | 17 | screen2 = lcd.add_screen("Screen2") 18 | screen2.set_heartbeat("off") 19 | screen2.set_duration(2) 20 | 21 | #string_widget = screen.add_string_widget("MyStringWidget", text="TestwWEJIowejioewjio", x=1, y=2) 22 | #scroller_widget = screen.add_scroller_widget("MyScrollerWidget", text="This Is A Test Message, Yeah, Yeah, Yeah", speed=2) 23 | #hbar_widget = screen.add_hbar_widget("MyHBarWidget", x=1, y=4, length=60) 24 | #frame_widget = screen.add_frame_widget("MyFrameWidget") 25 | 26 | num1_widget = screen1.add_number_widget("MyNumber1Widget", x=1, value=0) 27 | num2_widget = screen1.add_number_widget("MyNumber2Widget", x=5, value=0) 28 | num3_widget = screen1.add_number_widget("MyNumber3Widget", x=9, value=0) 29 | num4_widget = screen1.add_number_widget("MyNumber4Widget", x=13, value=0) 30 | 31 | time.sleep(2) 32 | 33 | progress = 0 34 | 35 | while True: 36 | 37 | num1_widget.set_value(progress) 38 | num2_widget.set_value(progress) 39 | num3_widget.set_value(progress) 40 | num4_widget.set_value(progress) 41 | 42 | time.sleep(0.5) 43 | 44 | progress = progress + 1 45 | if progress > 9: progress = 0 46 | 47 | # Run 48 | 49 | if __name__ == "__main__": 50 | main() -------------------------------------------------------------------------------- /lcdproc/server.py: -------------------------------------------------------------------------------- 1 | import telnetlib 2 | import urllib 3 | import select 4 | 5 | from screen import Screen 6 | 7 | 8 | class Server(object): 9 | 10 | """ LCDproc Server Object """ 11 | 12 | def __init__(self, hostname="localhost", port=13666, debug=False): 13 | 14 | """ Constructor """ 15 | 16 | self.debug = debug 17 | self.hostname = hostname 18 | self.port = port 19 | self.tn = telnetlib.Telnet(self.hostname, self.port) 20 | self.server_info = dict() 21 | self.screens = dict() 22 | self.keys = list() 23 | 24 | def start_session(self): 25 | 26 | """ Start Session """ 27 | 28 | response = self.request("hello") 29 | bits = response.split(" ") 30 | self.server_info.update({ 31 | "server_version": bits[2], 32 | "protocol_version": bits[4], 33 | "screen_width": int(bits[7]), 34 | "screen_height": int(bits[9]), 35 | "cell_width": int(bits[11]), 36 | "cell_height": int(bits[13]) 37 | }) 38 | return response 39 | 40 | 41 | def request(self, command_string): 42 | 43 | """ Request """ 44 | 45 | self.tn.write((command_string + "\n").encode()) 46 | if self.debug: print "Telnet Request: %s" % (command_string) 47 | while True: 48 | response = urllib.unquote(self.tn.read_until(b"\n").decode()) 49 | if "success" in response: # Normal successful reply 50 | break 51 | if "huh" in response: # Something went wrong 52 | break 53 | if "connect" in response: # Special reply to "hello" 54 | break 55 | # TODO Keep track of which screen is displayed 56 | # Try again if response was key, menu or visibility notification. 57 | if "huh" in response or self.debug: print "Telnet Response: %s" % (response[:-1]) 58 | return response 59 | 60 | 61 | def poll(self): 62 | """ 63 | Poll 64 | 65 | Check for a non-response string generated by LCDd and return any string read. 66 | LCDd generates strings for key presses, menu events & screen visibility changes. 67 | """ 68 | if select.select([self.tn], [], [], 0) == ([self.tn], [], []): 69 | response = urllib.unquote(self.tn.read_until(b"\n").decode()) 70 | if self.debug: print "Telnet Poll: %s" % (response[:-1]) 71 | # TODO Keep track of which screen is displayed 72 | return response 73 | else: 74 | return None 75 | 76 | 77 | def add_screen(self, ref): 78 | 79 | """ Add Screen """ 80 | 81 | if ref not in self.screens: 82 | screen = Screen(self, ref) 83 | screen.clear() # TODO Check this is needed, new screens should be clear. 84 | self.screens[ref] = screen 85 | return self.screens[ref] 86 | 87 | 88 | def del_screen(self, ref): 89 | """ Delete/Remove Screen """ 90 | self.request("screen_del %s" % (ref)) 91 | del(self.screens[ref]) 92 | 93 | 94 | def add_key(self, ref, mode = "shared"): 95 | """ 96 | Add a key. 97 | 98 | (ref) 99 | Return key name or None on error 100 | """ 101 | if ref not in self.keys: 102 | response = self.request("client_add_key %s -%s" % (ref, mode)) 103 | if "success" not in response: return None 104 | self.keys.append(ref) 105 | return ref 106 | 107 | 108 | def del_key(self, ref): 109 | """ 110 | Delete a key. 111 | 112 | (ref) 113 | Return None or LCDd response on error 114 | """ 115 | if ref not in self.keys: 116 | response = self.request("client_del_key %s" % (ref)) 117 | self.keys.remove(ref) 118 | if "success" in response: 119 | return None 120 | else: 121 | return response 122 | 123 | 124 | def output(self, value): 125 | """ 126 | Sets the client's output (on, off, int) 127 | 128 | Sets the general purpose output on some display modules to this value. 129 | Use on to set all outputs to high state, and off to set all to low state. 130 | The meaning of the integer value depends on your specific device, usually 131 | it is a bit pattern describing the state of each output line. 132 | 133 | Return None or LCDd response on error 134 | """ 135 | response = self.request(("output %s" % (value)).encode()) 136 | if "success" in response: 137 | return None 138 | else: 139 | return response 140 | 141 | def get_server_info(self): 142 | """ 143 | Returns information about the server and the connected 144 | LCD as a dictionary with the following keys: 145 | 146 | "server_version", "protocol_version", 147 | "screen_width", "screen_height", 148 | "cell_width", "cell_height" 149 | """ 150 | return self.server_info 151 | -------------------------------------------------------------------------------- /lcdproc/screen.py: -------------------------------------------------------------------------------- 1 | from widgets import StringWidget, TitleWidget, HBarWidget, VBarWidget, IconWidget, ScrollerWidget, FrameWidget,NumberWidget 2 | 3 | 4 | class Screen(object): 5 | 6 | """ LCDproc Screen Object """ 7 | 8 | def __init__(self, server, ref): 9 | 10 | """ Constructor """ 11 | 12 | self.server = server 13 | self.ref = ref 14 | self.name = ref 15 | self.width = None 16 | self.height = None 17 | self.priority = None 18 | self.heartbeat = None 19 | self.backlight = None 20 | self.duration = None 21 | self.timeout = None 22 | self.cursor = None 23 | self.cursor_x = None 24 | self.cursor_y = None 25 | self.widgets = dict() 26 | 27 | self.server.request("screen_add %s" % (ref)) 28 | self.set_cursor("off") 29 | 30 | 31 | def set_name(self, name): 32 | 33 | """ Set Screen Name """ 34 | 35 | self.name = name 36 | self.server.request("screen_set %s name %s" % (self.ref, self.name)) 37 | 38 | 39 | def set_width(self, width): 40 | 41 | """ Set Screen Width """ 42 | 43 | if width > 0 and width <= self.server.server_info.get("screen_width"): 44 | self.width = width 45 | self.server.request("screen_set %s wid %i" % (self.ref, self.width)) 46 | 47 | 48 | def set_height(self, height): 49 | 50 | """ Set Screen Height """ 51 | 52 | if height > 0 and height <= self.server.server_info.get("screen_height"): 53 | self.height = height 54 | self.server.request("screen_set %s hgt %i" % (self.ref, self.height)) 55 | 56 | 57 | def set_cursor_x(self, x): 58 | 59 | """ Set Screen Cursor X Position """ 60 | 61 | if x >= 0 and x <= self.server.server_info.get("screen_width"): 62 | self.cursor_x = x 63 | self.server.request("screen_set %s cursor_x %i" % (self.ref, self.cursor_x)) 64 | 65 | 66 | def set_cursor_y(self, y): 67 | 68 | """ Set Screen Cursor Y Position """ 69 | 70 | if y >= 0 and y <= self.server.server_info.get("screen_height"): 71 | self.cursor_y = y 72 | self.server.request("screen_set %s cursor_y %i" % (self.ref, self.cursor_y)) 73 | 74 | 75 | def set_duration(self, duration): 76 | 77 | """ Set Screen Change Interval Duration """ 78 | 79 | if duration > 0: 80 | self.duration = duration 81 | self.server.request("screen_set %s duration %i" % (self.ref, (self.duration * 8))) 82 | 83 | 84 | def set_timeout(self, timeout): 85 | 86 | """ Set Screen Timeout Duration """ 87 | 88 | if timeout > 0: 89 | self.timeout = timeout 90 | self.server.request("screen_set %s timeout %i" % (self.ref, (self.timeout * 8))) 91 | 92 | 93 | def set_priority(self, priority): 94 | 95 | """ Set Screen Priority Class """ 96 | 97 | if priority in ["hidden", "background", "info", "foreground", "alert", "input"]: 98 | self.priority = priority 99 | self.server.request("screen_set %s priority %s" % (self.ref, self.priority)) 100 | 101 | 102 | def set_backlight(self, state): 103 | 104 | """ Set Screen Backlight Mode """ 105 | 106 | if state in ["on", "off", "toggle", "open", "blink", "flash"]: 107 | self.backlight = state 108 | self.server.request("screen_set %s backlight %s" % (self.ref, self.backlight)) 109 | 110 | 111 | def set_heartbeat(self, state): 112 | 113 | """ Set Screen Heartbeat Display Mode """ 114 | 115 | if state in ["on", "off", "open"]: 116 | self.heartbeat = state 117 | self.server.request("screen_set %s heartbeat %s" % (self.ref, self.heartbeat)) 118 | 119 | 120 | def set_cursor(self, cursor): 121 | 122 | """ Set Screen Cursor Mode """ 123 | 124 | if cursor in ["on", "off", "under", "block"]: 125 | self.cursor = cursor 126 | self.server.request("screen_set %s cursor %s" % (self.ref, self.cursor)) 127 | 128 | 129 | def clear(self): 130 | 131 | """ Clear Screen """ 132 | 133 | w1 = StringWidget(self, ref="_w1_", text=" "*20, x=1, y=1) 134 | w2 = StringWidget(self, ref="_w2_", text=" "*20, x=1, y=2) 135 | w3 = StringWidget(self, ref="_w3_", text=" "*20, x=1, y=3) 136 | w4 = StringWidget(self, ref="_w4_", text=" "*20, x=1, y=4) 137 | 138 | 139 | def add_string_widget(self, ref, text="Text", x=1, y=1): 140 | 141 | """ Add String Widget """ 142 | 143 | if ref not in self.widgets: 144 | widget = StringWidget(screen=self, ref=ref, text=text, x=x, y=y) 145 | self.widgets[ref] = widget 146 | return self.widgets[ref] 147 | 148 | 149 | def add_title_widget(self, ref, text="Title"): 150 | 151 | """ Add Title Widget """ 152 | 153 | if ref not in self.widgets: 154 | widget = TitleWidget(screen=self, ref=ref, text=text) 155 | self.widgets[ref] = widget 156 | return self.widgets[ref] 157 | 158 | 159 | def add_hbar_widget(self, ref, x=1, y=1, length=10): 160 | 161 | """ Add Horizontal Bar Widget """ 162 | 163 | if ref not in self.widgets: 164 | widget = HBarWidget(screen=self, ref=ref, x=x, y=y, length=length) 165 | self.widgets[ref] = widget 166 | return self.widgets[ref] 167 | 168 | 169 | def add_vbar_widget(self, ref, x=1, y=1, length=10): 170 | 171 | """ Add Vertical Bar Widget """ 172 | 173 | if ref not in self.widgets: 174 | widget = VBarWidget(screen=self, ref=ref, x=x, y=y, length=length) 175 | self.widgets[ref] = widget 176 | return self.widgets[ref] 177 | 178 | 179 | def add_icon_widget(self, ref, x=1, y=1, name="heart"): 180 | 181 | """ Add Icon Widget """ 182 | 183 | if ref not in self.widgets: 184 | widget = IconWidget(screen=self, ref=ref, x=x, y=y, name=name) 185 | self.widgets[ref] = widget 186 | return self.widgets[ref] 187 | 188 | 189 | def add_scroller_widget(self, ref, left=1, top=1, right=20, bottom=1, direction="h", speed=1, text="Message"): 190 | 191 | """ Add Scroller Widget """ 192 | 193 | if ref not in self.widgets: 194 | widget = ScrollerWidget(screen=self, ref=ref, left=left, top=top, right=right, bottom=bottom, direction=direction, speed=speed, text=text) 195 | self.widgets[ref] = widget 196 | return self.widgets[ref] 197 | 198 | 199 | def add_frame_widget(self, ref, left=1, top=1, right=20, bottom=1, width=20, height=4, direction="h", speed=1): 200 | 201 | """ Add Frame Widget """ 202 | 203 | if ref not in self.widgets: 204 | widget = FrameWidget(screen=self, ref=ref, left=left, top=top, right=right, bottom=bottom, width=width, height=height, direction=direction, speed=speed) 205 | self.widgets[ref] = widget 206 | return self.widgets[ref] 207 | 208 | 209 | def add_number_widget(self, ref, x=1, value=1): 210 | 211 | """ Add Number Widget """ 212 | 213 | if ref not in self.widgets: 214 | widget = NumberWidget(screen=self, ref=ref, x=x, value=value) 215 | self.widgets[ref] = widget 216 | return self.widgets[ref] 217 | 218 | 219 | 220 | def del_widget(self, ref): 221 | """ Delete/Remove A Widget """ 222 | self.server.request("widget_del %s %s" % (self.name, ref)) 223 | del(self.widgets[ref]) 224 | -------------------------------------------------------------------------------- /lcdproc/widgets.py: -------------------------------------------------------------------------------- 1 | import urllib 2 | 3 | class StringWidget(object): 4 | 5 | """ String Widget """ 6 | 7 | def __init__(self, screen, ref, x, y, text): 8 | 9 | self.screen = screen 10 | self.ref = ref 11 | self.x = x 12 | self.y = y 13 | self.text = text 14 | 15 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, self.ref, "string")) 16 | self.update() 17 | 18 | 19 | def update(self): 20 | 21 | self.screen.server.request('widget_set %s %s %s %s "%s"' % (self.screen.ref, self.ref, self.x, self.y, self.text)) 22 | 23 | 24 | def set_x(self, x): 25 | 26 | self.x = x 27 | self.update() 28 | 29 | 30 | def set_y(self, y): 31 | 32 | self.y = y 33 | self.update() 34 | 35 | 36 | def set_text(self, text): 37 | 38 | self.text = text 39 | self.update() 40 | 41 | 42 | class TitleWidget(object): 43 | 44 | """ Title Widget """ 45 | 46 | def __init__(self, screen, ref, text): 47 | 48 | self.screen = screen 49 | self.ref = ref 50 | self.text = text 51 | 52 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, self.ref, "title")) 53 | self.update() 54 | 55 | def update(self): 56 | 57 | self.screen.server.request('widget_set %s %s "%s"' % (self.screen.ref, self.ref, self.text)) 58 | 59 | def set_text(self, text): 60 | 61 | self.text = text 62 | self.update() 63 | 64 | 65 | class HBarWidget(object): 66 | 67 | def __init__(self, screen, ref, x, y, length): 68 | 69 | self.screen = screen 70 | self.ref = ref 71 | self.x = x 72 | self.y = y 73 | self.length = length 74 | 75 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, self.ref, "hbar")) 76 | self.update() 77 | 78 | def update(self): 79 | 80 | self.screen.server.request("widget_set %s %s %s %s %s" % (self.screen.ref, self.ref, self.x, self.y, self.length)) 81 | 82 | def set_x(self, x): 83 | 84 | self.x = x 85 | self.update() 86 | 87 | def set_y(self, y): 88 | 89 | self.y = y 90 | self.update() 91 | 92 | def set_length(self, length): 93 | 94 | self.length = length 95 | self.update() 96 | 97 | 98 | class VBarWidget(object): 99 | 100 | def __init__(self, screen, ref, x, y, length): 101 | 102 | self.screen = screen 103 | self.ref = ref 104 | self.x = x 105 | self.y = y 106 | self.length = length 107 | 108 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, self.ref, "vbar")) 109 | self.update() 110 | 111 | def update(self): 112 | 113 | self.screen.server.request("widget_set %s %s %s %s %s" % (self.screen.ref, self.ref, self.x, self.y, self.length)) 114 | 115 | def set_x(self, x): 116 | 117 | self.x = x 118 | self.update() 119 | 120 | def set_y(self, y): 121 | 122 | self.y = y 123 | self.update() 124 | 125 | def set_length(self, length): 126 | 127 | self.length = length 128 | self.update() 129 | 130 | 131 | class IconWidget(object): 132 | 133 | def __init__(self, screen, ref, x, y, name): 134 | 135 | self.screen = screen 136 | self.ref = ref 137 | self.x = x 138 | self.y = y 139 | self.name = name 140 | 141 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, self.ref, "icon")) 142 | self.update() 143 | 144 | def update(self): 145 | 146 | self.screen.server.request("widget_set %s %s %s %s %s" % (self.screen.ref, self.ref, self.x, self.y, self.name)) 147 | 148 | def set_x(self, x): 149 | 150 | self.x = x 151 | self.update() 152 | 153 | def set_y(self, y): 154 | 155 | self.y = y 156 | self.update() 157 | 158 | def set_name(self, name): 159 | 160 | self.name = name 161 | self.update() 162 | 163 | class ScrollerWidget(object): 164 | 165 | def __init__(self, screen, ref, left, top, right, bottom, direction, speed, text): 166 | 167 | self.screen = screen 168 | self.ref = ref 169 | self.left = left 170 | self.top = top 171 | self.right = right 172 | self.bottom = bottom 173 | self.direction = direction 174 | self.speed = speed 175 | self.text = text 176 | 177 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, 178 | self.ref, 179 | "scroller")) 180 | self.update() 181 | 182 | def update(self): 183 | 184 | self.screen.server.request('widget_set %s %s %s %s %s %s %s %s "%s"' % (self.screen.ref, 185 | self.ref, 186 | self.left, 187 | self.top, 188 | self.right, 189 | self.bottom, 190 | self.direction, 191 | self.speed, 192 | self.text)) 193 | 194 | def set_left(self, left): 195 | 196 | self.left = left 197 | self.update() 198 | 199 | def set_top(self, top): 200 | 201 | self.top = top 202 | self.update() 203 | 204 | def set_right(self, right): 205 | 206 | self.right = right 207 | self.update() 208 | 209 | def set_bottom(self, bottom): 210 | 211 | self.bottom = bottom 212 | self.update() 213 | 214 | def set_direction(self, direction): 215 | 216 | self.direction = direction 217 | self.update() 218 | 219 | def set_speed(self, speed): 220 | 221 | self.speed = speed 222 | self.update() 223 | 224 | def set_text(self, text): 225 | 226 | self.text = text 227 | self.update() 228 | 229 | 230 | class FrameWidget(object): 231 | 232 | def __init__(self, screen, ref, left, top, right, bottom, width, height, direction, speed): 233 | 234 | self.screen = screen 235 | self.ref = ref 236 | self.left = left 237 | self.top = top 238 | self.right = right 239 | self.bottom = bottom 240 | self.width = width 241 | self.height = height 242 | self.direction = direction 243 | self.speed = speed 244 | 245 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, 246 | self.ref, 247 | "frame")) 248 | self.update() 249 | 250 | def update(self): 251 | 252 | self.screen.server.request('widget_set %s %s %s %s %s %s %s %s %s %s' % (self.screen.ref, 253 | self.ref, 254 | self.left, 255 | self.top, 256 | self.right, 257 | self.bottom, 258 | self.width, 259 | self.height, 260 | self.direction, 261 | self.speed)) 262 | 263 | def set_left(self, left): 264 | 265 | self.left = left 266 | self.update() 267 | 268 | def set_top(self, top): 269 | 270 | self.top = top 271 | self.update() 272 | 273 | def set_right(self, right): 274 | 275 | self.right = right 276 | self.update() 277 | 278 | def set_bottom(self, bottom): 279 | 280 | self.bottom = bottom 281 | self.update() 282 | 283 | def set_width(self, width): 284 | 285 | self.width = width 286 | self.update() 287 | 288 | def set_height(self, height): 289 | 290 | self.height = height 291 | self.update() 292 | 293 | def set_direction(self, direction): 294 | 295 | self.direction = direction 296 | self.update() 297 | 298 | def set_speed(self, speed): 299 | 300 | self.speed = speed 301 | self.update() 302 | 303 | 304 | class NumberWidget(object): 305 | 306 | def __init__(self, screen, ref, x, value): 307 | 308 | self.screen = screen 309 | self.ref = ref 310 | self.x = x 311 | self.value = value 312 | 313 | self.screen.server.request("widget_add %s %s %s" % (self.screen.ref, 314 | self.ref, 315 | "num")) 316 | self.update() 317 | 318 | def update(self): 319 | 320 | self.screen.server.request('widget_set %s %s %s %s' % (self.screen.ref, 321 | self.ref, 322 | self.x, 323 | self.value)) 324 | 325 | def set_x(self, x): 326 | 327 | self.x = x 328 | self.update() 329 | 330 | def set_value(self, value): 331 | 332 | self.value = value 333 | self.update() -------------------------------------------------------------------------------- /ez_setup.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """Bootstrap setuptools installation 3 | 4 | If you want to use setuptools in your package's setup.py, just include this 5 | file in the same directory with it, and add this to the top of your setup.py:: 6 | 7 | from ez_setup import use_setuptools 8 | use_setuptools() 9 | 10 | If you want to require a specific version of setuptools, set a download 11 | mirror, or use an alternate download directory, you can do so by supplying 12 | the appropriate options to ``use_setuptools()``. 13 | 14 | This file can also be run as a script to install or upgrade setuptools. 15 | """ 16 | import sys 17 | DEFAULT_VERSION = "0.6c11" 18 | DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] 19 | 20 | md5_data = { 21 | 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 22 | 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 23 | 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 24 | 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 25 | 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 26 | 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 27 | 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 28 | 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 29 | 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 30 | 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 31 | 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', 32 | 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', 33 | 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', 34 | 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', 35 | 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', 36 | 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', 37 | 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', 38 | 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 39 | 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 40 | 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 41 | 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 42 | 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 43 | 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 44 | 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 45 | 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 46 | 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 47 | 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 48 | 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 49 | 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 50 | 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', 51 | 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', 52 | 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', 53 | 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', 54 | 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', 55 | 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', 56 | 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 57 | 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 58 | 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 59 | 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 60 | 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 61 | 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 62 | 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', 63 | } 64 | 65 | import sys, os 66 | try: from hashlib import md5 67 | except ImportError: from md5 import md5 68 | 69 | def _validate_md5(egg_name, data): 70 | if egg_name in md5_data: 71 | digest = md5(data).hexdigest() 72 | if digest != md5_data[egg_name]: 73 | print >>sys.stderr, ( 74 | "md5 validation of %s failed! (Possible download problem?)" 75 | % egg_name 76 | ) 77 | sys.exit(2) 78 | return data 79 | 80 | def use_setuptools( 81 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 82 | download_delay=15 83 | ): 84 | """Automatically find/download setuptools and make it available on sys.path 85 | 86 | `version` should be a valid setuptools version number that is available 87 | as an egg for download under the `download_base` URL (which should end with 88 | a '/'). `to_dir` is the directory where setuptools will be downloaded, if 89 | it is not already available. If `download_delay` is specified, it should 90 | be the number of seconds that will be paused before initiating a download, 91 | should one be required. If an older version of setuptools is installed, 92 | this routine will print a message to ``sys.stderr`` and raise SystemExit in 93 | an attempt to abort the calling script. 94 | """ 95 | was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules 96 | def do_download(): 97 | egg = download_setuptools(version, download_base, to_dir, download_delay) 98 | sys.path.insert(0, egg) 99 | import setuptools; setuptools.bootstrap_install_from = egg 100 | try: 101 | import pkg_resources 102 | except ImportError: 103 | return do_download() 104 | try: 105 | pkg_resources.require("setuptools>="+version); return 106 | except pkg_resources.VersionConflict, e: 107 | if was_imported: 108 | print >>sys.stderr, ( 109 | "The required version of setuptools (>=%s) is not available, and\n" 110 | "can't be installed while this script is running. Please install\n" 111 | " a more recent version first, using 'easy_install -U setuptools'." 112 | "\n\n(Currently using %r)" 113 | ) % (version, e.args[0]) 114 | sys.exit(2) 115 | else: 116 | del pkg_resources, sys.modules['pkg_resources'] # reload ok 117 | return do_download() 118 | except pkg_resources.DistributionNotFound: 119 | return do_download() 120 | 121 | def download_setuptools( 122 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 123 | delay = 15 124 | ): 125 | """Download setuptools from a specified location and return its filename 126 | 127 | `version` should be a valid setuptools version number that is available 128 | as an egg for download under the `download_base` URL (which should end 129 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 130 | `delay` is the number of seconds to pause before an actual download attempt. 131 | """ 132 | import urllib2, shutil 133 | egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) 134 | url = download_base + egg_name 135 | saveto = os.path.join(to_dir, egg_name) 136 | src = dst = None 137 | if not os.path.exists(saveto): # Avoid repeated downloads 138 | try: 139 | from distutils import log 140 | if delay: 141 | log.warn(""" 142 | --------------------------------------------------------------------------- 143 | This script requires setuptools version %s to run (even to display 144 | help). I will attempt to download it for you (from 145 | %s), but 146 | you may need to enable firewall access for this script first. 147 | I will start the download in %d seconds. 148 | 149 | (Note: if this machine does not have network access, please obtain the file 150 | 151 | %s 152 | 153 | and place it in this directory before rerunning this script.) 154 | ---------------------------------------------------------------------------""", 155 | version, download_base, delay, url 156 | ); from time import sleep; sleep(delay) 157 | log.warn("Downloading %s", url) 158 | src = urllib2.urlopen(url) 159 | # Read/write all in one block, so we don't create a corrupt file 160 | # if the download is interrupted. 161 | data = _validate_md5(egg_name, src.read()) 162 | dst = open(saveto,"wb"); dst.write(data) 163 | finally: 164 | if src: src.close() 165 | if dst: dst.close() 166 | return os.path.realpath(saveto) 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | def main(argv, version=DEFAULT_VERSION): 204 | """Install or upgrade setuptools and EasyInstall""" 205 | try: 206 | import setuptools 207 | except ImportError: 208 | egg = None 209 | try: 210 | egg = download_setuptools(version, delay=0) 211 | sys.path.insert(0,egg) 212 | from setuptools.command.easy_install import main 213 | return main(list(argv)+[egg]) # we're done here 214 | finally: 215 | if egg and os.path.exists(egg): 216 | os.unlink(egg) 217 | else: 218 | if setuptools.__version__ == '0.0.1': 219 | print >>sys.stderr, ( 220 | "You have an obsolete version of setuptools installed. Please\n" 221 | "remove it from your system entirely before rerunning this script." 222 | ) 223 | sys.exit(2) 224 | 225 | req = "setuptools>="+version 226 | import pkg_resources 227 | try: 228 | pkg_resources.require(req) 229 | except pkg_resources.VersionConflict: 230 | try: 231 | from setuptools.command.easy_install import main 232 | except ImportError: 233 | from easy_install import main 234 | main(list(argv)+[download_setuptools(delay=0)]) 235 | sys.exit(0) # try to force an exit 236 | else: 237 | if argv: 238 | from setuptools.command.easy_install import main 239 | main(argv) 240 | else: 241 | print "Setuptools version",version,"or greater has been installed." 242 | print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' 243 | 244 | def update_md5(filenames): 245 | """Update our built-in md5 registry""" 246 | 247 | import re 248 | 249 | for name in filenames: 250 | base = os.path.basename(name) 251 | f = open(name,'rb') 252 | md5_data[base] = md5(f.read()).hexdigest() 253 | f.close() 254 | 255 | data = [" %r: %r,\n" % it for it in md5_data.items()] 256 | data.sort() 257 | repl = "".join(data) 258 | 259 | import inspect 260 | srcfile = inspect.getsourcefile(sys.modules[__name__]) 261 | f = open(srcfile, 'rb'); src = f.read(); f.close() 262 | 263 | match = re.search("\nmd5_data = {\n([^}]+)}", src) 264 | if not match: 265 | print >>sys.stderr, "Internal error!" 266 | sys.exit(2) 267 | 268 | src = src[:match.start(1)] + repl + src[match.end(1):] 269 | f = open(srcfile,'w') 270 | f.write(src) 271 | f.close() 272 | 273 | 274 | if __name__=='__main__': 275 | if len(sys.argv)>2 and sys.argv[1]=='--md5update': 276 | update_md5(sys.argv[2:]) 277 | else: 278 | main(sys.argv[1:]) 279 | 280 | 281 | 282 | 283 | 284 | 285 | --------------------------------------------------------------------------------