[telepathy-butterfly/master] Improved to support webcam, SIP and tunneled SIP calls

Louis-Francis Ratté-Boulianne louis-francis.ratte-boulianne at collabora.co.uk
Thu Sep 10 06:48:11 PDT 2009


---
 butterfly/channel/media.py         |   16 +++----
 butterfly/media/session_handler.py |   15 ++++--
 butterfly/media/stream_handler.py  |   91 +++++++++++++++++++++++++-----------
 3 files changed, 82 insertions(+), 40 deletions(-)

diff --git a/butterfly/channel/media.py b/butterfly/channel/media.py
index 00df280..c6d0a30 100644
--- a/butterfly/channel/media.py
+++ b/butterfly/channel/media.py
@@ -53,7 +53,7 @@ class ButterflyMediaChannel(
         self._handle = handle
 
         self._session_handler = ButterflySessionHandler(self._conn, self, call)
-        self.NewSessionHandler(self._session_handler, self._session_handler.type)
+        self.NewSessionHandler(self._session_handler, self._session_handler.subtype)
 
         self.GroupFlagsChanged(telepathy.CHANNEL_GROUP_FLAG_CAN_REMOVE, 0)
         self.GroupFlagsChanged(telepathy.CHANNEL_GROUP_FLAG_MESSAGE_REMOVE, 0)
@@ -65,7 +65,7 @@ class ButterflyMediaChannel(
         self._call.end()
 
     def GetSessionHandlers(self):
-        return [(self._session_handler, self._session_handler.type)]
+        return [(self._session_handler, self._session_handler.subtype)]
 
     def ListStreams(self):
         print "ListStreams"
@@ -82,9 +82,10 @@ class ButterflyMediaChannel(
 
         streams = dbus.Array([], signature="a(uuuuuu)")
         for type in types:
-            handler = self._session_handler.CreateStream(type)
+            handler = self._session_handler.CreateStream(type, 3)
             streams.append((handler.id, self._handle, handler.type,
                 handler.state, handler.direction, handler.pending_send))
+        self._call.invite()
         return streams
 
     def RequestStreamDirection(self, id, direction):
@@ -112,12 +113,8 @@ class ButterflyMediaChannel(
         for handle in handles:
             print handle, self.GetSelfHandle()
             if handle == int(self.GetSelfHandle()):
-                print "That's me"
                 if self.GetSelfHandle() in self._local_pending:
-                    print "Is local pending"
                     self._call.accept()
-            else:
-                print "Not me", self.GetSelfHandle()
 
     def RemoveMembers(self, handles, message):
         print "Remove members", handles, message
@@ -127,11 +124,11 @@ class ButterflyMediaChannel(
 
     #papyon.event.call.CallEventInterface
     def on_call_incoming(self):
-        self._call.accept()
+        print "RING"
 
     #papyon.event.call.CallEventInterface
     def on_call_ringing(self):
-        pass
+        print "RING"
 
     #papyon.event.call.CallEventInterface
     def on_call_accepted(self):
@@ -184,3 +181,4 @@ class ButterflyMediaChannel(
 
         self.MembersChanged('', added, [], local_pending, remote_pending,
                 0, telepathy.CHANNEL_GROUP_CHANGE_REASON_NONE)
+        self._call.ring()
diff --git a/butterfly/media/session_handler.py b/butterfly/media/session_handler.py
index 0475a7f..ed9b357 100644
--- a/butterfly/media/session_handler.py
+++ b/butterfly/media/session_handler.py
@@ -27,6 +27,7 @@ import papyon.event
 from butterfly.util.decorator import async
 from butterfly.handle import ButterflyHandleFactory
 from butterfly.media import ButterflyStreamHandler
+from papyon.sip.media import MediaSessionType
 
 __all__ = ['ButterflySessionHandler']
 
@@ -37,6 +38,8 @@ class ButterflySessionHandler (telepathy.server.MediaSessionHandler):
         self._call = call
         self._stream_handlers = {}
         self._next_stream_id = 0
+        self._type = call.media_session.type
+        self._subtype = self._type is MediaSessionType.WEBCAM and "msn" or "rtp"
 
         path = channel._object_path + "/sessionhandler1"
         telepathy.server.MediaSessionHandler.__init__(self, connection._name, path)
@@ -47,8 +50,12 @@ class ButterflySessionHandler (telepathy.server.MediaSessionHandler):
         return self._next_stream_id
 
     @property
+    def subtype(self):
+        return self._subtype
+
+    @property
     def type(self):
-        return "rtp"
+        return self._type
 
     def get_stream_path(self, id):
         return "%s/stream%d" % (self._object_path, id)
@@ -87,12 +94,12 @@ class ButterflySessionHandler (telepathy.server.MediaSessionHandler):
         self.NewStreamHandler(path, handler.id, handler.type, handler.direction)
         return handler
 
-    def CreateStream(self, type):
-        if type == 0:
+    def CreateStream(self, type, direction):
+        if type == telepathy.MEDIA_STREAM_TYPE_AUDIO:
             media_type = "audio"
         else:
             media_type = "video"
-        stream = self._call.media_session.add_stream(media_type, True)
+        stream = self._call.media_session.add_stream(media_type, direction, True)
         handler = ButterflyStreamHandler(self._conn, self, stream)
         return handler
 
diff --git a/butterfly/media/stream_handler.py b/butterfly/media/stream_handler.py
index 16cc96c..5002bdc 100644
--- a/butterfly/media/stream_handler.py
+++ b/butterfly/media/stream_handler.py
@@ -24,6 +24,8 @@ import telepathy
 import papyon
 import papyon.event
 
+from papyon.sip.constants import *
+
 __all__ = ['ButterflyStreamHandler']
 
 StreamTypes = {
@@ -46,7 +48,7 @@ class ButterflyStreamHandler (
         self._interfaces = set()
 
         self._state = 1
-        self._direction = telepathy.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL
+        self._direction = stream.direction
         if self._stream.controlling:
             self._pending_send = telepathy.MEDIA_STREAM_PENDING_REMOTE_SEND
         else:
@@ -61,7 +63,7 @@ class ButterflyStreamHandler (
         papyon.event.MediaStreamEventInterface.__init__(self, stream)
 
         self._implement_property_get(telepathy.interfaces.MEDIA_STREAM_HANDLER,
-            {'CreatedLocally': lambda: self._stream.controlling,
+            {'CreatedLocally': lambda: self.created_locally,
              'NATTraversal': lambda: self.nat_traversal,
              'STUNServers': lambda: self.stun_servers,
              'RelayInfo': lambda: self.relay_info})
@@ -87,8 +89,17 @@ class ButterflyStreamHandler (
         return self._state
 
     @property
+    def created_locally(self):
+        return self._stream.controlling
+
+    @property
     def nat_traversal(self):
-        return "wlm-2009"
+        if self._session.type is MediaSessionType.SIP:
+            return "wlm-8.5"
+        elif self._session.type is MediaSessionType.TUNNELED_SIP:
+            return "wlm-2009"
+        else:
+            return "none"
 
     @property
     def relay_info(self):
@@ -96,7 +107,11 @@ class ButterflyStreamHandler (
 
     @property
     def stun_servers(self):
-        return [("64.14.48.28", dbus.UInt32(3478))]
+        if self._session.type in (MediaSessionType.SIP,
+                MediaSessionType.TUNNELED_SIP):
+            return [("64.14.48.28", dbus.UInt32(3478))]
+        else:
+            return dbus.Array([], signature="a(su)")
 
     def set_direction(self, direction, pending_send):
         self._direction = direction
@@ -104,16 +119,21 @@ class ButterflyStreamHandler (
 
     def Ready(self, codecs):
         print "StreamReady : ", codecs
+        webcam = (self._session.type is MediaSessionType.WEBCAM)
+
         if self._remote_candidates is not None:
             self.SetRemoteCandidateList(self._remote_candidates)
-        if self._remote_codecs is not None:
+        if self._remote_codecs is not None and not webcam:
             self.SetRemoteCodecs(self._remote_codecs)
-        self.SetStreamPlaying(True)
-        self.SetStreamSending(True)
-        if self._stream.controlling:
+
+        self.SetStreamPlaying(self._direction &
+                telepathy.MEDIA_STREAM_DIRECTION_RECEIVE)
+        self.SetStreamSending(self._direction &
+                telepathy.MEDIA_STREAM_DIRECTION_SEND)
+
+        if self.created_locally or webcam:
+            print "Set local codecs"
             self.SetLocalCodecs(codecs)
-        #if self._session is None:
-        #    self._session = ButterflyWebcamSession(self._conn, self._handle.contact)
 
     def StreamState(self, state):
         print "StreamState : ", state
@@ -122,6 +142,7 @@ class ButterflyStreamHandler (
 
     def Error(self, code, message):
         print "StreamError - %i - %s" % (code, message)
+        self.Close()
 
     def NewNativeCandidate(self, id, transports):
         candidates = []
@@ -192,7 +213,7 @@ class ButterflyStreamHandler (
     def convert_ice_candidates(self, candidates):
         array = {}
         for c in candidates:
-            if c.transport.lower() == "udp":
+            if c.transport == "UDP":
                 proto = 0
             else:
                 proto = 1
@@ -205,22 +226,34 @@ class ButterflyStreamHandler (
             else:
                 print "TYPE", c.type
                 type = 0
-            while True:
-                try:
-                    base64.b64decode(c.username)
-                    break
-                except:
-                    c.username += "="
-            while True:
-                try:
-                    base64.b64decode(c.password)
-                    break
-                except:
-                    c.password += "="
-            preference = float(c.priority) / 65536.0
-            transport = (c.component_id, c.ip, c.port, proto, "RTP", "AVP",
-                    preference, type, c.username, c.password)
+            #FIXME
+            if c.username:
+                while True:
+                    try:
+                        base64.b64decode(c.username)
+                        break
+                    except:
+                        c.username += "="
+            else:
+                c.username = ""
+            if c.password:
+                while True:
+                    try:
+                        base64.b64decode(c.password)
+                        break
+                    except:
+                        c.password += "="
+            else:
+                c.password = ""
+            if c.priority is not None:
+                preference = float(c.priority) / 65536.0
+            else:
+                preference = 1.0
+            transport = (c.component_id, c.ip, c.port, proto,
+                    self._session.subtype, "AVP", preference, type, c.username,
+                    c.password)
             array.setdefault(c.foundation, []).append(transport)
+        print array
         return array.items()
 
     def convert_tp_candidate(self, id, transport):
@@ -238,6 +271,10 @@ class ButterflyStreamHandler (
             type = "relay"
             addr = None
             port = None
-        return papyon.sip.ice.ICECandidate(19, id, int(transport[0]), proto, priority,
+        if self._session.type is MediaSessionType.SIP:
+            draft = 6
+        else:
+            draft = 19
+        return papyon.sip.ice.ICECandidate(draft, id, int(transport[0]), proto, priority,
                 transport[8], transport[9], type, transport[1],
                 int(transport[2]), addr, port)
-- 
1.5.6.5




More information about the telepathy-commits mailing list