New class for video sessions, added an end_session method, and minor changes
This commit is contained in:
parent
8b4cd1b368
commit
163b01e113
4 changed files with 71 additions and 25 deletions
|
@ -198,7 +198,7 @@ gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE,
|
||||||
'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
|
'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
|
||||||
xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX,
|
xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX,
|
||||||
xmpp.NS_JINGLE, xmpp.NS_JINGLE_RTP, xmpp.NS_JINGLE_RTP_AUDIO,
|
xmpp.NS_JINGLE, xmpp.NS_JINGLE_RTP, xmpp.NS_JINGLE_RTP_AUDIO,
|
||||||
xmpp.NS_JINGLE_ICE_UDP]
|
xmpp.NS_JINGLE_RTP_VIDEO, xmpp.NS_JINGLE_ICE_UDP]
|
||||||
|
|
||||||
# Optional features gajim supports per account
|
# Optional features gajim supports per account
|
||||||
gajim_optional_features = {}
|
gajim_optional_features = {}
|
||||||
|
|
|
@ -148,6 +148,14 @@ class JingleSession(object):
|
||||||
reason.addChild('decline')
|
reason.addChild('decline')
|
||||||
self.__sessionTerminate(reason)
|
self.__sessionTerminate(reason)
|
||||||
|
|
||||||
|
def end_session(self):
|
||||||
|
reason = xmpp.Node('reason')
|
||||||
|
if self.state == JingleStates.active:
|
||||||
|
reason.addChild('success')
|
||||||
|
else:
|
||||||
|
reason.addChild('abort')
|
||||||
|
self.__sessionTerminate(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 addContent(self, name, content, creator='we'):
|
||||||
|
@ -337,12 +345,15 @@ class JingleSession(object):
|
||||||
desc_ns = element.getTag('description').getNamespace()
|
desc_ns = element.getTag('description').getNamespace()
|
||||||
media = element.getTag('description')['media']
|
media = element.getTag('description')['media']
|
||||||
tran_ns = element.getTag('transport').getNamespace()
|
tran_ns = element.getTag('transport').getNamespace()
|
||||||
if desc_ns == xmpp.NS_JINGLE_RTP and media == 'audio':
|
if desc_ns == xmpp.NS_JINGLE_RTP and media in ('audio', 'video'):
|
||||||
contents_ok = True
|
contents_ok = True
|
||||||
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
|
||||||
self.addContent(element['name'], JingleVoIP(self), 'peer')
|
if media == 'audio':
|
||||||
contents.append(('VOIP',))
|
self.addContent(element['name'], JingleVoIP(self), 'peer')
|
||||||
|
else:
|
||||||
|
self.addContent(element['name'], JingleVideo(self), 'peer')
|
||||||
|
contents.append((media,))
|
||||||
transports_ok = True
|
transports_ok = True
|
||||||
|
|
||||||
# If there's no content we understand...
|
# If there's no content we understand...
|
||||||
|
@ -600,6 +611,8 @@ class JingleRTPContent(JingleContent):
|
||||||
def __init__(self, session, media, node=None):
|
def __init__(self, session, media, node=None):
|
||||||
JingleContent.__init__(self, session, node)
|
JingleContent.__init__(self, session, node)
|
||||||
self.media = media
|
self.media = media
|
||||||
|
self.farsight_media = {'audio': farsight.MEDIA_TYPE_AUDIO,
|
||||||
|
'video': farsight.MEDIA_TYPE_VIDEO}[media]
|
||||||
self.got_codecs = False
|
self.got_codecs = False
|
||||||
|
|
||||||
self.callbacks['content-accept'] += [self.__getRemoteCodecsCB]
|
self.callbacks['content-accept'] += [self.__getRemoteCodecsCB]
|
||||||
|
@ -621,6 +634,15 @@ class JingleRTPContent(JingleContent):
|
||||||
self.pipeline.add(self.conference)
|
self.pipeline.add(self.conference)
|
||||||
self.funnel = None
|
self.funnel = None
|
||||||
|
|
||||||
|
self.p2psession = self.conference.new_session(self.farsight_media)
|
||||||
|
|
||||||
|
participant = self.conference.new_participant(self.session.peerjid)
|
||||||
|
params = {'controlling-mode': self.session.weinitiate,# 'debug': False}
|
||||||
|
'stun-ip': '69.0.208.27', 'debug': False}
|
||||||
|
|
||||||
|
self.p2pstream = self.p2psession.new_stream(participant,
|
||||||
|
farsight.DIRECTION_RECV, 'nice', params)
|
||||||
|
|
||||||
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.iterCodecs())
|
||||||
|
@ -646,7 +668,7 @@ class JingleRTPContent(JingleContent):
|
||||||
elif name == 'farsight-component-state-changed':
|
elif name == 'farsight-component-state-changed':
|
||||||
state = message.structure['state']
|
state = message.structure['state']
|
||||||
print message.structure['component'], state
|
print message.structure['component'], state
|
||||||
if state==farsight.STREAM_STATE_CONNECTED:
|
if state==farsight.STREAM_STATE_READY:
|
||||||
self.negotiated = True
|
self.negotiated = True
|
||||||
#TODO: farsight.DIRECTION_BOTH only if senders='both'
|
#TODO: farsight.DIRECTION_BOTH only if senders='both'
|
||||||
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH)
|
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH)
|
||||||
|
@ -667,7 +689,7 @@ class JingleRTPContent(JingleContent):
|
||||||
codecs = []
|
codecs = []
|
||||||
for codec in content.getTag('description').iterTags('payload-type'):
|
for codec in content.getTag('description').iterTags('payload-type'):
|
||||||
c = farsight.Codec(int(codec['id']), codec['name'],
|
c = farsight.Codec(int(codec['id']), codec['name'],
|
||||||
farsight.MEDIA_TYPE_AUDIO, int(codec['clockrate']))
|
self.farsight_media, int(codec['clockrate']))
|
||||||
if 'channels' in codec:
|
if 'channels' in codec:
|
||||||
c.channels = int(codec['channels'])
|
c.channels = int(codec['channels'])
|
||||||
else:
|
else:
|
||||||
|
@ -709,8 +731,6 @@ class JingleVoIP(JingleRTPContent):
|
||||||
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.got_codecs = False
|
|
||||||
|
|
||||||
self.setupStream()
|
self.setupStream()
|
||||||
|
|
||||||
|
|
||||||
|
@ -718,13 +738,6 @@ class JingleVoIP(JingleRTPContent):
|
||||||
def setupStream(self):
|
def setupStream(self):
|
||||||
JingleRTPContent.setupStream(self)
|
JingleRTPContent.setupStream(self)
|
||||||
|
|
||||||
# the network part
|
|
||||||
participant = self.conference.new_participant(self.session.peerjid)
|
|
||||||
params = {'controlling-mode': self.session.weinitiate,# 'debug': False}
|
|
||||||
'stun-ip': '69.0.208.27', 'debug': False}
|
|
||||||
|
|
||||||
self.p2psession = self.conference.new_session(farsight.MEDIA_TYPE_AUDIO)
|
|
||||||
|
|
||||||
# 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?)
|
||||||
# So, if it doesn't work with pidgin or psi, LOOK AT THIS
|
# So, if it doesn't work with pidgin or psi, LOOK AT THIS
|
||||||
|
@ -734,9 +747,6 @@ class JingleVoIP(JingleRTPContent):
|
||||||
farsight.MEDIA_TYPE_AUDIO, 16000)]
|
farsight.MEDIA_TYPE_AUDIO, 16000)]
|
||||||
self.p2psession.set_codec_preferences(codecs)
|
self.p2psession.set_codec_preferences(codecs)
|
||||||
|
|
||||||
self.p2pstream = self.p2psession.new_stream(participant,
|
|
||||||
farsight.DIRECTION_RECV, 'nice', params)
|
|
||||||
|
|
||||||
# the local parts
|
# the local parts
|
||||||
# TODO: use gconfaudiosink?
|
# TODO: use gconfaudiosink?
|
||||||
# sink = get_first_gst_element(['alsasink', 'osssink', 'autoaudiosink'])
|
# sink = get_first_gst_element(['alsasink', 'osssink', 'autoaudiosink'])
|
||||||
|
@ -744,19 +754,17 @@ class JingleVoIP(JingleRTPContent):
|
||||||
sink.set_property('sync', False)
|
sink.set_property('sync', False)
|
||||||
#sink.set_property('latency-time', 20000)
|
#sink.set_property('latency-time', 20000)
|
||||||
#sink.set_property('buffer-time', 80000)
|
#sink.set_property('buffer-time', 80000)
|
||||||
self.pipeline.add(sink)
|
|
||||||
|
|
||||||
# TODO: use gconfaudiosrc?
|
# TODO: use gconfaudiosrc?
|
||||||
self.src_mic = gst.element_factory_make('alsasrc')
|
src_mic = gst.element_factory_make('alsasrc')
|
||||||
self.src_mic.set_property('blocksize', 320)
|
src_mic.set_property('blocksize', 320)
|
||||||
self.pipeline.add(self.src_mic)
|
|
||||||
|
|
||||||
self.mic_volume = gst.element_factory_make('volume')
|
self.mic_volume = gst.element_factory_make('volume')
|
||||||
self.mic_volume.set_property('volume', 1)
|
self.mic_volume.set_property('volume', 1)
|
||||||
self.pipeline.add(self.mic_volume)
|
|
||||||
|
|
||||||
# link gst elements
|
# link gst elements
|
||||||
self.src_mic.link(self.mic_volume)
|
self.pipeline.add(sink, src_mic, self.mic_volume)
|
||||||
|
src_mic.link(self.mic_volume)
|
||||||
|
|
||||||
def src_pad_added (stream, pad, codec):
|
def src_pad_added (stream, pad, codec):
|
||||||
if not self.funnel:
|
if not self.funnel:
|
||||||
|
@ -774,6 +782,43 @@ class JingleVoIP(JingleRTPContent):
|
||||||
# The following is needed for farsight to process ICE requests:
|
# The following is needed for farsight to process ICE requests:
|
||||||
self.pipeline.set_state(gst.STATE_PLAYING)
|
self.pipeline.set_state(gst.STATE_PLAYING)
|
||||||
|
|
||||||
|
class JingleVideo(JingleRTPContent):
|
||||||
|
def __init__(self, session, node=None):
|
||||||
|
JingleRTPContent.__init__(self, session, 'video', node)
|
||||||
|
self.setupStream()
|
||||||
|
|
||||||
|
''' Things to control the gstreamer's pipeline '''
|
||||||
|
def setupStream(self):
|
||||||
|
#TODO: Everything is not working properly:
|
||||||
|
# sometimes, one window won't show up,
|
||||||
|
# sometimes it'll freeze...
|
||||||
|
JingleRTPContent.setupStream(self)
|
||||||
|
# the local parts
|
||||||
|
src_vid = gst.element_factory_make('videotestsrc')
|
||||||
|
videoscale = gst.element_factory_make('videoscale')
|
||||||
|
caps = gst.element_factory_make('capsfilter')
|
||||||
|
caps.set_property('caps', gst.caps_from_string('video/x-raw-yuv, width=320, height=240'))
|
||||||
|
colorspace = gst.element_factory_make('ffmpegcolorspace')
|
||||||
|
|
||||||
|
self.pipeline.add(src_vid, videoscale, caps, colorspace)
|
||||||
|
gst.element_link_many(src_vid, videoscale, caps, colorspace)
|
||||||
|
|
||||||
|
def src_pad_added (stream, pad, codec):
|
||||||
|
if not self.funnel:
|
||||||
|
self.funnel = gst.element_factory_make('fsfunnel')
|
||||||
|
self.pipeline.add(self.funnel)
|
||||||
|
videosink = gst.element_factory_make('xvimagesink')
|
||||||
|
self.pipeline.add(videosink)
|
||||||
|
self.funnel.set_state (gst.STATE_PLAYING)
|
||||||
|
videosink.set_state(gst.STATE_PLAYING)
|
||||||
|
self.funnel.link(videosink)
|
||||||
|
pad.link(self.funnel.get_pad('sink%d'))
|
||||||
|
|
||||||
|
colorspace.get_pad('src').link(self.p2psession.get_property('sink-pad'))
|
||||||
|
self.p2pstream.connect('src-pad-added', src_pad_added)
|
||||||
|
|
||||||
|
# The following is needed for farsight to process ICE requests:
|
||||||
|
self.pipeline.set_state(gst.STATE_PLAYING)
|
||||||
|
|
||||||
class ConnectionJingle(object):
|
class ConnectionJingle(object):
|
||||||
''' This object depends on that it is a part of Connection class. '''
|
''' This object depends on that it is a part of Connection class. '''
|
||||||
|
|
|
@ -67,6 +67,7 @@ NS_JINGLE ='urn:xmpp:jingle:1' # XEP-01
|
||||||
NS_JINGLE_ERRORS='urn:xmpp:jingle:errors:1' # XEP-0166
|
NS_JINGLE_ERRORS='urn:xmpp:jingle:errors:1' # XEP-0166
|
||||||
NS_JINGLE_RTP ='urn:xmpp:jingle:apps:rtp:1' # XEP-0167
|
NS_JINGLE_RTP ='urn:xmpp:jingle:apps:rtp:1' # XEP-0167
|
||||||
NS_JINGLE_RTP_AUDIO='urn:xmpp:jingle:apps:rtp:audio' # XEP-0167
|
NS_JINGLE_RTP_AUDIO='urn:xmpp:jingle:apps:rtp:audio' # XEP-0167
|
||||||
|
NS_JINGLE_RTP_VIDEO='urn:xmpp:jingle:apps:rtp:video' # XEP-0167
|
||||||
NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177
|
NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177
|
||||||
NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176
|
NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176
|
||||||
NS_LAST ='jabber:iq:last'
|
NS_LAST ='jabber:iq:last'
|
||||||
|
|
|
@ -2087,7 +2087,7 @@ class Interface:
|
||||||
content_types = set(c[0] for c in contents)
|
content_types = set(c[0] for c in contents)
|
||||||
|
|
||||||
# check type of jingle session
|
# check type of jingle session
|
||||||
if 'VOIP' in content_types:
|
if 'audio' in content_types or 'video' in content_types:
|
||||||
# a voip session...
|
# a voip session...
|
||||||
# we now handle only voip, so the only thing we will do here is
|
# we now handle only voip, so the only thing we will do here is
|
||||||
# not to return from function
|
# not to return from function
|
||||||
|
|
Loading…
Add table
Reference in a new issue