coding standards, and other few things
This commit is contained in:
parent
6b99db8980
commit
c162780a58
|
@ -1775,7 +1775,7 @@ class ChatControl(ChatControlBase, ChatCommands):
|
||||||
self.set_audio_state('connecting', sid)
|
self.set_audio_state('connecting', sid)
|
||||||
|
|
||||||
def on_stop_audio_button_activate(self, *things):
|
def on_stop_audio_button_activate(self, *things):
|
||||||
session = gajim.connections[self.account].getJingleSession(
|
session = gajim.connections[self.account].get_jingle_session(
|
||||||
self.contact.get_full_jid(), self.audio_sid)
|
self.contact.get_full_jid(), self.audio_sid)
|
||||||
if session:
|
if session:
|
||||||
session.end_session()
|
session.end_session()
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
# * handle different kinds of sink and src elements
|
# * handle different kinds of sink and src elements
|
||||||
|
|
||||||
import gajim
|
import gajim
|
||||||
import gobject
|
|
||||||
import xmpp
|
import xmpp
|
||||||
|
|
||||||
import farsight, gst
|
import farsight, gst
|
||||||
|
@ -65,9 +64,9 @@ def get_first_gst_element(elements):
|
||||||
#FIXME: Move it to JingleSession.States?
|
#FIXME: Move it to JingleSession.States?
|
||||||
class JingleStates(object):
|
class JingleStates(object):
|
||||||
''' States in which jingle session may exist. '''
|
''' States in which jingle session may exist. '''
|
||||||
ended=0
|
ended = 0
|
||||||
pending=1
|
pending = 1
|
||||||
active=2
|
active = 2
|
||||||
|
|
||||||
#FIXME: Move it to JingleTransport.Type?
|
#FIXME: Move it to JingleTransport.Type?
|
||||||
class TransportType(object):
|
class TransportType(object):
|
||||||
|
@ -75,9 +74,6 @@ class TransportType(object):
|
||||||
datagram = 1
|
datagram = 1
|
||||||
streaming = 2
|
streaming = 2
|
||||||
|
|
||||||
class Error(Exception): pass
|
|
||||||
class WrongState(Error): pass
|
|
||||||
|
|
||||||
class OutOfOrder(Exception):
|
class OutOfOrder(Exception):
|
||||||
''' Exception that should be raised when an action is received when in the wrong state. '''
|
''' Exception that should be raised when an action is received when in the wrong state. '''
|
||||||
|
|
||||||
|
@ -110,7 +106,7 @@ class JingleSession(object):
|
||||||
# callbacks to call on proper contents
|
# callbacks to call on proper contents
|
||||||
# use .prepend() to add new callbacks, especially when you're going
|
# use .prepend() to add new callbacks, especially when you're going
|
||||||
# to send error instead of ack
|
# to send error instead of ack
|
||||||
self.callbacks={
|
self.callbacks = {
|
||||||
'content-accept': [self.__contentAcceptCB, self.__defaultCB],
|
'content-accept': [self.__contentAcceptCB, self.__defaultCB],
|
||||||
'content-add': [self.__defaultCB], #TODO
|
'content-add': [self.__defaultCB], #TODO
|
||||||
'content-modify': [self.__defaultCB], #TODO
|
'content-modify': [self.__defaultCB], #TODO
|
||||||
|
@ -134,39 +130,37 @@ class JingleSession(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
''' Interaction with user '''
|
''' Interaction with user '''
|
||||||
def approveSession(self):
|
def approve_session(self):
|
||||||
''' Called when user accepts session in UI (when we aren't the initiator).
|
''' Called when user accepts session in UI (when we aren't the initiator).
|
||||||
'''
|
'''
|
||||||
self.accepted = True
|
self.accepted = True
|
||||||
self.acceptSession()
|
self.accept_session()
|
||||||
|
|
||||||
def declineSession(self):
|
def decline_session(self):
|
||||||
''' Called when user declines session in UI (when we aren't the initiator)
|
''' Called when user declines session in UI (when we aren't the initiator)
|
||||||
'''
|
'''
|
||||||
reason = xmpp.Node('reason')
|
reason = xmpp.Node('reason')
|
||||||
reason.addChild('decline')
|
reason.addChild('decline')
|
||||||
self.__sessionTerminate(reason)
|
self.__session_terminate(reason)
|
||||||
|
|
||||||
def end_session(self):
|
def end_session(self):
|
||||||
|
''' Called when user stops or cancel session in UI. '''
|
||||||
reason = xmpp.Node('reason')
|
reason = xmpp.Node('reason')
|
||||||
if self.state == JingleStates.active:
|
if self.state == JingleStates.active:
|
||||||
reason.addChild('success')
|
reason.addChild('success')
|
||||||
else:
|
else:
|
||||||
reason.addChild('cancel')
|
reason.addChild('cancel')
|
||||||
self.__sessionTerminate(reason)
|
self.__session_terminate(reason)
|
||||||
|
|
||||||
''' Middle-level functions to manage contents. Handle local content
|
''' Middle-level functions to manage contents. Handle local content
|
||||||
cache and send change notifications. '''
|
cache and send change notifications. '''
|
||||||
def addContent(self, name, content, creator='we'):
|
def add_content(self, name, content, creator='we'):
|
||||||
''' Add new content to session. If the session is active,
|
''' Add new content to session. If the session is active,
|
||||||
this will send proper stanza to update session.
|
this will send proper stanza to update session.
|
||||||
The protocol prohibits changing that when pending.
|
The protocol prohibits changing that when pending.
|
||||||
Creator must be one of ('we', 'peer', 'initiator', 'responder')'''
|
Creator must be one of ('we', 'peer', 'initiator', 'responder')'''
|
||||||
assert creator in ('we', 'peer', 'initiator', 'responder')
|
assert creator in ('we', 'peer', 'initiator', 'responder')
|
||||||
|
|
||||||
if self.state == JingleStates.pending:
|
|
||||||
raise WrongState
|
|
||||||
|
|
||||||
if (creator == 'we' and self.weinitiate) or (creator == 'peer' and \
|
if (creator == 'we' and self.weinitiate) or (creator == 'peer' and \
|
||||||
not self.weinitiate):
|
not self.weinitiate):
|
||||||
creator = 'initiator'
|
creator = 'initiator'
|
||||||
|
@ -175,47 +169,50 @@ class JingleSession(object):
|
||||||
creator = 'responder'
|
creator = 'responder'
|
||||||
content.creator = creator
|
content.creator = creator
|
||||||
content.name = name
|
content.name = name
|
||||||
self.contents[(creator,name)] = content
|
self.contents[(creator, name)] = content
|
||||||
|
|
||||||
if self.state == JingleStates.active:
|
if self.state == JingleStates.active:
|
||||||
pass # TODO: send proper stanza, shouldn't be needed now
|
pass # TODO: send proper stanza, shouldn't be needed now
|
||||||
|
|
||||||
def removeContent(self, creator, name):
|
def remove_content(self, creator, name):
|
||||||
''' We do not need this now '''
|
''' We do not need this now '''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def modifyContent(self, creator, name, *someother):
|
def modify_content(self, creator, name, *someother):
|
||||||
''' We do not need this now '''
|
''' We do not need this now '''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def acceptSession(self):
|
def accept_session(self):
|
||||||
''' Check if all contents and user agreed to start session. '''
|
''' Check if all contents and user agreed to start session. '''
|
||||||
if not self.weinitiate and self.accepted and \
|
if not self.weinitiate and self.accepted and \
|
||||||
self.state == JingleStates.pending and self.is_ready():
|
self.state == JingleStates.pending and self.is_ready():
|
||||||
self.__sessionAccept()
|
self.__session_accept()
|
||||||
|
|
||||||
def is_ready(self):
|
def is_ready(self):
|
||||||
|
''' Returns True when all codecs and candidates are ready
|
||||||
|
(for all contents). '''
|
||||||
return all((c.candidates_ready and c.p2psession.get_property('codecs-ready')
|
return all((c.candidates_ready and c.p2psession.get_property('codecs-ready')
|
||||||
for c in self.contents.itervalues()))
|
for c in self.contents.itervalues()))
|
||||||
|
|
||||||
''' Middle-level function to do stanza exchange. '''
|
''' Middle-level function to do stanza exchange. '''
|
||||||
def startSession(self):
|
def start_session(self):
|
||||||
''' Start session. '''
|
''' Start session. '''
|
||||||
#FIXME: Start only once
|
#FIXME: Start only once
|
||||||
if self.weinitiate and self.state == JingleStates.ended and self.is_ready():
|
if self.weinitiate and self.state == JingleStates.ended and self.is_ready():
|
||||||
self.__sessionInitiate()
|
self.__session_initiate()
|
||||||
|
|
||||||
def sendSessionInfo(self): pass
|
def send_session_info(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def sendContentAccept(self, content):
|
def send_content_accept(self, content):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
stanza, jingle = self.__makeJingle('content-accept')
|
stanza, jingle = self.__make_jingle('content-accept')
|
||||||
jingle.addChild(node=content)
|
jingle.addChild(node=content)
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
|
|
||||||
def sendTransportInfo(self, content):
|
def send_transport_info(self, content):
|
||||||
assert self.state!=JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
stanza, jingle = self.__makeJingle('transport-info')
|
stanza, jingle = self.__make_jingle('transport-info')
|
||||||
jingle.addChild(node=content)
|
jingle.addChild(node=content)
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
|
|
||||||
|
@ -272,7 +269,7 @@ class JingleSession(object):
|
||||||
self.__dispatch_error(xmpp_error, jingle_error, text)
|
self.__dispatch_error(xmpp_error, jingle_error, text)
|
||||||
#FIXME: Not sure when we would want to do that...
|
#FIXME: Not sure when we would want to do that...
|
||||||
if xmpp_error == 'item-not-found':
|
if xmpp_error == 'item-not-found':
|
||||||
self.connection.deleteJingle(self)
|
self.connection.delete_jingle(self)
|
||||||
|
|
||||||
def __transportReplaceCB(self, stanza, jingle, error, action):
|
def __transportReplaceCB(self, stanza, jingle, error, action):
|
||||||
for content in jingle.iterTags('content'):
|
for content in jingle.iterTags('content'):
|
||||||
|
@ -286,16 +283,16 @@ class JingleSession(object):
|
||||||
#Anyway, content's transport is not modifiable yet
|
#Anyway, content's transport is not modifiable yet
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
stanza, jingle = self.__makeJingle('transport-reject')
|
stanza, jingle = self.__make_jingle('transport-reject')
|
||||||
c = jingle.setTag('content', attrs={'creator': creator,
|
content = jingle.setTag('content', attrs={'creator': creator,
|
||||||
'name': name})
|
'name': name})
|
||||||
c.setTag('transport', namespace=transport_ns)
|
content.setTag('transport', namespace=transport_ns)
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
else:
|
else:
|
||||||
#FIXME: This ressource is unknown to us, what should we do?
|
#FIXME: This ressource is unknown to us, what should we do?
|
||||||
#For now, reject the transport
|
#For now, reject the transport
|
||||||
stanza, jingle = self.__makeJingle('transport-reject')
|
stanza, jingle = self.__make_jingle('transport-reject')
|
||||||
c = jingle.setTag('content', attrs={'creator': creator,
|
c = jingle.setTag('content', attrs={'creator': creator,
|
||||||
'name': name})
|
'name': name})
|
||||||
c.setTag('transport', namespace=transport_ns)
|
c.setTag('transport', namespace=transport_ns)
|
||||||
|
@ -317,7 +314,7 @@ class JingleSession(object):
|
||||||
if len(self.contents) == 0:
|
if len(self.contents) == 0:
|
||||||
reason = xmpp.Node('reason')
|
reason = xmpp.Node('reason')
|
||||||
reason.setTag('success') #FIXME: Is it the good one?
|
reason.setTag('success') #FIXME: Is it the good one?
|
||||||
self.__sessionTerminate(reason)
|
self.__session_terminate(reason)
|
||||||
|
|
||||||
def __sessionAcceptCB(self, stanza, jingle, error, action):
|
def __sessionAcceptCB(self, stanza, jingle, error, action):
|
||||||
if self.state != JingleStates.pending: #FIXME
|
if self.state != JingleStates.pending: #FIXME
|
||||||
|
@ -363,9 +360,9 @@ class JingleSession(object):
|
||||||
if tran_ns == xmpp.NS_JINGLE_ICE_UDP:
|
if tran_ns == xmpp.NS_JINGLE_ICE_UDP:
|
||||||
# we've got voip content
|
# we've got voip content
|
||||||
if media == 'audio':
|
if media == 'audio':
|
||||||
self.addContent(element['name'], JingleVoIP(self), 'peer')
|
self.add_content(element['name'], JingleVoIP(self), 'peer')
|
||||||
else:
|
else:
|
||||||
self.addContent(element['name'], JingleVideo(self), 'peer')
|
self.add_content(element['name'], JingleVideo(self), 'peer')
|
||||||
contents.append((media,))
|
contents.append((media,))
|
||||||
transports_ok = True
|
transports_ok = True
|
||||||
|
|
||||||
|
@ -375,7 +372,7 @@ class JingleSession(object):
|
||||||
reason = xmpp.Node('reason')
|
reason = xmpp.Node('reason')
|
||||||
reason.setTag('unsupported-applications')
|
reason.setTag('unsupported-applications')
|
||||||
self.__defaultCB(stanza, jingle, error, action)
|
self.__defaultCB(stanza, jingle, error, action)
|
||||||
self.__sessionTerminate(reason)
|
self.__session_terminate(reason)
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
if not transports_ok:
|
if not transports_ok:
|
||||||
|
@ -383,7 +380,7 @@ class JingleSession(object):
|
||||||
reason = xmpp.Node('reason')
|
reason = xmpp.Node('reason')
|
||||||
reason.setTag('unsupported-transports')
|
reason.setTag('unsupported-transports')
|
||||||
self.__defaultCB(stanza, jingle, error, action)
|
self.__defaultCB(stanza, jingle, error, action)
|
||||||
self.__sessionTerminate(reason)
|
self.__session_terminate(reason)
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
self.state = JingleStates.pending
|
self.state = JingleStates.pending
|
||||||
|
@ -401,7 +398,7 @@ class JingleSession(object):
|
||||||
cn.stanzaCB(stanza, content, error, action)
|
cn.stanzaCB(stanza, content, error, action)
|
||||||
|
|
||||||
def __sessionTerminateCB(self, stanza, jingle, error, action):
|
def __sessionTerminateCB(self, stanza, jingle, error, action):
|
||||||
self.connection.deleteJingle(self)
|
self.connection.delete_jingle(self)
|
||||||
reason, text = self.__reason_from_stanza(jingle)
|
reason, text = self.__reason_from_stanza(jingle)
|
||||||
if reason not in ('success', 'cancel', 'decline'):
|
if reason not in ('success', 'cancel', 'decline'):
|
||||||
self.__dispatch_error(reason, reason, text)
|
self.__dispatch_error(reason, reason, text)
|
||||||
|
@ -411,6 +408,11 @@ class JingleSession(object):
|
||||||
text = reason#TODO
|
text = reason#TODO
|
||||||
self.connection.dispatch('JINGLE_DISCONNECTED', (self.peerjid, self.sid, text))
|
self.connection.dispatch('JINGLE_DISCONNECTED', (self.peerjid, self.sid, text))
|
||||||
|
|
||||||
|
def __broadcastAllCB(self, stanza, jingle, error, action):
|
||||||
|
''' Broadcast the stanza to all content handlers. '''
|
||||||
|
for content in self.contents.itervalues():
|
||||||
|
content.stanzaCB(stanza, None, error, action)
|
||||||
|
|
||||||
def __send_error(self, stanza, error, jingle_error=None, text=None):
|
def __send_error(self, stanza, error, jingle_error=None, text=None):
|
||||||
err = xmpp.Error(stanza, error)
|
err = xmpp.Error(stanza, error)
|
||||||
err.setNamespace(xmpp.NS_STANZAS)
|
err.setNamespace(xmpp.NS_STANZAS)
|
||||||
|
@ -430,11 +432,6 @@ class JingleSession(object):
|
||||||
text = error
|
text = error
|
||||||
self.connection.dispatch('JINGLE_ERROR', (self.peerjid, self.sid, text))
|
self.connection.dispatch('JINGLE_ERROR', (self.peerjid, self.sid, text))
|
||||||
|
|
||||||
def __broadcastAllCB(self, stanza, jingle, error, action):
|
|
||||||
''' Broadcast the stanza to all content handlers. '''
|
|
||||||
for content in self.contents.itervalues():
|
|
||||||
content.stanzaCB(stanza, None, error, action)
|
|
||||||
|
|
||||||
def __reason_from_stanza(self, stanza):
|
def __reason_from_stanza(self, stanza):
|
||||||
reason = 'success'
|
reason = 'success'
|
||||||
reasons = ['success', 'busy', 'cancel', 'connectivity-error',
|
reasons = ['success', 'busy', 'cancel', 'connectivity-error',
|
||||||
|
@ -453,7 +450,7 @@ class JingleSession(object):
|
||||||
|
|
||||||
''' Methods that make/send proper pieces of XML. They check if the session
|
''' Methods that make/send proper pieces of XML. They check if the session
|
||||||
is in appropriate state. '''
|
is in appropriate state. '''
|
||||||
def __makeJingle(self, action):
|
def __make_jingle(self, action):
|
||||||
stanza = xmpp.Iq(typ='set', to=xmpp.JID(self.peerjid))
|
stanza = xmpp.Iq(typ='set', to=xmpp.JID(self.peerjid))
|
||||||
attrs = {'action': action,
|
attrs = {'action': action,
|
||||||
'sid': self.sid}
|
'sid': self.sid}
|
||||||
|
@ -464,46 +461,46 @@ class JingleSession(object):
|
||||||
jingle = stanza.addChild('jingle', attrs=attrs, namespace=xmpp.NS_JINGLE)
|
jingle = stanza.addChild('jingle', attrs=attrs, namespace=xmpp.NS_JINGLE)
|
||||||
return stanza, jingle
|
return stanza, jingle
|
||||||
|
|
||||||
def __appendContent(self, jingle, content):
|
def __append_content(self, jingle, content):
|
||||||
''' Append <content/> element to <jingle/> element,
|
''' Append <content/> element to <jingle/> element,
|
||||||
with (full=True) or without (full=False) <content/>
|
with (full=True) or without (full=False) <content/>
|
||||||
children. '''
|
children. '''
|
||||||
jingle.addChild('content',
|
jingle.addChild('content',
|
||||||
attrs={'name': content.name, 'creator': content.creator})
|
attrs={'name': content.name, 'creator': content.creator})
|
||||||
|
|
||||||
def __appendContents(self, jingle):
|
def __append_contents(self, jingle):
|
||||||
''' Append all <content/> elements to <jingle/>.'''
|
''' Append all <content/> elements to <jingle/>.'''
|
||||||
# TODO: integrate with __appendContent?
|
# TODO: integrate with __appendContent?
|
||||||
# TODO: parameters 'name', 'content'?
|
# TODO: parameters 'name', 'content'?
|
||||||
for content in self.contents.values():
|
for content in self.contents.values():
|
||||||
self.__appendContent(jingle, content)
|
self.__append_content(jingle, content)
|
||||||
|
|
||||||
def __sessionInitiate(self):
|
def __session_initiate(self):
|
||||||
assert self.state==JingleStates.ended
|
assert self.state == JingleStates.ended
|
||||||
stanza, jingle = self.__makeJingle('session-initiate')
|
stanza, jingle = self.__make_jingle('session-initiate')
|
||||||
self.__appendContents(jingle)
|
self.__append_contents(jingle)
|
||||||
self.__broadcastCB(stanza, jingle, None, 'session-initiate-sent')
|
self.__broadcastCB(stanza, jingle, None, 'session-initiate-sent')
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
self.state = JingleStates.pending
|
self.state = JingleStates.pending
|
||||||
|
|
||||||
def __sessionAccept(self):
|
def __session_accept(self):
|
||||||
assert self.state==JingleStates.pending
|
assert self.state == JingleStates.pending
|
||||||
stanza, jingle = self.__makeJingle('session-accept')
|
stanza, jingle = self.__make_jingle('session-accept')
|
||||||
self.__appendContents(jingle)
|
self.__append_contents(jingle)
|
||||||
self.__broadcastCB(stanza, jingle, None, 'session-accept-sent')
|
self.__broadcastCB(stanza, jingle, None, 'session-accept-sent')
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
self.state = JingleStates.active
|
self.state = JingleStates.active
|
||||||
|
|
||||||
def __sessionInfo(self, payload=None):
|
def __session_info(self, payload=None):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
stanza, jingle = self.__makeJingle('session-info')
|
stanza, jingle = self.__make_jingle('session-info')
|
||||||
if payload:
|
if payload:
|
||||||
jingle.addChild(node=payload)
|
jingle.addChild(node=payload)
|
||||||
self.connection.connection.send(stanza)
|
self.connection.connection.send(stanza)
|
||||||
|
|
||||||
def __sessionTerminate(self, reason=None):
|
def __session_terminate(self, reason=None):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
stanza, jingle = self.__makeJingle('session-terminate')
|
stanza, jingle = self.__make_jingle('session-terminate')
|
||||||
if reason is not None:
|
if reason is not None:
|
||||||
jingle.addChild(node=reason)
|
jingle.addChild(node=reason)
|
||||||
self.__broadcastAllCB(stanza, jingle, None, 'session-terminate-sent')
|
self.__broadcastAllCB(stanza, jingle, None, 'session-terminate-sent')
|
||||||
|
@ -516,29 +513,29 @@ class JingleSession(object):
|
||||||
else:
|
else:
|
||||||
text = reason
|
text = reason
|
||||||
self.connection.dispatch('JINGLE_DISCONNECTED', (self.peerjid, self.sid, text))
|
self.connection.dispatch('JINGLE_DISCONNECTED', (self.peerjid, self.sid, text))
|
||||||
self.connection.deleteJingle(self)
|
self.connection.delete_jingle(self)
|
||||||
|
|
||||||
def __contentAdd(self):
|
def __content_add(self):
|
||||||
assert self.state == JingleStates.active
|
assert self.state == JingleStates.active
|
||||||
|
|
||||||
def __contentAccept(self):
|
def __content_accept(self):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
|
|
||||||
def __contentModify(self):
|
def __content_modify(self):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
|
|
||||||
def __contentRemove(self):
|
def __content_remove(self):
|
||||||
assert self.state != JingleStates.ended
|
assert self.state != JingleStates.ended
|
||||||
|
|
||||||
def content_negociated(self, media):
|
def content_negociated(self, media):
|
||||||
self.connection.dispatch('JINGLE_CONNECTED', (self.peerjid, self.sid,
|
self.connection.dispatch('JINGLE_CONNECTED', (self.peerjid, self.sid,
|
||||||
media))
|
media))
|
||||||
|
|
||||||
class JingleTransport(object):
|
#TODO:
|
||||||
''' An abstraction of a transport in Jingle sessions. '''
|
#class JingleTransport(object):
|
||||||
#TODO: Complete
|
# ''' An abstraction of a transport in Jingle sessions. '''
|
||||||
def __init__(self):
|
# def __init__(self):
|
||||||
pass#TODO: Complete
|
# pass
|
||||||
|
|
||||||
|
|
||||||
class JingleContent(object):
|
class JingleContent(object):
|
||||||
|
@ -595,7 +592,7 @@ class JingleContent(object):
|
||||||
cand.priority = int(candidate['priority'])
|
cand.priority = int(candidate['priority'])
|
||||||
|
|
||||||
if candidate['protocol'] == 'udp':
|
if candidate['protocol'] == 'udp':
|
||||||
cand.proto=farsight.NETWORK_PROTOCOL_UDP
|
cand.proto = farsight.NETWORK_PROTOCOL_UDP
|
||||||
else:
|
else:
|
||||||
# we actually don't handle properly different tcp options in jingle
|
# we actually don't handle properly different tcp options in jingle
|
||||||
cand.proto = farsight.NETWORK_PROTOCOL_TCP
|
cand.proto = farsight.NETWORK_PROTOCOL_TCP
|
||||||
|
@ -629,7 +626,7 @@ class JingleContent(object):
|
||||||
farsight.CANDIDATE_TYPE_PRFLX: 'prlfx',
|
farsight.CANDIDATE_TYPE_PRFLX: 'prlfx',
|
||||||
farsight.CANDIDATE_TYPE_RELAY: 'relay',
|
farsight.CANDIDATE_TYPE_RELAY: 'relay',
|
||||||
farsight.CANDIDATE_TYPE_MULTICAST: 'multicast'}
|
farsight.CANDIDATE_TYPE_MULTICAST: 'multicast'}
|
||||||
attrs={
|
attrs = {
|
||||||
'component': candidate.component_id,
|
'component': candidate.component_id,
|
||||||
'foundation': '1', # hack
|
'foundation': '1', # hack
|
||||||
'generation': '0',
|
'generation': '0',
|
||||||
|
@ -640,26 +637,27 @@ class JingleContent(object):
|
||||||
}
|
}
|
||||||
if candidate.type in types:
|
if candidate.type in types:
|
||||||
attrs['type'] = types[candidate.type]
|
attrs['type'] = types[candidate.type]
|
||||||
if candidate.proto==farsight.NETWORK_PROTOCOL_UDP:
|
if candidate.proto == farsight.NETWORK_PROTOCOL_UDP:
|
||||||
attrs['protocol'] = 'udp'
|
attrs['protocol'] = 'udp'
|
||||||
else:
|
else:
|
||||||
# we actually don't handle properly different tcp options in jingle
|
# we actually don't handle properly different tcp options in jingle
|
||||||
attrs['protocol'] = 'tcp'
|
attrs['protocol'] = 'tcp'
|
||||||
return xmpp.Node('candidate', attrs=attrs)
|
return xmpp.Node('candidate', attrs=attrs)
|
||||||
|
|
||||||
def iterCandidates(self):
|
def iter_candidates(self):
|
||||||
for candidate in self.candidates:
|
for candidate in self.candidates:
|
||||||
yield self.__candidate(candidate)
|
yield self.__candidate(candidate)
|
||||||
|
|
||||||
def send_candidate(self, candidate):
|
def send_candidate(self, candidate):
|
||||||
c = self.__content()
|
content = self.__content()
|
||||||
t = c.addChild(xmpp.NS_JINGLE_ICE_UDP + ' transport')
|
transport = content.addChild(xmpp.NS_JINGLE_ICE_UDP + ' transport')
|
||||||
|
|
||||||
if candidate.username: t['ufrag'] = candidate.username
|
if candidate.username and candidate.password:
|
||||||
if candidate.password: t['pwd'] = candidate.password
|
transport['ufrag'] = candidate.username
|
||||||
|
transport['pwd'] = candidate.password
|
||||||
|
|
||||||
t.addChild(node=self.__candidate(candidate))
|
transport.addChild(node=self.__candidate(candidate))
|
||||||
self.session.sendTransportInfo(c)
|
self.session.send_transport_info(content)
|
||||||
|
|
||||||
def __fillJingleStanza(self, stanza, content, error, action):
|
def __fillJingleStanza(self, stanza, content, error, action):
|
||||||
''' Add our things to session-initiate stanza. '''
|
''' Add our things to session-initiate stanza. '''
|
||||||
|
@ -672,7 +670,7 @@ class JingleContent(object):
|
||||||
else:
|
else:
|
||||||
attrs = {}
|
attrs = {}
|
||||||
content.addChild(xmpp.NS_JINGLE_ICE_UDP + ' transport', attrs=attrs,
|
content.addChild(xmpp.NS_JINGLE_ICE_UDP + ' transport', attrs=attrs,
|
||||||
payload=self.iterCandidates())
|
payload=self.iter_candidates())
|
||||||
|
|
||||||
class JingleRTPContent(JingleContent):
|
class JingleRTPContent(JingleContent):
|
||||||
def __init__(self, session, media, node=None):
|
def __init__(self, session, media, node=None):
|
||||||
|
@ -690,7 +688,7 @@ class JingleRTPContent(JingleContent):
|
||||||
self.callbacks['session-terminate'] += [self.__stop]
|
self.callbacks['session-terminate'] += [self.__stop]
|
||||||
self.callbacks['session-terminate-sent'] += [self.__stop]
|
self.callbacks['session-terminate-sent'] += [self.__stop]
|
||||||
|
|
||||||
def setupStream(self):
|
def setup_stream(self):
|
||||||
# pipeline and bus
|
# pipeline and bus
|
||||||
self.pipeline = gst.Pipeline()
|
self.pipeline = gst.Pipeline()
|
||||||
bus = self.pipeline.get_bus()
|
bus = self.pipeline.get_bus()
|
||||||
|
@ -714,7 +712,7 @@ class JingleRTPContent(JingleContent):
|
||||||
|
|
||||||
def _fillContent(self, content):
|
def _fillContent(self, content):
|
||||||
content.addChild(xmpp.NS_JINGLE_RTP + ' description',
|
content.addChild(xmpp.NS_JINGLE_RTP + ' description',
|
||||||
attrs={'media': self.media}, payload=self.iterCodecs())
|
attrs={'media': self.media}, payload=self.iter_codecs())
|
||||||
|
|
||||||
def _on_gst_message(self, bus, message):
|
def _on_gst_message(self, bus, message):
|
||||||
if message.type == gst.MESSAGE_ELEMENT:
|
if message.type == gst.MESSAGE_ELEMENT:
|
||||||
|
@ -725,12 +723,12 @@ class JingleRTPContent(JingleContent):
|
||||||
elif name == 'farsight-recv-codecs-changed':
|
elif name == 'farsight-recv-codecs-changed':
|
||||||
pass
|
pass
|
||||||
elif name == 'farsight-codecs-changed':
|
elif name == 'farsight-codecs-changed':
|
||||||
self.session.acceptSession()
|
self.session.accept_session()
|
||||||
self.session.startSession()
|
self.session.start_session()
|
||||||
elif name == 'farsight-local-candidates-prepared':
|
elif name == 'farsight-local-candidates-prepared':
|
||||||
self.candidates_ready = True
|
self.candidates_ready = True
|
||||||
self.session.acceptSession()
|
self.session.accept_session()
|
||||||
self.session.startSession()
|
self.session.start_session()
|
||||||
elif name == 'farsight-new-local-candidate':
|
elif name == 'farsight-new-local-candidate':
|
||||||
candidate = message.structure['candidate']
|
candidate = message.structure['candidate']
|
||||||
self.candidates.append(candidate)
|
self.candidates.append(candidate)
|
||||||
|
@ -746,8 +744,8 @@ class JingleRTPContent(JingleContent):
|
||||||
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH)
|
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH)
|
||||||
self.session.content_negociated(self.media)
|
self.session.content_negociated(self.media)
|
||||||
#if not self.session.weinitiate: #FIXME: one more FIXME...
|
#if not self.session.weinitiate: #FIXME: one more FIXME...
|
||||||
# self.session.sendContentAccept(self.__content((xmpp.Node(
|
# self.session.send_content_accept(self.__content((xmpp.Node(
|
||||||
# 'description', payload=self.iterCodecs()),)))
|
# 'description', payload=self.iter_codecs()),)))
|
||||||
elif name == 'farsight-error':
|
elif name == 'farsight-error':
|
||||||
print 'Farsight error #%d!' % message.structure['error-no']
|
print 'Farsight error #%d!' % message.structure['error-no']
|
||||||
print 'Message: %s' % message.structure['error-msg']
|
print 'Message: %s' % message.structure['error-msg']
|
||||||
|
@ -757,7 +755,8 @@ class JingleRTPContent(JingleContent):
|
||||||
|
|
||||||
def __getRemoteCodecsCB(self, stanza, content, error, action):
|
def __getRemoteCodecsCB(self, stanza, content, error, action):
|
||||||
''' Get peer codecs from what we get from peer. '''
|
''' Get peer codecs from what we get from peer. '''
|
||||||
if self.got_codecs: return
|
if self.got_codecs:
|
||||||
|
return
|
||||||
|
|
||||||
codecs = []
|
codecs = []
|
||||||
for codec in content.getTag('description').iterTags('payload-type'):
|
for codec in content.getTag('description').iterTags('payload-type'):
|
||||||
|
@ -770,26 +769,27 @@ class JingleRTPContent(JingleContent):
|
||||||
c.optional_params = [(str(p['name']), str(p['value'])) for p in \
|
c.optional_params = [(str(p['name']), str(p['value'])) for p in \
|
||||||
codec.iterTags('parameter')]
|
codec.iterTags('parameter')]
|
||||||
codecs.append(c)
|
codecs.append(c)
|
||||||
if len(codecs) == 0: return
|
|
||||||
|
|
||||||
#FIXME: Handle this case:
|
if len(codecs) > 0:
|
||||||
# glib.GError: There was no intersection between the remote codecs and
|
#FIXME: Handle this case:
|
||||||
# the local ones
|
# glib.GError: There was no intersection between the remote codecs and
|
||||||
self.p2pstream.set_remote_codecs(codecs)
|
# the local ones
|
||||||
self.got_codecs = True
|
self.p2pstream.set_remote_codecs(codecs)
|
||||||
|
self.got_codecs = True
|
||||||
|
|
||||||
def iterCodecs(self):
|
def iter_codecs(self):
|
||||||
codecs=self.p2psession.get_property('codecs')
|
codecs = self.p2psession.get_property('codecs')
|
||||||
for codec in codecs:
|
for codec in codecs:
|
||||||
a = {'name': codec.encoding_name,
|
attrs = {'name': codec.encoding_name,
|
||||||
'id': codec.id,
|
'id': codec.id,
|
||||||
'channels': codec.channels}
|
'channels': codec.channels}
|
||||||
if codec.clock_rate: a['clockrate']=codec.clock_rate
|
if codec.clock_rate:
|
||||||
|
attrs['clockrate'] = codec.clock_rate
|
||||||
if codec.optional_params:
|
if codec.optional_params:
|
||||||
p = (xmpp.Node('parameter', {'name': name, 'value': value})
|
payload = (xmpp.Node('parameter', {'name': name, 'value': value})
|
||||||
for name, value in codec.optional_params)
|
for name, value in codec.optional_params)
|
||||||
else: p = ()
|
else: payload = ()
|
||||||
yield xmpp.Node('payload-type', a, p)
|
yield xmpp.Node('payload-type', attrs, payload)
|
||||||
|
|
||||||
def __stop(self, *things):
|
def __stop(self, *things):
|
||||||
self.pipeline.set_state(gst.STATE_NULL)
|
self.pipeline.set_state(gst.STATE_NULL)
|
||||||
|
@ -803,12 +803,12 @@ class JingleVoIP(JingleRTPContent):
|
||||||
over an ICE UDP protocol. '''
|
over an ICE UDP protocol. '''
|
||||||
def __init__(self, session, node=None):
|
def __init__(self, session, node=None):
|
||||||
JingleRTPContent.__init__(self, session, 'audio', node)
|
JingleRTPContent.__init__(self, session, 'audio', node)
|
||||||
self.setupStream()
|
self.setup_stream()
|
||||||
|
|
||||||
|
|
||||||
''' Things to control the gstreamer's pipeline '''
|
''' Things to control the gstreamer's pipeline '''
|
||||||
def setupStream(self):
|
def setup_stream(self):
|
||||||
JingleRTPContent.setupStream(self)
|
JingleRTPContent.setup_stream(self)
|
||||||
|
|
||||||
# Configure SPEEX
|
# Configure SPEEX
|
||||||
#FIXME: codec ID is an important thing for psi (and pidgin?)
|
#FIXME: codec ID is an important thing for psi (and pidgin?)
|
||||||
|
@ -858,14 +858,14 @@ class JingleVoIP(JingleRTPContent):
|
||||||
class JingleVideo(JingleRTPContent):
|
class JingleVideo(JingleRTPContent):
|
||||||
def __init__(self, session, node=None):
|
def __init__(self, session, node=None):
|
||||||
JingleRTPContent.__init__(self, session, 'video', node)
|
JingleRTPContent.__init__(self, session, 'video', node)
|
||||||
self.setupStream()
|
self.setup_stream()
|
||||||
|
|
||||||
''' Things to control the gstreamer's pipeline '''
|
''' Things to control the gstreamer's pipeline '''
|
||||||
def setupStream(self):
|
def setup_stream(self):
|
||||||
#TODO: Everything is not working properly:
|
#TODO: Everything is not working properly:
|
||||||
# sometimes, one window won't show up,
|
# sometimes, one window won't show up,
|
||||||
# sometimes it'll freeze...
|
# sometimes it'll freeze...
|
||||||
JingleRTPContent.setupStream(self)
|
JingleRTPContent.setup_stream(self)
|
||||||
# the local parts
|
# the local parts
|
||||||
src_vid = gst.element_factory_make('v4l2src')
|
src_vid = gst.element_factory_make('v4l2src')
|
||||||
videoscale = gst.element_factory_make('videoscale')
|
videoscale = gst.element_factory_make('videoscale')
|
||||||
|
@ -904,13 +904,13 @@ class ConnectionJingle(object):
|
||||||
# one time callbacks
|
# one time callbacks
|
||||||
self.__iq_responses = {}
|
self.__iq_responses = {}
|
||||||
|
|
||||||
def addJingle(self, jingle):
|
def add_jingle(self, jingle):
|
||||||
''' Add a jingle session to a jingle stanza dispatcher
|
''' Add a jingle session to a jingle stanza dispatcher
|
||||||
jingle - a JingleSession object.
|
jingle - a JingleSession object.
|
||||||
'''
|
'''
|
||||||
self.__sessions[(jingle.peerjid, jingle.sid)] = jingle
|
self.__sessions[(jingle.peerjid, jingle.sid)] = jingle
|
||||||
|
|
||||||
def deleteJingle(self, jingle):
|
def delete_jingle(self, jingle):
|
||||||
''' Remove a jingle session from a jingle stanza dispatcher '''
|
''' Remove a jingle session from a jingle stanza dispatcher '''
|
||||||
del self.__sessions[(jingle.peerjid, jingle.sid)]
|
del self.__sessions[(jingle.peerjid, jingle.sid)]
|
||||||
|
|
||||||
|
@ -937,24 +937,21 @@ class ConnectionJingle(object):
|
||||||
# do we need to create a new jingle object
|
# do we need to create a new jingle object
|
||||||
if (jid, sid) not in self.__sessions:
|
if (jid, sid) not in self.__sessions:
|
||||||
newjingle = JingleSession(con=self, weinitiate=False, jid=jid, sid=sid)
|
newjingle = JingleSession(con=self, weinitiate=False, jid=jid, sid=sid)
|
||||||
self.addJingle(newjingle)
|
self.add_jingle(newjingle)
|
||||||
|
|
||||||
# we already have such session in dispatcher...
|
# we already have such session in dispatcher...
|
||||||
self.__sessions[(jid, sid)].stanzaCB(stanza)
|
self.__sessions[(jid, sid)].stanzaCB(stanza)
|
||||||
|
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def addJingleIqCallback(self, jid, id, jingle):
|
|
||||||
self.__iq_responses[(jid, id)] = jingle
|
|
||||||
|
|
||||||
def startVoIP(self, jid):
|
def startVoIP(self, jid):
|
||||||
jingle = JingleSession(self, weinitiate=True, jid=jid)
|
jingle = JingleSession(self, weinitiate=True, jid=jid)
|
||||||
self.addJingle(jingle)
|
self.add_jingle(jingle)
|
||||||
jingle.addContent('voice', JingleVoIP(jingle))
|
jingle.add_content('voice', JingleVoIP(jingle))
|
||||||
jingle.startSession()
|
jingle.start_session()
|
||||||
return jingle.sid
|
return jingle.sid
|
||||||
|
|
||||||
def getJingleSession(self, jid, sid):
|
def get_jingle_session(self, jid, sid):
|
||||||
try:
|
try:
|
||||||
return self.__sessions[(jid, sid)]
|
return self.__sessions[(jid, sid)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
|
@ -4470,10 +4470,10 @@ class VoIPCallReceivedDialog(object):
|
||||||
|
|
||||||
def on_voip_call_received_messagedialog_response(self, dialog, response):
|
def on_voip_call_received_messagedialog_response(self, dialog, response):
|
||||||
# we've got response from user, either stop connecting or accept the call
|
# we've got response from user, either stop connecting or accept the call
|
||||||
session = gajim.connections[self.account].getJingleSession(self.fjid,
|
session = gajim.connections[self.account].get_jingle_session(self.fjid,
|
||||||
self.sid)
|
self.sid)
|
||||||
if response==gtk.RESPONSE_YES:
|
if response==gtk.RESPONSE_YES:
|
||||||
session.approveSession()
|
session.approve_session()
|
||||||
jid = gajim.get_jid_without_resource(self.fjid)
|
jid = gajim.get_jid_without_resource(self.fjid)
|
||||||
resource = gajim.get_resource_from_jid(self.fjid)
|
resource = gajim.get_resource_from_jid(self.fjid)
|
||||||
ctrl = gajim.interface.msg_win_mgr.get_control(self.fjid, self.account)
|
ctrl = gajim.interface.msg_win_mgr.get_control(self.fjid, self.account)
|
||||||
|
@ -4489,7 +4489,7 @@ class VoIPCallReceivedDialog(object):
|
||||||
ctrl = gajim.interface.new_chat(contact, self.account)
|
ctrl = gajim.interface.new_chat(contact, self.account)
|
||||||
ctrl.set_audio_state('connecting', self.sid)
|
ctrl.set_audio_state('connecting', self.sid)
|
||||||
else: # response==gtk.RESPONSE_NO
|
else: # response==gtk.RESPONSE_NO
|
||||||
session.declineSession()
|
session.decline_session()
|
||||||
|
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue