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