|
|
1.1 ! root 1: # -*- mode: python; tab-width: 4 -*- ! 2: # ! 3: # Micropolis, Unix Version. This game was released for the Unix platform ! 4: # in or about 1990 and has been modified for inclusion in the One Laptop ! 5: # Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If ! 6: # you need assistance with this program, you may contact: ! 7: # http://wiki.laptop.org/go/Micropolis or email [email protected]. ! 8: # ! 9: # This program is free software: you can redistribute it and/or modify ! 10: # it under the terms of the GNU General Public License as published by ! 11: # the Free Software Foundation, either version 3 of the License, or (at ! 12: # your option) any later version. ! 13: # ! 14: # This program is distributed in the hope that it will be useful, but ! 15: # WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 17: # General Public License for more details. You should have received a ! 18: # copy of the GNU General Public License along with this program. If ! 19: # not, see <http://www.gnu.org/licenses/>. ! 20: # ! 21: # ADDITIONAL TERMS per GNU GPL Section 7 ! 22: # ! 23: # No trademark or publicity rights are granted. This license does NOT ! 24: # give you any right, title or interest in the trademark SimCity or any ! 25: # other Electronic Arts trademark. You may not distribute any ! 26: # modification of this program using the trademark SimCity or claim any ! 27: # affliation or association with Electronic Arts Inc. or its employees. ! 28: # ! 29: # Any propagation or conveyance of this program must include this ! 30: # copyright notice and these terms. ! 31: # ! 32: # If you convey this program (or any modifications of it) and assume ! 33: # contractual liability for the program to recipients of it, you agree ! 34: # to indemnify Electronic Arts for any liability that those contractual ! 35: # assumptions impose on Electronic Arts. ! 36: # ! 37: # You may not misrepresent the origins of this program; modified ! 38: # versions of the program must be marked as such and not identified as ! 39: # the original program. ! 40: # ! 41: # This disclaimer supplements the one included in the General Public ! 42: # License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS ! 43: # PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY ! 44: # OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF ! 45: # SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS ! 46: # DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES, ! 47: # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, ! 48: # FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY ! 49: # RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING, ! 50: # USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST ! 51: # INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL ! 52: # MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE ! 53: # UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE ! 54: # WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE ! 55: # CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR ! 56: # ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME ! 57: # JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED ! 58: # WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A ! 59: # CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY ! 60: # NOT APPLY TO YOU. ! 61: ! 62: import gtk ! 63: import os ! 64: import signal ! 65: import tempfile ! 66: import logging ! 67: import sys ! 68: import time ! 69: import subprocess ! 70: import thread ! 71: import fcntl ! 72: ! 73: from sugar.activity import activity ! 74: from sugar.activity.activity import get_bundle_path ! 75: from sugar import profile ! 76: from gettext import gettext as _ ! 77: from glob import glob ! 78: ! 79: try: ! 80: import pygame.mixer ! 81: pygame.mixer.init() ! 82: except: pass ! 83: ! 84: try: ! 85: from sugar.presence import presenceservice ! 86: except ImportError: ! 87: from sugar.presence import PresenceService as presenceservice ! 88: ! 89: ! 90: def QuoteTCL(s): ! 91: return s.replace('"', '\\"') ! 92: ! 93: ! 94: class MicropolisActivity(activity.Activity): ! 95: ! 96: def __init__(self, handle): ! 97: ! 98: activity.Activity.__init__(self, handle) ! 99: ! 100: self.set_title(_('Micropolis Activity')) ! 101: self.connect('destroy', self._destroy_cb) ! 102: self.connect('focus-in-event', self._focus_in_cb) ! 103: self.connect('focus-out-event', self._focus_out_cb) ! 104: ! 105: signal.signal(signal.SIGCHLD, self._sigchild_handler) ! 106: ! 107: self._bundle_path = get_bundle_path() ! 108: ! 109: if False: ! 110: # FIXME: Plug Micropolis's window into a gtk socket. ! 111: # Doesn't work yet, but it would be cool if it did. ! 112: socket = gtk.Socket() ! 113: try: ! 114: self.set_canvas(socket) ! 115: except AttributeError: ! 116: self.add(socket) ! 117: socket.show() ! 118: socket.connect('plug-added', self._plug_added_cb) ! 119: socket.connect('plug-removed', self._plug_removed_cb) ! 120: ! 121: win = socket.get_id() ! 122: ! 123: command = os.path.join( ! 124: self._bundle_path, ! 125: 'Micropolis') ! 126: ! 127: args = [ ! 128: command, ! 129: #'-R', str(win), # Set root window to socket window id ! 130: '-t', # Interactive tty mode, so we can send it commands. ! 131: ] ! 132: ! 133: logging.debug("CWD: " + self._bundle_path) ! 134: logging.debug("Micropolis ARGS: " + repr(args)) ! 135: ! 136: self._process = subprocess.Popen( ! 137: args, ! 138: stdin=subprocess.PIPE, ! 139: stdout=subprocess.PIPE, ! 140: close_fds=True, ! 141: cwd=self._bundle_path, ! 142: preexec_fn=lambda: os.chdir(self._bundle_path)) ! 143: ! 144: logging.debug("STARTING THREAD... " + str(self._stdout_thread_function)) ! 145: t = None ! 146: try: ! 147: t = thread.start_new( ! 148: self._stdout_thread_function, ! 149: ()) ! 150: except Exception, e: ! 151: logging.debug("EXCEPTION " + str(e)) ! 152: self._stdout_thread = t ! 153: logging.debug("STARTED THREAD. " + str(t)) ! 154: ! 155: uri = handle.uri or '' ! 156: logging.debug("Micropolis SUGARSTARTUP URI " + repr(uri)) ! 157: self.send_process( ! 158: 'SugarStartUp "' + QuoteTCL(uri) + '"\n') ! 159: ! 160: nick = profile.get_nick_name() or '' ! 161: logging.debug("Micropolis SUGARNICKNAME NICK " + repr(nick)) ! 162: self.send_process( ! 163: 'SugarNickName "' + QuoteTCL(nick) + '"\n') ! 164: ! 165: #logging.debug("started Micropolis, pid " + repr(self._pid)) ! 166: ! 167: ps = presenceservice.get_instance() ! 168: ! 169: for buddy in ps.get_buddies(): ! 170: self._buddy_appeared_cb(ps, buddy) ! 171: ! 172: ps.connect("buddy-appeared", self._buddy_appeared_cb) ! 173: ps.connect("buddy-disappeared", self._buddy_disappeared_cb) ! 174: ! 175: ! 176: def _stdout_thread_function(self, *args, **keys): ! 177: logging.debug("_stdout_thread_function BEGIN " + repr(args) + " " + repr(keys)) ! 178: f = self._process.stdout ! 179: fcntl.fcntl(f.fileno(), fcntl.F_SETFD, 0) ! 180: while True: ! 181: line = 'XXX' ! 182: try: ! 183: line = f.readline() ! 184: except Exception, e: ! 185: logging.debug("READLINE EXCEPTION " + str(e)) ! 186: break ! 187: logging.debug("LINE: " + repr(line)) ! 188: line = line.strip() ! 189: if not line: ! 190: continue ! 191: words = line.strip().split(' ') ! 192: command = words[0] ! 193: if command == 'PlaySound': ! 194: logging.debug("PLAYSOUND " + " ".join(words[1:])) ! 195: self.play_sound(words[1]) ! 196: else: ! 197: pass # logging.debug(">>> " + line) ! 198: logging.debug("_stdout_thread_function END") ! 199: ! 200: ! 201: def play_sound(self, name): ! 202: fileName = os.path.join( ! 203: self._bundle_path, ! 204: 'res/sounds', ! 205: name.lower() + '.wav') ! 206: print "PLAY_SOUND " + fileName ! 207: try: ! 208: sound = pygame.mixer.Sound(fileName) ! 209: sound.play() ! 210: except Exception, e: ! 211: print "Can't play sound: " + fileName + " " + str(e) ! 212: pass ! 213: ! 214: ! 215: def send_process(self, message): ! 216: logging.debug("SEND_PROCESS " + message) ! 217: self._process.stdin.write(message) ! 218: ! 219: ! 220: def share(self): ! 221: logging.debug("SHARE") ! 222: Activity.share(self) ! 223: self.send_process( ! 224: 'SugarShare\n') ! 225: ! 226: ! 227: def quit_process(self): ! 228: logging.debug("QUIT_PROCESS") ! 229: self.send_process( ! 230: 'SugarQuit\n') ! 231: time.sleep(10) ! 232: ! 233: ! 234: def _plug_added_cb(self, sock): ! 235: logging.debug("Micropolis window opened") ! 236: return False ! 237: ! 238: ! 239: def _plug_removed_cb(self, sock): ! 240: logging.debug("Micropolis window closed") ! 241: self.destroy() ! 242: return False ! 243: ! 244: ! 245: def _destroy_cb(self, window): ! 246: logging.debug("Micropolis activity destroyed %r" % window) ! 247: self.quit_process() ! 248: ! 249: ! 250: def _focus_in_cb(self, window, event): ! 251: logging.debug("Micropolis activated %r %r" % (window, event)) ! 252: self.send_process( ! 253: 'SugarActivate\n') ! 254: ! 255: ! 256: def _focus_out_cb(self, window, event): ! 257: logging.debug("Micropolis deactivated %r %r" % (window, event)) ! 258: self.send_process( ! 259: 'SugarDeactivate\n') ! 260: ! 261: ! 262: def _buddy_appeared_cb(self, ps, buddy): ! 263: ! 264: try: ! 265: key = buddy.props.key or '' ! 266: nick = buddy.props.nick or '' ! 267: color = buddy.props.color or '' ! 268: address = buddy.props.ip4_address or '' ! 269: except AttributeError: ! 270: key = buddy.get_name() or '' ! 271: nick = buddy.get_name() or '' ! 272: color = buddy.get_color() or '' ! 273: address = buddy.get_ip4_address() or '' ! 274: ! 275: logging.debug("Micropolis _BUDDY_APPEARED_CB KEY " + repr(key) + " NICK " + repr(nick) + " COLOR " + repr(color) + " ADDRESS " + repr(address)) ! 276: ! 277: logging.debug("Buddy appeared " + repr(buddy.props.nick)) ! 278: ! 279: self.send_process( ! 280: 'SugarBuddyAdd "' + ! 281: QuoteTCL(key) + '" "' + ! 282: QuoteTCL(nick) + '" "' + ! 283: QuoteTCL(color) + '" "' + ! 284: QuoteTCL(address) + '"\n') ! 285: ! 286: def _buddy_disappeared_cb(self, ps, buddy): ! 287: ! 288: try: ! 289: key = buddy.props.key or '' ! 290: nick = buddy.props.nick or '' ! 291: color = buddy.props.color or '' ! 292: address = buddy.props.ip4_address or '' ! 293: except AttributeError: ! 294: key = buddy.get_name() or '' ! 295: nick = buddy.get_name() or '' ! 296: color = buddy.get_color() or '' ! 297: address = buddy.get_ip4_address() or '' ! 298: ! 299: logging.debug("Micropolis _BUDDY_DISAPPEARED_CB KEY " + repr(key) + " NICK " + repr(nick) + " COLOR " + repr(color) + " ADDRESS " + repr(address)) ! 300: ! 301: logging.debug("Buddy disappeared " + repr(buddy.props.nick)) ! 302: ! 303: self.send_process( ! 304: 'SugarBuddyDel "' + ! 305: QuoteTCL(key) + '" "' + ! 306: QuoteTCL(nick) + '" "' + ! 307: QuoteTCL(color) + '" "' + ! 308: QuoteTCL(address) + '"\n') ! 309: ! 310: def _sigchild_handler(self, signum, frame): ! 311: logging.debug("got signal %i %r %r" % (signum, frame, self._process)) ! 312: sys.exit(0) ! 313:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.