# Copyright 2009 Simon Schampijer # # 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 2 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """WebSDK Activity: A studio for developing an activity.""" import gtk import gobject import os import sys import logging import socket import subprocess from gettext import gettext as _ from sugar.activity import activity from sugar.activity.activity import get_bundle_path USE_GECKO=False if not USE_GECKO: try: import webkit from websdk.inspector import Inspector except ImportError: try: import websdk.webkit_local as webkit from websdk.inspector import Inspector except ImportError: print "Webkit not found" USE_GECKO=True if USE_GECKO: import hulahop hulahop.startup(os.path.join(activity.get_activity_root(), 'data/gecko')) from websdk.browser import Browser def yieldsleep(func): def start(*args, **kwds): iterable = func(*args, **kwds) def step(*args, **kwds): try: time = next(iterable) gobject.timeout_add_seconds(time, step) except StopIteration: pass gobject.idle_add(step) return start def PickUnusedPort(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('localhost', 0)) addr, port = s.getsockname() s.close() return port def isOpen(ip,port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, int(port))) s.shutdown(2) return True except: return False class HelloWorldActivity(activity.Activity): """HelloWorldActivity class as specified in activity.info""" def __init__(self, handle): """Set up the HelloWorld activity.""" activity.Activity.__init__(self, handle) self.port = PickUnusedPort() self.serverprocess = None self.bundle_dir = get_bundle_path() self.max_participants = 1 OLD_TOOLBAR = False try: from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton, ToolButton from sugar.activity.widgets import ActivityToolbarButton, StopButton, \ ShareButton, KeepButton, TitleEntry, ActivityButton except ImportError: OLD_TOOLBAR = True if not self._shared_activity: #I am the initiator self.start_server() else: self.connect('joined', self._joined_cb) if self.get_shared(): # we have already joined self._joined_cb() if OLD_TOOLBAR: from sugar.activity.activity import Activity, ActivityToolbox toolbox = ActivityToolbox(self) self.set_toolbox(toolbox) toolbox.show() else: # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() title_entry = TitleEntry(self) toolbar_box.toolbar.insert(title_entry, -1) title_entry.show() share_button = ShareButton(self) toolbar_box.toolbar.insert(share_button, -1) share_button.show() separator = gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() #play_image = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, # gtk.ICON_SIZE_BUTTON) #play_image.show() start_button = ToolButton('go-home') #start_button.set_icon_widget(play_image) start_button.show() start_button.connect('clicked', self.__start_button_cb) toolbar_box.toolbar.insert(start_button, -1) debug_button = ToolButton("activity-debug") toolbar_box.toolbar.insert(debug_button, -1) debug_button.connect('clicked', self.__debug_button_cb) debug_button.show() stop_button = StopButton(self) toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show() if not USE_GECKO: self.web_view = webkit.WebView() settings = self.web_view.get_settings() settings.set_property("enable-developer-extras", True) self.inspector = Inspector(self.web_view.get_web_inspector()) self.inspector.set_title("WebSDK Inspector") else: self.web_view = Browser() self.open("file:///%s/app/static/init.html" % self.bundle_dir) self.set_canvas(self.web_view) self.web_view.show() self.waitforport() def _joined_cb(self, activity): """Joined a shared activity.""" if not self._shared_activity: return if len(self._shared_activity.get_joined_buddies())==1: print "We are alone" def __start_button_cb(self, widget): self.open("http://localhost:%s/" % self.port) return True def __debug_button_cb(self, widget): self.open("http://localhost:%s/debug" % self.port) return True @yieldsleep def waitforport(self): while 1: if isOpen("127.0.0.1", self.port): if self._shared_activity: # we are shared self.open("http://localhost:%s/" % self.port) else: self.open("http://localhost:%s/" % self.port) break else: yield(1) def open(self, url): if not USE_GECKO: self.web_view.open(url) else: #use webkit self.web_view.load_uri(url) def can_close(self): self.open("http://localhost:%s/shutdown" % self.port) return True def start_server(self): self.serverprocess = subprocess.Popen(("python", "app/app.py", str(self.port))) if self._shared_activity: self.share_server() def share_server(self): # Make a tube for it chan = self._shared_activity.telepathy_tubes_chan iface = chan[telepathy.CHANNEL_TYPE_TUBES] self.httpd_tube_id = iface.OfferStreamTube( READ_STREAM_SERVICE, {}, telepathy.SOCKET_ADDRESS_TYPE_IPV4, ('127.0.0.1', dbus.UInt16(self.port)), telepathy.SOCKET_ACCESS_CONTROL_LOCALHOST, 0) return True