changeset 1b61572222a0 in /home/hg/repos/gajim

details:http://hg.gajim.org/gajim?cmd=changeset;node=1b61572222a0
description: support for content-{add,reject,accept}, new helpers, and other 
few things

diffstat:

 src/chat_control.py  |   18 +++-
 src/common/jingle.py |  223 
++++++++++++++++++++++++++++++++++++++-----------------
 src/dialogs.py       |   18 ++++-
 src/gajim.py         |   16 +++-
 4 files changed, 195 insertions(+), 80 deletions(-)

diffs (truncated from 602 to 300 lines):

diff -r cbd3eacacb0c -r 1b61572222a0 src/chat_control.py
--- a/src/chat_control.py       Fri Sep 25 15:47:43 2009 +0200
+++ b/src/chat_control.py       Fri Sep 25 19:32:13 2009 +0200
@@ -1579,14 +1579,17 @@
                elif state == 'connecting':
                        self.audio_state = self.JINGLE_STATE_CONNECTING
                        self.audio_sid = sid
+                       self._audio_button.set_active(True)
                elif state == 'connection_received':
                        self.audio_state = self.JINGLE_STATE_CONNECTION_RECEIVED
                        self.audio_sid = sid
+                       self._audio_button.set_active(True)
                elif state == 'connected':
                        self.audio_state = self.JINGLE_STATE_CONNECTED
                elif state == 'stop':
                        self.audio_state = self.JINGLE_STATE_AVAILABLE
                        self.audio_sid = None
+                       self._audio_button.set_active(False)
                elif state == 'error':
                        self.audio_state = self.JINGLE_STATE_ERROR
                self.update_audio()
@@ -1605,15 +1608,18 @@
                        self.video_sid = None
                elif state == 'connecting':
                        self.video_state = self.JINGLE_STATE_CONNECTING
+                       self._video_button.set_active(True)
                        self.video_sid = sid
                elif state == 'connection_received':
                        self.video_state = self.JINGLE_STATE_CONNECTION_RECEIVED
+                       self._video_button.set_active(True)
                        self.video_sid = sid
                elif state == 'connected':
                        self.video_state = self.JINGLE_STATE_CONNECTED
                elif state == 'stop':
                        self.video_state = self.JINGLE_STATE_AVAILABLE
                        self.video_sid = None
+                       self._video_button.set_active(False)
                elif state == 'error':
                        self.video_state = self.JINGLE_STATE_ERROR
                self.update_video()
@@ -1825,10 +1831,11 @@
                        self.set_audio_state('connecting', sid)
                else:
                        session = 
gajim.connections[self.account].get_jingle_session(
-                               self.contact.get_full_jid(), self.audio_sid)
+                               self.contact.get_full_jid(), self.video_sid)
                        if session:
-                               # TODO: end only audio
-                               session.end_session()
+                               content = session.get_content('audio')
+                               if content:
+                                       session.remove_content(content.creator, 
content.name)
 
        def on_video_button_toggled(self, widget):
                if widget.get_active():
@@ -1839,8 +1846,9 @@
                        session = 
gajim.connections[self.account].get_jingle_session(
                                self.contact.get_full_jid(), self.video_sid)
                        if session:
-                               # TODO: end only video
-                               session.end_session()
+                               content = session.get_content('video')
+                               if content:
+                                       session.remove_content(content.creator, 
content.name)
 
        def _toggle_gpg(self):
                if not self.gpg_is_active and not self.contact.keyID:
diff -r cbd3eacacb0c -r 1b61572222a0 src/common/jingle.py
--- a/src/common/jingle.py      Fri Sep 25 15:47:43 2009 +0200
+++ b/src/common/jingle.py      Fri Sep 25 19:32:13 2009 +0200
@@ -17,7 +17,10 @@
 #   - 'senders' attribute of 'content' element
 #   - security preconditions
 #   * actions:
-#     - content-accept, content-reject, content-add, content-modify
+#     - content-accept: see content-add
+#     - content-reject: sending it ; receiving is ok
+#     - content-add: handling ; sending is ok
+#     - content-modify: both
 #     - description-info, session-info
 #     - security-info
 #     - transport-accept, transport-reject
@@ -88,7 +91,7 @@
                # our full jid
                self.ourjid = gajim.get_jid_from_account(self.connection.name) 
