Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/mesh
diff options
context:
space:
mode:
authorAntoine van Gelder <antoine@g7.org.za>2007-10-28 09:45:28 (GMT)
committer Antoine van Gelder <antoine@g7.org.za>2007-10-28 09:45:28 (GMT)
commit800e3caabcd9c85b0b2ae9299217ea31d0309545 (patch)
tree130af075b9cbc72eba462c58166c771739ded092 /mesh
parent49eb6ebd4760b4bfcf009f7e887a3ef9a547061d (diff)
Initial import
Diffstat (limited to 'mesh')
-rw-r--r--mesh/__init__.py0
-rw-r--r--mesh/activitysession.py254
2 files changed, 254 insertions, 0 deletions
diff --git a/mesh/__init__.py b/mesh/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mesh/__init__.py
diff --git a/mesh/activitysession.py b/mesh/activitysession.py
new file mode 100644
index 0000000..6c2b51b
--- /dev/null
+++ b/mesh/activitysession.py
@@ -0,0 +1,254 @@
+# 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
+#
+
+
+import logging
+
+
+from dbus.service import method, signal
+from dbus.gobject_service import ExportedGObject
+
+
+from globals import Globals
+from persistence.jokemachinestate import JokeMachineState
+from persistence.joke import Joke
+
+MESH_SERVICE = 'org.worldwideworkshop.JokeMachine'
+MESH_IFACE = MESH_SERVICE
+MESH_PATH = '/org/worldwideworkshop/JokeMachine'
+
+
+
+class JokeMachineSession(ExportedGObject):
+ """The bit that talks over the TUBES!!!"""
+
+ def __init__(self, tube, is_initiator, get_buddy, activity):
+ """Initialise the PollSession.
+
+ tube -- TubeConnection
+ is_initiator -- boolean, True = we are sharing, False = we are joining
+ get_buddy -- function
+ activity -- JokeMachine (sugar.activity.Activity)
+ """
+ super(JokeMachineSession, self).__init__(tube, MESH_PATH)
+ self.tube = tube
+ self.is_initiator = is_initiator
+ self.entered = False # Have we set up the tube?
+ self._get_buddy = get_buddy # Converts handle to Buddy object
+ self.activity = activity # JokeMachine
+ self.tube.watch_participants(self.participant_change_cb)
+
+
+
+ # Signals and signal handlers ################################################
+
+ @signal(dbus_interface=MESH_IFACE, signature='')
+ def Hello(self):
+ """Signal to request that my UpdatePoll method is called to let me know about
+ other known polls."""
+
+ # a -> Say hello to incoming buddy and send him our state
+ def hello_cb(self, sender=None):
+ '''Tell the newcomer what's going on.'''
+ assert sender is not None
+ logging.debug('In hello_cb - Newcomer %s has joined and sent Hello', sender)
+ # sender is a bus name - check if it's me:
+ if sender == self.my_bus_name:
+ # then I don't want to respond to my own Hello
+ return
+
+ logging.debug('Sending %s my state' % sender)
+ state_pickle = Globals.JokeMachineState.dumps()
+ logging.debug('PICKLE TYPE: %r (hello_cb)' % type(state_pickle))
+ #state_pickle = ('This is my tubes message being sent to %s' % sender)
+ #logging.debug('PICKLE TYPE: %r (hello_cb)' % type(state_pickle))
+ self.tube.get_object(sender, MESH_PATH).PumpActivityState(state_pickle, dbus_interface=MESH_IFACE)
+
+ # Ask for other's jokes back
+ #self.HelloBack(sender)
+
+
+
+ # b -> I am a buddy who be receiving some state
+ @method(dbus_interface=MESH_IFACE,
+ in_signature='s',
+ out_signature='')
+ def PumpActivityState(self, state_pickle):
+ state_pickle = str(state_pickle)
+ #logging.info('I JUST RECEIVED PICKLE TYPE: %r - %s (PumpActivityState)', type(state_pickle), state_pickle)
+ if len(state_pickle) == 0:
+ logging.debug('JokeMachineSession.ReceiveActivityState() -> empty state_pickle - creating empty state')
+ activity_state = JokeMachineState().test_data()
+ else:
+ logging.debug('JokeMachineSession.ReceiveActivityState() -> Unpickling state from remote')
+ activity_state = JokeMachineState.loads(state_pickle)
+ Globals.set_activity_state(activity_state)
+
+ # refresh activity ui
+ Globals.JokeMachineActivity.refresh()
+ logging.debug('Finished receiving state')
+
+
+ # c -> I am the connecting buddy, I can send some state back here if I want
+ @signal(dbus_interface=MESH_IFACE, signature='s')
+ def HelloBack(self, recipient):
+ """Respond to Hello.
+ recipient -- string, sender of Hello.
+ """
+
+ def helloback_cb(self, recipient, sender):
+ """Reply to Hello.
+
+ recipient -- string, the XO who send the original Hello.
+
+ Other XOs should ignore this signal.
+ """
+ logging.debug('*** In helloback_cb: recipient: %s, sender: %s' %
+ (recipient, sender))
+ if sender == self.my_bus_name:
+ # Ignore my own signal
+ return
+ if recipient != self.my_bus_name:
+ # This is not for me
+ return
+
+ # anything ?
+
+
+ # d -> I am the connecting buddy, I have a joke to submit to you
+ @signal (dbus_interface=MESH_IFACE, signature='us')
+ def Submit(self, jokebook_id, joke_pickle):
+ '''Submit a joke'''
+
+ def submit_cb(self, jokebook_id, joke_pickle, sender=None):
+ '''Receive someones submission
+ jokebook_id -- the jokebook to submit joke to
+ joke_pickle -- a pickled joke'''
+ if sender == self.my_bus_name: # don't respond to own submit signal
+ return
+ logging.debug('In submit_cv. sender: %r' % sender)
+
+ # 1. unpickle joke
+ joke_pickle = str(joke_pickle)
+ if len(joke_pickle) == 0:
+ logging.debug('JokeMachineSession.submit_cb() -> empty joke_pickle - doing nothing')
+ return
+ joke = Joke.loads(joke_pickle)
+ logging.debug('%s submitted a joke to my jokebook# %d with text: %s and answer %s', joke.joker, jokebook_id, joke.text, joke.answer)
+
+ # 2. get the jokebook it belongs to
+ jokebook = Globals.JokeMachineState.jokebook(jokebook_id)
+ if jokebook is None:
+ logging.error('Joke was submitted to non-existent jokebook id %d', jokebook_id)
+ return
+
+ # 3. add it to submissions in the appropriate jokebook
+ jokebook.submissions.append(joke)
+
+ # 4. TODO - show some kind of alert - ask on #sugar
+
+
+ # e -> I am the initiator, I've just accepted a submission, tell everyone!
+ @signal (dbus_interface=MESH_IFACE, signature='us')
+ def BroadcastJoke(self, jokebook_id, joke_pickle):
+ '''broadcast newly accepted submission back to the mesh'''
+
+ def broadcast_joke_cb(self, jokebook_id, joke_pickle, sender):
+ '''handle a BroadCast Joke by creating a new joke in the local store'''
+ if sender == self.my_bus_name:
+ # Ignore my own signal
+ return
+
+ logging.debug('In broadcast_joke_cb. sender: %r' % sender)
+
+ # 1. unpickle joke
+ joke_pickle = str(joke_pickle)
+ if len(joke_pickle) == 0:
+ logging.debug('JokeMachineSession.broadcast_joke_cb() -> empty joke_pickle - doing nothing')
+ return
+ joke = Joke.loads(joke_pickle)
+ logging.debug('%s broadcast a joke to my jokebook# %d with text: %s and answer %s', joke.joker, jokebook_id, joke.text, joke.answer)
+
+ # 2. get the jokebook it belongs to
+ jokebook = Globals.JokeMachineState.jokebook(jokebook_id)
+ if jokebook is None:
+ logging.error('Joke was broadcast to non-existent jokebook id %d', jokebook_id)
+ return
+
+ # 3. add it to jokes in the appropriate jokebook
+ jokebook.jokes.append(joke)
+
+ # 4. TODO - show some kind of alert - ask on #sugar
+
+
+ # ############################################################################
+
+
+ def participant_change_cb(self, added, removed):
+ '''Callback when tube participants change.'''
+ logging.debug('In participant_change_cb')
+ if added:
+ logging.debug('Adding participants: %r' % added)
+ if removed:
+ logging.debug('Removing participants: %r' % removed)
+ for handle, bus_name in added:
+ buddy = self._get_buddy(handle)
+ if buddy is not None:
+ logging.debug('Buddy %s was added' % buddy.props.nick)
+ for handle in removed:
+ buddy = self._get_buddy(handle)
+ if buddy is not None:
+ logging.debug('Buddy %s was removed' % buddy.props.nick)
+
+ # TODO - participant changed
+ # Set buddy's polls to not active so I can't vote on them
+ #for poll in self.activity._polls:
+ #if poll.author == buddy.props.nick:
+ #poll.active = False
+ #logging.debug(
+ #'Closing poll %s of %s who just left.' %
+ #(poll.title, poll.author))
+
+ if not self.entered:
+ if self.is_initiator:
+ logging.debug("I'm initiating the tube")
+ else:
+ logging.debug('Joining, sending Hello')
+ self.Hello()
+ self.tube.add_signal_receiver(self.hello_cb,
+ 'Hello',
+ MESH_IFACE,
+ path=MESH_PATH,
+ sender_keyword='sender')
+ self.tube.add_signal_receiver(self.helloback_cb,
+ 'HelloBack',
+ MESH_IFACE,
+ path=MESH_PATH,
+ sender_keyword='sender')
+ self.tube.add_signal_receiver(self.submit_cb,
+ 'Submit',
+ MESH_IFACE,
+ path=MESH_PATH,
+ sender_keyword='sender')
+ self.tube.add_signal_receiver(self.broadcast_joke_cb,
+ 'BroadcastJoke',
+ MESH_IFACE,
+ path=MESH_PATH,
+ sender_keyword='sender')
+
+ self.my_bus_name = self.tube.get_unique_name()
+ self.entered = True
+
+