Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@localhost.localdomain>2006-07-12 11:20:41 (GMT)
committer Marco Pesenti Gritti <marco@localhost.localdomain>2006-07-12 11:20:41 (GMT)
commitca2b08f8b6fb1bc54a4e4f9cfc457f57cf958c7f (patch)
tree8fe41e84baa9f16f4a4d8aa99aa30f1851a24c09 /shell
parente959a6f37f07550e62d670ce6bad69a7e1ad8270 (diff)
Cleanup and document session creation and activity registry
Diffstat (limited to 'shell')
-rw-r--r--shell/ActivityRegistry.py72
-rw-r--r--shell/ConsoleLogger.py2
-rw-r--r--shell/Makefile.am3
-rw-r--r--shell/Session.py119
-rw-r--r--shell/session/Makefile.am4
-rw-r--r--shell/session/__init__.py0
-rw-r--r--shell/session/session.py70
-rwxr-xr-xshell/sugar54
8 files changed, 180 insertions, 144 deletions
diff --git a/shell/ActivityRegistry.py b/shell/ActivityRegistry.py
index 96ec3b1..9f1e857 100644
--- a/shell/ActivityRegistry.py
+++ b/shell/ActivityRegistry.py
@@ -1,29 +1,73 @@
-import dbus
+import logging
-class ActivityInfo:
- def __init__(self, name, title):
+class ActivityModule:
+ """Info about an activity module. Wraps a .activity file."""
+
+ def __init__(self, name, activity_id, activity_exec, directory):
self._name = name
- self._title = title
+ self._id = activity_id
+ self._directory = directory
+ self._exec = activity_exec
def get_name(self):
+ """Get the activity user visible name."""
return self._name
- def get_title(self):
- return self._title
+ def get_id(self):
+ """Get the activity identifier"""
+ return self._id
+
+ def get_class(self):
+ """Get the activity executable"""
+ return self._class
-class ActivityRegistry(dbus.service.Object):
- """Dbus service that tracks the available activities"""
+ def get_directory(self):
+ """Get the path to activity directory."""
+ return self._directory
+
+class ActivityRegistry:
+ """Service that tracks the available activities"""
def __init__(self):
self._activities = []
- bus = dbus.SessionBus()
- bus_name = dbus.service.BusName('com.redhat.Sugar.ActivityRegistry', bus = bus)
- dbus.service.Object.__init__(self, bus_name, '/com/redhat/Sugar/ActivityRegistry')
+ def scan_directory(self, path):
+ """Scan a directory for activities and add them to the registry."""
+ if os.path.isdir(base_dir):
+ for filename in os.listdir(base_dir):
+ activity_dir = os.path.join(base_dir, filename)
+ if os.path.isdir(activity_dir):
+ for filename in os.listdir(activity_dir):
+ if filename.endswith(".activity"):
+ self.add(os.path.join(activity_dir, filename))
+
+ def add(self, path):
+ """Add an activity to the registry. The path points to a .activity file."""
+ cp = ConfigParser()
+ cp.read([path])
+
+ directory = os.path.dirname(path)
+
+ try:
+ activity_id = cp.get('Activity', 'id')
+ name = cp.get('Activity', 'name')
+ except NoOptionError:
+ logging.error('%s miss a required option' % (path))
+
+ if cp.has_option('Activity', 'exec'):
+ activity_exec = cp.get('Activity', 'exec')
+ elif cp.has_option('Activity', 'python_module'):
+ python_module = cp.get('Activity', 'python_module')
+ activity_exec = 'python -m sugar/activity/Activity %s %s' \
+ % (name, python_module)
+ else:
+ logging.error('%s must specifiy exec or python_module' % (path))
+
+ module = ActivityModule(name, activity_id, activity_exec, directory)
+ self._activities.append(module)
- @dbus.service.method("com.redhat.Sugar.ActivityRegistry")
- def add(self, name, title):
- self._activities.append(ActivityInfo(name, title))
+ return True
def list_activities(self):
+ """Enumerate the registered activities as an ActivityModule list."""
return self._activities
diff --git a/shell/ConsoleLogger.py b/shell/ConsoleLogger.py
index fc431ec..4c3eee2 100644
--- a/shell/ConsoleLogger.py
+++ b/shell/ConsoleLogger.py
@@ -1,5 +1,5 @@
import gtk
-import dbus
+import dbus.service
class ConsoleLogger(dbus.service.Object):
def __init__(self):
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 6410546..486c497 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -1,5 +1,3 @@
-SUBDIRS = session
-
bin_SCRIPTS = sugar
sugardir = $(pkgdatadir)/shell
@@ -10,6 +8,7 @@ sugar_PYTHON = \
Owner.py \
HomeWindow.py \
PresenceWindow.py \
+ Session.py \
Shell.py
EXTRA_DIST = sugar
diff --git a/shell/Session.py b/shell/Session.py
new file mode 100644
index 0000000..5f85c10
--- /dev/null
+++ b/shell/Session.py
@@ -0,0 +1,119 @@
+import os
+import signal
+
+import gobject
+
+from Shell import Shell
+
+class Process:
+ def __init__(self, command):
+ self._pid = None
+ self._command = command
+
+ def get_name(self):
+ return self._command
+
+ def start(self):
+ splitted_cmd = self._command.split()
+ try:
+ self._pid = os.spawnvp(os.P_NOWAIT, splitted_cmd[0], splitted_cmd)
+ except Exception, e:
+ logging.error('Cannot run %s' % (self.get_name()))
+
+ def stop(self):
+ # FIXME Obviously we want to notify the processes to
+ # shut down rather then killing them down forcefully.
+ print 'Stopping %s (%d)' % (self.get_name(), self._pid)
+ os.kill(self._pid, signal.SIGTERM)
+
+class ActivityProcess(Process):
+ def __init__(self, module):
+ Process.__init__(self, module.get_exec())
+ self._module = module
+
+ def get_name(self):
+ return self._module.get_name()
+
+class DbusProcess(Process):
+ def __init__(self):
+ Process.__init__(self, "/bin/dbus-daemon --session --print-address")
+
+ def get_name(self):
+ return 'Dbus'
+
+ def start(self):
+ args = self._command.split()
+ (self._pid, ign1, dbus_stdout, ign3) = gobject.spawn_async(
+ args, flags=gobject.SPAWN_STDERR_TO_DEV_NULL, standard_output=True)
+
+ dbus_file = os.fdopen(dbus_stdout)
+ addr = dbus_file.readline()
+ addr = addr.strip()
+ dbus_file.close()
+ os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr
+
+class MatchboxProcess(Process):
+ def __init__(self):
+ Process.__init__(self, 'matchbox-window-manager -use_titlebar no')
+
+ def get_name(self):
+ return 'Matchbox'
+
+class XephyrProcess(Process):
+ def __init__(self):
+ # FIXME How to pick a free display number?
+ self._display = 100
+ cmd = 'Xephyr :%d -ac -screen 640x480' % (self._display)
+ Process.__init__(self, cmd)
+
+ def get_name(self):
+ return 'Xephyr'
+
+ def start(self):
+ Process.start(self)
+ os.environ['DISPLAY'] = ":%d" % (self._display)
+
+class Session:
+ """Takes care of running the shell and all the sugar processes"""
+
+ def __init__(self):
+ self._processes = []
+
+ self._shell = Shell()
+ self._shell.connect('close', self._shell_close_cb)
+ self._shell.start()
+
+ def start(self):
+ """Start the session"""
+ # FIXME We should not start this on the olpc
+ process = XephyrProcess()
+ self._processes.insert(0, process)
+ process.start()
+
+ process = DbusProcess()
+ self._processes.insert(0, process)
+ process.start()
+
+ process = MatchboxProcess()
+ self._processes.insert(0, process)
+ process.start()
+
+ registry = self._shell.get_registry()
+ for activity_module in registry.list_activities():
+ process = ActivityProcess(activity_module)
+ self._processes.insert(0, process)
+ process.start()
+
+ try:
+ import gtk
+ gtk.main()
+ except KeyboardInterrupt:
+ print 'Ctrl+C pressed, exiting...'
+ self.shutdown()
+
+ def _shell_close_cb(self, shell):
+ self.shutdown()
+
+ def shutdown(self):
+ for process in self._processes:
+ process.stop()
diff --git a/shell/session/Makefile.am b/shell/session/Makefile.am
deleted file mode 100644
index 23e4194..0000000
--- a/shell/session/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
-sugardir = $(pkgdatadir)/shell/session
-sugar_PYTHON = \
- __init__.py \
- session.py
diff --git a/shell/session/__init__.py b/shell/session/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/shell/session/__init__.py
+++ /dev/null
diff --git a/shell/session/session.py b/shell/session/session.py
deleted file mode 100644
index d996aa7..0000000
--- a/shell/session/session.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import os
-import signal
-from ConfigParser import ConfigParser
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-from sugar.activity import Activity
-from sugar import env
-
-from Shell import Shell
-
-class Session:
- def __init__(self):
- self._activity_processes = {}
-
- def start(self):
- shell = Shell()
- shell.connect('close', self._shell_close_cb)
- shell.start()
-
- self._run_activities()
-
- try:
- gtk.main()
- except KeyboardInterrupt:
- print 'Ctrl+C pressed, exiting...'
- self.shutdown()
-
- def _run_activities(self):
- base_dirs = []
-
- base_dirs.append(env.get_activities_dir())
- base_dirs.append(os.path.join(env.get_user_dir(), 'activities'))
-
- for base_dir in base_dirs:
- if os.path.isdir(base_dir):
- for filename in os.listdir(base_dir):
- activity_dir = os.path.join(base_dir, filename)
- if os.path.isdir(activity_dir):
- self._run_activity(os.path.abspath(activity_dir))
-
- def _run_activity(self, activity_dir):
- env.add_to_python_path(activity_dir)
-
- for filename in os.listdir(activity_dir):
- if filename.endswith(".activity"):
- path = os.path.join(activity_dir, filename)
- cp = ConfigParser()
- cp.read([path])
-
- activity_name = cp.get('Activity', "name")
- activity_class = cp.get('Activity', "class")
-
- args = [ 'python', '-m', 'sugar/activity/Activity' ]
- args.append(activity_name)
- args.append(activity_class)
- pid = os.spawnvp(os.P_NOWAIT, 'python', args)
- self._activity_processes[activity_name] = pid
-
- def _shell_close_cb(self, shell):
- self.shutdown()
-
- def shutdown(self):
- # FIXME Obviously we want to notify the activities to
- # shutt down rather then killing them down forcefully.
- for name in self._activity_processes.keys():
- print 'Shutting down %s' % (name)
- os.kill(self._activity_processes[name], signal.SIGTERM)
diff --git a/shell/sugar b/shell/sugar
index d352442..1a5d1ad 100755
--- a/shell/sugar
+++ b/shell/sugar
@@ -5,11 +5,6 @@ import os
import pwd
import random
-import gobject
-
-# FIXME How to pick a good display number
-XEPHYR_DISPLAY = 100
-
def add_to_python_path(path):
sys.path.insert(0, path)
if os.environ.has_key('PYTHONPATH'):
@@ -18,54 +13,13 @@ def add_to_python_path(path):
else:
os.environ['PYTHONPATH'] = path
-def start_dbus():
- curdir = os.path.dirname(__file__)
- args = "/bin/dbus-daemon --session --print-address".split()
- (dbus_pid, ign1, dbus_stdout, ign3) = gobject.spawn_async(args, flags=gobject.SPAWN_STDERR_TO_DEV_NULL, standard_output=True)
- dbus_file = os.fdopen(dbus_stdout)
- addr = dbus_file.readline()
- addr = addr.strip()
- dbus_file.close()
-
- os.environ["DBUS_SESSION_BUS_ADDRESS"] = addr
-
- return dbus_pid
-
-def stop_dbus(dbus_pid):
- try:
- print 'Closing dbus-daemon, pid %d' % (dbus_pid)
- os.kill(dbus_pid, 9)
- except OSError:
- pass
-
-def start_xephyr():
- command = 'Xephyr :%d -ac -screen 640x480' % (XEPHYR_DISPLAY)
- xephyr_pid = os.spawnvp(os.P_NOWAIT, 'Xephyr', command.split())
-
-def stop_xephyr():
- os.kill(xephyr_pid)
-
-def start_matchbox():
- command = 'matchbox-window-manager -use_titlebar no'
- xephyr_pid = os.spawnvp(os.P_NOWAIT, 'matchbox-window-manager', command.split())
-
-def stop_matchbox():
- os.kill(xephyr_pid)
-
-start_xephyr()
-os.environ['DISPLAY'] = ":%d" % (XEPHYR_DISPLAY)
-start_matchbox()
-
i = 0
-dbus_daemon_pid = None
for arg in sys.argv:
if arg == '--test-user':
user = sys.argv[i + 1]
user_dir = os.path.expanduser('~/.sugar-' + user)
os.environ['SUGAR_NICK_NAME'] = user
os.environ['SUGAR_USER_DIR'] = user_dir
- dbus_daemon_pid = start_dbus()
- started_dbus = True
i += 1
if not os.environ.has_key("SUGAR_NICK_NAME"):
@@ -89,13 +43,7 @@ else:
print 'Redirecting output to the console, press Ctrl+Down to open it.'
-from session.session import Session
+from Session import Session
session = Session()
session.start()
-
-if dbus_daemon_pid:
- stop_dbus(dbus_daemon_pid)
-
-stop_matchbox()
-stop_xephyr()