+ '/' + \
                        con.server_resource
-               self.peerjid = jid # jid we connect to
+               self.peerjid = str(jid) # jid we connect to
                # jid we use as the initiator
                self.initiator = weinitiate and self.ourjid or self.peerjid
                # jid we use as the responder
@@ -107,10 +110,12 @@
                # use .prepend() to add new callbacks, especially when you're 
going
                # to send error instead of ack
                self.callbacks = {
-                       'content-accept':       [self.__contentAcceptCB, 
self.__defaultCB],
-                       'content-add':          [self.__defaultCB], #TODO
+                       'content-accept':       [self.__contentAcceptCB, 
self.__broadcastCB,
+                               self.__defaultCB],
+                       'content-add':          [self.__contentAddCB, 
self.__broadcastCB,
+                               self.__defaultCB], #TODO
                        'content-modify':       [self.__defaultCB], #TODO
-                       'content-reject':       [self.__defaultCB], #TODO
+                       'content-reject':       [self.__defaultCB, 
self.__contentRemoveCB], #TODO
                        'content-remove':       [self.__defaultCB, 
self.__contentRemoveCB],
                        'description-info':     [self.__defaultCB], #TODO
                        'security-info':        [self.__defaultCB], #TODO
@@ -133,7 +138,6 @@
        def approve_session(self):
                ''' Called when user accepts session in UI (when we aren't the 
initiator).
                '''
-               self.accepted = True
                self.accept_session()
 
        def decline_session(self):
@@ -154,10 +158,23 @@
 
        ''' Middle-level functions to manage contents. Handle local content
        cache and send change notifications. '''
+       def get_content(self, media=None):
+               if media == 'audio':
+                       cls = JingleVoIP
+               elif media == 'video':
+                       cls = JingleVideo
+               #elif media == None:
+               #       cls = JingleContent
+               else:
+                       return None
+
+               for content in self.contents.values():
+                       if isinstance(content, cls):
+                               return content
+
        def add_content(self, name, content, creator='we'):
                ''' Add new content to session. If the session is active,
                this will send proper stanza to update session. 
-               The protocol prohibits changing that when pending.
                Creator must be one of ('we', 'peer', 'initiator', 
'responder')'''
                assert creator in ('we', 'peer', 'initiator', 'responder')
 
@@ -171,34 +188,53 @@
                content.name = name
                self.contents[(creator, name)] = content
 
-               if self.state == JingleStates.active:
-                       pass # TODO: send proper stanza, shouldn't be needed now
-
        def remove_content(self, creator, name):
                ''' We do not need this now '''
-               pass
+               #TODO:
+               if (creator, name) in self.contents:
+                       content = self.contents[(creator, name)]
+                       if len(self.contents) > 1:
+                               self.__content_remove(content)
+                       self.contents[(creator, name)].destroy()
+               if len(self.contents) == 0:
+                       self.end_session()
 
        def modify_content(self, creator, name, *someother):
                ''' We do not need this now '''
                pass
 
-       def accept_session(self):
-               ''' Check if all contents and user agreed to start session. '''
-               if not self.weinitiate and self.accepted and \
-               self.state == JingleStates.pending and self.is_ready():
-                       self.__session_accept()
+       def on_session_state_changed(self, content=None):
+               if self.state == JingleStates.active and self.accepted:
+                       if not content:
+                               return
+                       if (content.creator == 'initiator') == self.weinitiate:
+                               # We initiated this content. It's a pending 
content-add.
+                               self.__content_add(content)
+                       else:
+                               # The other side created this content, we 
accept it.
+                               self.__content_accept(content)
+               elif self.is_ready():
+                       if not self.weinitiate and self.state == 
JingleStates.pending:
+                               self.__session_accept()
+                       elif self.weinitiate and self.state == 
JingleStates.ended:
+                               self.__session_initiate()
 
        def is_ready(self):
                ''' Returns True when all codecs and candidates are ready
                (for all contents). '''
-               return all((content.is_ready() for content in 
self.contents.itervalues()))
+               return (all((content.is_ready() for content in 
self.contents.itervalues()))
+                       and self.accepted)
 
        ''' Middle-level function to do stanza exchange. '''
+       def accept_session(self):
+               ''' Mark the session as accepted. '''
+               self.accepted = True
+               self.on_session_state_changed()
+
        def start_session(self):
-               ''' Start session. '''
-               #FIXME: Start only once
-               if self.weinitiate and self.state == JingleStates.ended and 
self.is_ready():
-                       self.__session_initiate()
+               ''' Mark the session as ready to be started. '''
+               self.accepted = True
+               self.on_session_state_changed()
 
        def send_session_info(self):
                pass
@@ -309,10 +345,10 @@
                        creator = content['creator']
                        name = content['name']
                        if (creator, name) in self.contents:
-                               del self.contents[(creator, name)]
+                               self.contents[(creator, name)].destroy()
                if len(self.contents) == 0:
                        reason = xmpp.Node('reason')
-                       reason.setTag('success') #FIXME: Is it the good one?
+                       reason.setTag('success')
                        self._session_terminate(reason)
 
        def __sessionAcceptCB(self, stanza, jingle, error, action):
@@ -328,6 +364,27 @@
                        creator = content['creator']
                        name = content['name']#TODO...
 
+       def __contentAddCB(self, stanza, jingle, error, action):
+               #TODO: Needs to be rewritten
+               if self.state == JingleStates.ended:
+                       raise OutOfOrder
+               for element in jingle.iterTags('content'):
+                       # checking what kind of session this will be
+                       desc_ns = element.getTag('description').getNamespace()
+                       media = element.getTag('description')['media']
+                       tran_ns = element.getTag('transport').getNamespace()
+                       if desc_ns == xmpp.NS_JINGLE_RTP and media in ('audio', 
'video') \
+                       and tran_ns == xmpp.NS_JINGLE_ICE_UDP:
+                               if media == 'audio':
+                                       self.add_content(element['name'], 
JingleVoIP(self), 'peer')
+                               else:
+                                       self.add_content(element['name'], 
JingleVideo(self), 'peer')
+                       else:
+                               content = JingleContent()
+                               self.add_content(element['name'], content, 
'peer')
+                               self.__content_reject(content)
+                               self.contents[(content.creator, 
content.name)].destroy()
+
        def __sessionInitiateCB(self, stanza, jingle, error, action):
                ''' We got a jingle session request from other entity,
                therefore we are the receiver... Unpack the data,
@@ -511,20 +568,40 @@
                        text = '%s (%s)' % (reason, text)
                else:
                        text = reason
+               self.connection.delete_jingle(self)
                self.connection.dispatch('JINGLE_DISCONNECTED', (self.peerjid, 
self.sid, text))
-               self.connection.delete_jingle(self)
 
-       def __content_add(self):
-               assert self.state == JingleStates.active
+       def __content_add(self, content):
+               #TODO: test
+               assert self.state != JingleStates.ended
+               stanza, jingle = self.__make_jingle('content-add')
+               self.__append_content(jingle, content)
+               self.__broadcastCB(stanza, jingle, None, 'content-add-sent')
+               self.connection.connection.send(stanza)
 
-       def __content_accept(self):
+       def __content_accept(self, content):
+               #TODO: test
                assert self.state != JingleStates.ended
+               stanza, jingle = self.__make_jingle('content-accept')
+               self.__append_content(jingle, content)
+               self.__broadcastCB(stanza, jingle, None, 'content-accept-sent')
+               self.connection.connection.send(stanza)
+
+       def __content_reject(self, content):
+               assert self.state != JingleStates.ended
+               stanza, jingle = self.__make_jingle('content-reject')
+               self.__append_content(jingle, content)
+               self.connection.connection.send(stanza)
 
        def __content_modify(self):
                assert self.state != JingleStates.ended
 
-       def __content_remove(self):
+       def __content_remove(self, content):
                assert self.state != JingleStates.ended
+               stanza, jingle = self.__make_jingle('content-remove')
+               self.__append_content(jingle, content)
+               self.connection.connection.send(stanza)
+               #TODO: dispatch something?
 
        def content_negociated(self, media):
                self.connection.dispatch('JINGLE_CONNECTED', (self.peerjid, 
self.sid,
@@ -554,8 +631,8 @@
 
                self.callbacks = {
                        # these are called when *we* get stanzas
-                       'content-accept': [],
_______________________________________________
Commits mailing list
[email protected]
http://lists.gajim.org/cgi-bin/listinfo/commits

Reply via email to