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