Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames/dbusproxy.py
diff options
context:
space:
mode:
authorManuel Kaufmann <humitos@gmail.com>2012-03-27 13:15:10 (GMT)
committer Rafael Ortiz <rafael@activitycentral.com>2012-03-28 18:05:22 (GMT)
commit335ad73456ba3ec8f56811abddcaca4650199db1 (patch)
treedb788baba57c7656c9bdb73eb9003a70dc87d59a /olpcgames/dbusproxy.py
parent6deeb3f569e6c9a1c02a32a011b7a96a58fa8443 (diff)
Save and restore state of the game
Ability to 'save' (when the user closes the Activity) and 'restore' (when the user launch it from the Journal or the Home without holding Alt) the state of the game. For this ability I had to upgrade 'olpcgames' to 1.6 because 'olpcgames.FILE_READ_REQUEST' and 'olpcgames.FILE_WRITE_REQUEST' events are added in that version and those events are needed for this. The data is saved (as JSON, with json module) in the 'event.metadata["state"]' and the timestamp state is saved in 'event.filename'. This commit solves ticket #2393: * http://bugs.sugarlabs.org/ticket/2393 Signed-off-by: Manuel Kaufmann <humitos@gmail.com> Signed-off-by: Rafael Ortiz <rafael@activitycentral.com>
Diffstat (limited to 'olpcgames/dbusproxy.py')
-rw-r--r--olpcgames/dbusproxy.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/olpcgames/dbusproxy.py b/olpcgames/dbusproxy.py
new file mode 100644
index 0000000..a103e28
--- /dev/null
+++ b/olpcgames/dbusproxy.py
@@ -0,0 +1,93 @@
+"""Spike test for a safer networking system for DBUS-based objects"""
+from olpcgames import eventwrap, util
+from dbus import proxies
+import logging
+log = logging.getLogger( 'dbus' )
+log.setLevel( logging.DEBUG )
+
+def wrap( value, tube=None,path=None ):
+ """Wrap object with any required pygame-side proxies"""
+ if isinstance( value,proxies._ProxyMethod ):
+ return DBUSMethod( value, tube=tube, path=path )
+ elif isinstance( value, proxies._DeferredMethod ):
+ value._proxy_method = DBUSMethod( value._proxy_method, tube=tube, path=path )
+ return value
+ elif isinstance( value, proxies.ProxyObject ):
+ return DBUSProxy( value, tube=tube, path=path )
+ else:
+ return value
+
+class DBUSProxy( object ):
+ """Proxy for the DBUS Proxy object"""
+ def __init__( self, proxy, tube=None, path=None ):
+ log.info( 'Creating Pygame-side proxy for %s (%s)', proxy,path )
+ self.__proxy = proxy
+ self.__tube = tube
+ self.__path = path
+ def __getattr__( self, key ):
+ """Retrieve attribute of given key"""
+ from dbus import proxies
+ return wrap( getattr( self.__proxy, key ) )
+ def add_signal_receiver( self, callback, eventName, interface, path=None, sender_keyword='sender'):
+ """Add a new signal handler (which will be called many times) for given signal
+ """
+ log.info( """Setting signal receiver %s for event %s on interface %s (object path %s) with sender_keyword = %r""",
+ callback, eventName, interface, path, sender_keyword,
+ )
+ log.debug( """proxy: %s proxy.tube: %s""", self.__proxy, self.__proxy.tube )
+ self.__tube.add_signal_receiver(
+ Callback( callback ),
+ eventName,
+ interface,
+ path = path or self.__path,
+ sender_keyword = sender_keyword,
+ )
+
+class DBUSMethod( object ):
+ """DBUS method which does callbacks in the Pygame (eventwrapper) thread"""
+ def __init__( self, proxy, tube,path ):
+ log.info( 'Creating Pygame-side method proxy for %s', proxy )
+ self.__proxy = proxy
+ self.__tube = tube
+ self.__path = path
+ def __call__( self, *args, **named ):
+ """Perform the asynchronous call"""
+ log.info( 'Calling proxy for %s with *%s, **%s', self.__proxy, args, named )
+ callback, errback = named.get( 'reply_handler'), named.get( 'error_handler' )
+ if not callback:
+ raise TypeError( """Require a reply_handler named argument to do any asynchronous call""" )
+ else:
+ callback = Callback( callback )
+ if not errback:
+ errback = defaultErrback
+ else:
+ errback = Callback( errback )
+ named['reply_handler'] = callback
+ named['error_handler'] = errback
+ return self.__proxy( *args, **named )
+
+def defaultErrback( error ):
+ """Log the error to stderr/log"""
+ log.error( """Failure in DBUS call: %s""", error )
+
+class Callback( object ):
+ """PyGTK-side callback which generates a CallbackResult to process on the Pygame side"""
+ def __init__( self, callable, callContext = None):
+ """Initialize the callback to process results"""
+ self.callable = callable
+ if callContext is None:
+ callContext = util.get_traceback( None )
+ self.callContext = callContext
+ def __call__( self, *args, **named ):
+ """PyGTK-side callback operation"""
+ log.info( 'Callback %s return value *%s, **%s', self.callable, args, named )
+ from olpcgames import eventwrap
+ args = [wrap(a) for a in args]
+ named = dict([
+ (k,wrap(v)) for k,v in named.items()
+ ])
+ eventwrap.post(
+ eventwrap.CallbackResult(
+ self.callable, args, named, callContext = self.callContext
+ )
+ )