Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames/eventwrap.py
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2013-12-11 20:16:42 (GMT)
committer Walter Bender <walter@sugarlabs.org>2013-12-11 20:16:42 (GMT)
commit324fb287d7b540bbb09a58350e2614507ed5c530 (patch)
treeb96a234fe0fa2c0f3a691049a52c1349c48e1098 /olpcgames/eventwrap.py
parent445dc0cc5770f9aa62264efb37c35d5964e41c0f (diff)
massive commit to reconstruct world before commits were lost
Diffstat (limited to 'olpcgames/eventwrap.py')
-rwxr-xr-xolpcgames/eventwrap.py388
1 files changed, 0 insertions, 388 deletions
diff --git a/olpcgames/eventwrap.py b/olpcgames/eventwrap.py
deleted file mode 100755
index 402109c..0000000
--- a/olpcgames/eventwrap.py
+++ /dev/null
@@ -1,388 +0,0 @@
-"""Provides substitute for Pygame's "event" module using gtkEvent
-
-Provides methods which will be substituted into Pygame in order to
-provide the synthetic events that we will feed into the Pygame queue.
-These methods are registered by the "install" method.
-
-This event queue does not support getting events only of a certain type.
-You need to get all pending events at a time, or filter them yourself. You
-can, however, block and unblock events of certain types, so that may be
-useful to you.
-
-Set_grab doesn't do anything (you are not allowed to grab events). Sorry.
-
-Extensions:
-
- wait( timeout=None ) -- allows you to wait for only a specified period
- before you return to the application. Can be used to e.g. wait for a
- short period, then release some resources, then wait a bit more, then
- release a few more resources, then a bit more...
-"""
-import pygame
-import gtk
-import Queue
-import thread, threading
-import logging
-from olpcgames import util
-
-log = logging.getLogger( 'olpcgames.eventwrap' )
-
-from pygame.event import Event, event_name, pump as pygame_pump, get as pygame_get
-
-class Event(object):
- """Mock pygame events"""
- def __init__(self, type, dict=None,**named):
- """Initialise the new event variables from dictionary and named become attributes"""
- self.type = type
- if dict:
- self.__dict__.update( dict )
- self.__dict__.update( named )
- def _get_dict( self ):
- return self.__dict__
- dict = property( _get_dict )
- def __repr__( self ):
- result = []
- for key,value in self.__dict__.items():
- if not key.startswith( '_' ):
- result.append( '%s = %r'%( key, value ))
- return '%s( %s, %s )'%(
- self.__class__.__name__,
- self.type,
- ",".join( result ),
- )
- def block( self ):
- """Block until this event is finished processing
-
- Event process is only finalized on the *next* call to retrieve an event
- after the processing operation in which the event is processed. In some
- extremely rare cases we might actually see that happen, were the
- file-saving event (for example) causes the Pygame event loop to exit.
- In that case, the GTK event loop *could* hang.
- """
- log.info( '''Blocking GTK thread on event: %s''', self )
- self.__lock = threading.Event()
- self.__lock.wait()
- def retire( self ):
- """Block the GTK event loop until this event is processed"""
- try:
- self.__lock.set()
- log.info( '''Released GTK thread on event: %s''', self )
- except AttributeError, err:
- pass
-
-class CallbackResult( object ):
- def __init__( self, callable, args, named, callContext=None ):
- """Perform callback in Pygame loop with args and named
-
- callContext is used to provide more information when there is
- a failure in the callback (for debugging purposes)
- """
- self.callable = callable
- self.args = args
- self.named = named
- if callContext is None:
- callContext = util.get_traceback( None )
- self.callContext = callContext
- def __call__( self ):
- """Perform the actual callback in the Pygame event loop"""
- try:
- self.callable( *self.args, **self.named )
- except Exception, err:
- log.error(
- """Failure in callback %s( *%s, **%s ): %s\n%s""",
- getattr(self.callable, '__name__',self.callable),
- self.args, self.named,
- util.get_traceback( err ),
- self.callContext
- )
-
-
-_EVENTS_TO_RETIRE = []
-
-def _releaseEvents( ):
- """Release/retire previously-processed events"""
- if _EVENTS_TO_RETIRE:
- for event in _EVENTS_TO_RETIRE:
- try:
- event.retire()
- except AttributeError, err:
- pass
-
-def _processCallbacks( events ):
- """Process any callbacks in events and remove from the stream"""
- result = []
- for event in events:
- if isinstance( event, CallbackResult ):
- event()
- else:
- result.append( event )
- if events and not result:
- result.append(
- Event( type=pygame.NOEVENT )
- )
- return result
-
-def _recordEvents( events ):
- """Record the set of events to retire on the next iteration"""
- global _EVENTS_TO_RETIRE
- events = _processCallbacks( events )
- _EVENTS_TO_RETIRE = events
- return events
-
-def install():
- """Installs this module (eventwrap) as an in-place replacement for the pygame.event module.
-
- Use install() when you need to interact with Pygame code written
- without reference to the olpcgames wrapper mechanisms to have the
- code use this module's event queue.
-
- XXX Really, use it everywhere you want to use olpcgames, as olpcgames
- registers the handler itself, so you will always wind up with it registered when
- you use olpcgames (the gtkEvent.Translator.hook_pygame method calls it).
- """
- log.info( 'Installing OLPCGames event wrapper' )
- from olpcgames import eventwrap
- import pygame
- pygame.event = eventwrap
- import sys
- sys.modules["pygame.event"] = eventwrap
-
-# Event queue:
-class _FilterQueue( Queue.Queue ):
- """Simple Queue sub-class with a put_left method"""
- def get_type( self, filterFunction, block=True, timeout=None ):
- """Get events of a given type
-
- Note: can raise Empty *even* when blocking if someone else
- pops the event off the queue before we get around to it.
- """
- self.not_empty.acquire()
- try:
- if not block:
- if self._empty_type( filterFunction ):
- raise Queue.Empty
- elif timeout is None:
- while self._empty_type( filterFunction ):
- self.not_empty.wait()
- else:
- if timeout < 0:
- raise ValueError("'timeout' must be a positive number")
- endtime = _time() + timeout
- while self._empty_type( filterFunction ):
- remaining = endtime - _time()
- if remaining <= 0.0:
- raise Queue.Empty
- self.not_empty.wait(remaining)
- item = self._get_type( filterFunction )
- self.not_full.notify()
- return item
- finally:
- self.not_empty.release()
- def _empty_type( self, filterFunction ):
- """Are we empty with respect to filterFunction?"""
- for element in self.queue:
- if filterFunction( element ):
- return False
- return True
- def _get_type( self, filterFunction ):
- """Get the first instance which matches filterFunction"""
- for element in self.queue:
- if filterFunction( element ):
- self.queue.remove( element )
- return element
- # someone popped the event off the queue before we got to it!
- raise Queue.Empty
- def peek_type( self, filterFunction= lambda x: True ):
- """Peek to see if we have filterFunction-matching element
-
- Note: obviously this is *not* thread safe, it's just informative...
- """
- try:
- for element in self.queue:
- if filterFunction( element ):
- return element
- return None
- except RuntimeError, err:
- return None # none yet, at least
-
-g_events = _FilterQueue()
-
-# Set of blocked events as set by set
-g_blocked = set()
-g_blockedlock = thread.allocate_lock() # should use threading instead
-g_blockAll = False
-
-def _typeChecker( types ):
- """Create check whether an event is in types"""
- try:
- if 1 in types:
- pass
- def check( element ):
- return element.type in types
- return check
- except TypeError, err:
- def check( element ):
- return element.type == types
- return check
-
-def pump():
- """Handle any window manager and other external events that aren't passed to the user
-
- Call this periodically (once a frame) if you don't call get(), poll() or wait()
- """
- pygame_pump()
- _releaseEvents()
-
-def get( types=None):
- """Get a list of all pending events
-
- types -- either an integer event-type or a sequence of integer event types
- which restrict the set of event-types returned from the queue. Keep in mind
- that if you do not remove events you may wind up with an eternally growing
- queue or a full queue. Normally you will want to remove all events in your
- top-level event-loop and propagate them yourself.
-
- Note: if you use types you lose all event ordering guarantees, events
- may show up after events which were originally produced before them due to
- the re-ordering of the queue on filtering!
- """
- pump()
- eventlist = []
- try:
- if types:
- check = _typeChecker( types )
- while True:
- eventlist.append(g_events.get_type( check, block=False))
- else:
- while True:
- eventlist.append(g_events.get(block=False))
- except Queue.Empty:
- pass
-
- pygameEvents = pygame_get()
- if pygameEvents:
- log.info( 'Raw Pygame events: %s', pygameEvents)
- eventlist.extend( pygameEvents )
- return _recordEvents( eventlist )
-
-def poll():
- """Get the next pending event if exists. Otherwise, return pygame.NOEVENT."""
- pump()
- try:
- result = g_events.get(block=False)
- return _recordEvents( [result] )[0]
- except Queue.Empty:
- return Event(pygame.NOEVENT)
-
-
-def wait( timeout = None):
- """Get the next pending event, wait up to timeout if none
-
- timeout -- if present, only wait up to timeout seconds, if we
- do not find an event before then, return None. timeout
- is an OLPCGames-specific extension.
- """
- pump()
- try:
- result = None
- result = g_events.get(block=True, timeout=timeout)
- try:
- return _recordEvents( [result] )[0]
- except IndexError, err:
- return Event( type=pygame.NOEVENT )
- except Queue.Empty, err:
- return None
-
-def peek(types=None):
- """True if there is any pending event
-
- types -- optional set of event-types used to check whether
- an event is of interest. If specified must be either a sequence
- of integers/longs or an integer/long.
- """
- if types:
- check = _typeChecker( types )
- return g_events.peek_type( check ) is not None
- return not g_events.empty()
-
-def clear():
- """Clears the entire pending queue of events
-
- Rarely used
- """
- try:
- discarded = []
- while True:
- discarded.append( g_events.get(block=False) )
- discarded = _recordEvents( discarded )
- _releaseEvents()
- return discarded
- except Queue.Empty:
- pass
-
-def set_blocked(item):
- """Block item/items from being added to the event queue"""
- g_blockedlock.acquire()
- try:
- # FIXME: we do not currently know how to block all event types when
- # you set_blocked(none).
- [g_blocked.add(x) for x in makeseq(item)]
- finally:
- g_blockedlock.release()
-
-def set_allowed(item):
- """Allow item/items to be added to the event queue"""
- g_blockedlock.acquire()
- try:
- if item is None:
- # Allow all events when you set_allowed(none). Strange, eh?
- # Pygame is a wonderful API.
- g_blocked.clear()
- else:
- [g_blocked.remove(x) for x in makeseq(item)]
- finally:
- g_blockedlock.release()
-
-def get_blocked(*args, **kwargs):
- g_blockedlock.acquire()
- try:
- blocked = frozenset(g_blocked)
- return blocked
- finally:
- g_blockedlock.release()
-
-def set_grab(grabbing):
- """This method will not be implemented"""
-
-def get_grab():
- """This method will not be implemented"""
-
-def post(event):
- """Post a new event to the Queue of events"""
- g_blockedlock.acquire()
- try:
- if getattr(event,'type',None) not in g_blocked:
- g_events.put(event, block=False)
- finally:
- g_blockedlock.release()
-
-def makeseq(obj):
- """Accept either a scalar object or a sequence, and return a sequence
- over which we can iterate. If we were passed a sequence, return it
- unchanged. If we were passed a scalar, return a tuple containing only
- that scalar. This allows the caller to easily support one-or-many.
- """
- # Strings are the exception because you can iterate over their chars
- # -- yet, for all the purposes I've ever cared about, I want to treat
- # a string as a scalar.
- if isinstance(obj, basestring):
- return (obj,)
- try:
- # Except as noted above, if you can get an iter() from an object,
- # it's a collection.
- iter(obj)
- return obj
- except TypeError:
- # obj is a scalar. Wrap it in a tuple so we can iterate over the
- # one item.
- return (obj,)