[Olivier Crete] port Gajim to use Farstream instead of Farsight2. Fixes #7113

This commit is contained in:
Yann Leboulanger 2012-04-01 19:49:52 +02:00
parent aec9f53c2d
commit e1808fd550
9 changed files with 72 additions and 75 deletions

View File

@ -1,7 +1,7 @@
gajim for Debian gajim for Debian
---------------- ----------------
For video chat support, you have to install python-farsight. For video chat support, you have to install python-farstream.
-- Yann Le Boulanger <asterix@lagaule.org>, Mon, 20 Jun 2005 12:02:31 +0200 -- Yann Le Boulanger <asterix@lagaule.org>, Mon, 20 Jun 2005 12:02:31 +0200
-- Julien Valroff <julien@debian.org> Sat, 07 May 2011 13:50:27 +0200 -- Julien Valroff <julien@debian.org> Sat, 07 May 2011 13:50:27 +0200

2
debian/control vendored
View File

@ -12,7 +12,7 @@ Package: gajim
Architecture: all Architecture: all
Depends: ${misc:Depends}, ${python:Depends}, python-gtk2 (>= 2.16.0), dnsutils Depends: ${misc:Depends}, ${python:Depends}, python-gtk2 (>= 2.16.0), dnsutils
Recommends: dbus, python-dbus, notification-daemon, python-openssl (>= 0.12), python-crypto, python-pyasn1 Recommends: dbus, python-dbus, notification-daemon, python-openssl (>= 0.12), python-crypto, python-pyasn1
Suggests: python-gconf, python-gnome2, nautilus-sendto, avahi-daemon, python-avahi, network-manager, libgtkspell0, aspell-en, python-gnomekeyring, gnome-keyring, python-kerberos (>= 1.1), texlive-latex-base, dvipng, python-farsight, gstreamer0.10-plugins-ugly, python-pycurl Suggests: python-gconf, python-gnome2, nautilus-sendto, avahi-daemon, python-avahi, network-manager, libgtkspell0, aspell-en, python-gnomekeyring, gnome-keyring, python-kerberos (>= 1.1), texlive-latex-base, dvipng, python-farstream, gstreamer0.10-plugins-ugly, python-pycurl
Description: Jabber client written in PyGTK Description: Jabber client written in PyGTK
Gajim is a Jabber client. It has a tabbed user interface with normal chats, Gajim is a Jabber client. It has a tabbed user interface with normal chats,
group chats, and has many features such as, TLS, GPG, SSL, multiple accounts, group chats, and has many features such as, TLS, GPG, SSL, multiple accounts,

View File

@ -1649,15 +1649,15 @@ class ChatControl(ChatControlBase):
self.restore_conversation() self.restore_conversation()
self.msg_textview.grab_focus() self.msg_textview.grab_focus()
# change tooltip text for audio and video buttons if python-farsight is # change tooltip text for audio and video buttons if python-farstream is
# not installed # not installed
if not gajim.HAVE_FARSIGHT: if not gajim.HAVE_FARSTREAM:
tooltip_text = self._audio_button.get_tooltip_text() tooltip_text = self._audio_button.get_tooltip_text()
self._audio_button.set_tooltip_text( self._audio_button.set_tooltip_text(
'%s\n%s' % (tooltip_text, _('Requires python-farsight.'))) '%s\n%s' % (tooltip_text, _('Requires python-farstream.')))
tooltip_text = self._video_button.get_tooltip_text() tooltip_text = self._video_button.get_tooltip_text()
self._video_button.set_tooltip_text( self._video_button.set_tooltip_text(
'%s\n%s' % (tooltip_text, _('Requires python-farsight.'))) '%s\n%s' % (tooltip_text, _('Requires python-farstream.')))
gajim.ged.register_event_handler('pep-received', ged.GUI1, gajim.ged.register_event_handler('pep-received', ged.GUI1,
self._nec_pep_received) self._nec_pep_received)
@ -1705,7 +1705,7 @@ class ChatControl(ChatControlBase):
# Jingle detection # Jingle detection
if self.contact.supports(NS_JINGLE_ICE_UDP) and \ if self.contact.supports(NS_JINGLE_ICE_UDP) and \
gajim.HAVE_FARSIGHT and self.contact.resource: gajim.HAVE_FARSTREAM and self.contact.resource:
self.audio_available = self.contact.supports(NS_JINGLE_RTP_AUDIO) self.audio_available = self.contact.supports(NS_JINGLE_RTP_AUDIO)
self.video_available = self.contact.supports(NS_JINGLE_RTP_VIDEO) self.video_available = self.contact.supports(NS_JINGLE_RTP_VIDEO)
else: else:

View File

@ -169,21 +169,21 @@ else:
# read. # read.
HAVE_LATEX = False HAVE_LATEX = False
HAVE_FARSIGHT = True HAVE_FARSTREAM = True
try: try:
farsight = __import__('farsight') farstream = __import__('farstream')
import gst import gst
import glib import glib
try: try:
conference = gst.element_factory_make('fsrtpconference') conference = gst.element_factory_make('fsrtpconference')
session = conference.new_session(farsight.MEDIA_TYPE_AUDIO) session = conference.new_session(farstream.MEDIA_TYPE_AUDIO)
del session del session
del conference del conference
except glib.GError: except glib.GError:
HAVE_FARSIGHT = False HAVE_FARSTREAM = False
except ImportError: except ImportError:
HAVE_FARSIGHT = False HAVE_FARSTREAM = False
HAVE_UPNP_IGD = True HAVE_UPNP_IGD = True
try: try:

View File

@ -1330,7 +1330,7 @@ def update_optional_features(account = None):
gajim.gajim_optional_features[a].append(xmpp.NS_ESESSION) gajim.gajim_optional_features[a].append(xmpp.NS_ESESSION)
if gajim.config.get_per('accounts', a, 'answer_receipts'): if gajim.config.get_per('accounts', a, 'answer_receipts'):
gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS) gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS)
if gajim.HAVE_FARSIGHT: if gajim.HAVE_FARSTREAM:
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE) gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP) gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP_AUDIO) gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP_AUDIO)

View File

@ -35,7 +35,7 @@ import helpers
import gajim import gajim
from jingle_session import JingleSession, JingleStates from jingle_session import JingleSession, JingleStates
if gajim.HAVE_FARSIGHT: if gajim.HAVE_FARSTREAM:
from jingle_rtp import JingleAudio, JingleVideo from jingle_rtp import JingleAudio, JingleVideo

View File

@ -21,7 +21,7 @@ import gobject
import socket import socket
import xmpp import xmpp
import farsight, gst import farstream, gst
from glib import GError from glib import GError
import gajim import gajim
@ -42,8 +42,8 @@ class JingleRTPContent(JingleContent):
JingleContent.__init__(self, session, transport) JingleContent.__init__(self, session, transport)
self.media = media self.media = media
self._dtmf_running = False self._dtmf_running = False
self.farsight_media = {'audio': farsight.MEDIA_TYPE_AUDIO, self.farstream_media = {'audio': farstream.MEDIA_TYPE_AUDIO,
'video': farsight.MEDIA_TYPE_VIDEO}[media] 'video': farstream.MEDIA_TYPE_VIDEO}[media]
self.pipeline = None self.pipeline = None
self.src_bin = None self.src_bin = None
@ -59,7 +59,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 setup_stream(self): def setup_stream(self, on_src_pad_added):
# pipeline and bus # pipeline and bus
self.pipeline = gst.Pipeline() self.pipeline = gst.Pipeline()
bus = self.pipeline.get_bus() bus = self.pipeline.get_bus()
@ -68,13 +68,12 @@ class JingleRTPContent(JingleContent):
# conference # conference
self.conference = gst.element_factory_make('fsrtpconference') self.conference = gst.element_factory_make('fsrtpconference')
self.conference.set_property('sdes-cname', self.session.ourjid)
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) self.p2psession = self.conference.new_session(self.farstream_media)
participant = self.conference.new_participant(self.session.peerjid) participant = self.conference.new_participant()
# FIXME: Consider a workaround, here... # FIXME: Consider a workaround, here...
# pidgin and telepathy-gabble don't follow the XEP, and it won't work # pidgin and telepathy-gabble don't follow the XEP, and it won't work
# due to bad controlling-mode # due to bad controlling-mode
@ -93,7 +92,9 @@ class JingleRTPContent(JingleContent):
params['stun-ip'] = ip params['stun-ip'] = ip
self.p2pstream = self.p2psession.new_stream(participant, self.p2pstream = self.p2psession.new_stream(participant,
farsight.DIRECTION_RECV, 'nice', params) farstream.DIRECTION_RECV)
self.p2pstream.connect('src-pad-added', on_src_pad_added)
self.p2pstream.set_transmitter('nice', params)
def is_ready(self): def is_ready(self):
return (JingleContent.is_ready(self) and self.candidates_ready) return (JingleContent.is_ready(self) and self.candidates_ready)
@ -117,7 +118,7 @@ class JingleRTPContent(JingleContent):
# FIXME: connectivity should not be etablished yet # FIXME: connectivity should not be etablished yet
# Instead, it should be etablished after session-accept! # Instead, it should be etablished after session-accept!
if self.sent: if self.sent:
self.p2pstream.set_remote_candidates(candidates) self.p2pstream.add_remote_candidates(candidates)
def batch_dtmf(self, events): def batch_dtmf(self, events):
""" """
@ -140,15 +141,14 @@ class JingleRTPContent(JingleContent):
def _start_dtmf(self, event): def _start_dtmf(self, event):
if event in ('*', '#'): if event in ('*', '#'):
event = {'*': farsight.DTMF_EVENT_STAR, event = {'*': farstream.DTMF_EVENT_STAR,
'#': farsight.DTMF_EVENT_POUND}[event] '#': farstream.DTMF_EVENT_POUND}[event]
else: else:
event = int(event) event = int(event)
self.p2psession.start_telephony_event(event, 2, self.p2psession.start_telephony_event(event, 2)
farsight.DTMF_METHOD_RTP_RFC4733)
def _stop_dtmf(self): def _stop_dtmf(self):
self.p2psession.stop_telephony_event(farsight.DTMF_METHOD_RTP_RFC4733) self.p2psession.stop_telephony_event()
def _fill_content(self, content): def _fill_content(self, content):
content.addChild(xmpp.NS_JINGLE_RTP + ' description', content.addChild(xmpp.NS_JINGLE_RTP + ' description',
@ -170,34 +170,33 @@ class JingleRTPContent(JingleContent):
if message.type == gst.MESSAGE_ELEMENT: if message.type == gst.MESSAGE_ELEMENT:
name = message.structure.get_name() name = message.structure.get_name()
log.debug('gst element message: %s: %s' % (name, message)) log.debug('gst element message: %s: %s' % (name, message))
if name == 'farsight-new-active-candidate-pair': if name == 'farstream-new-active-candidate-pair':
pass pass
elif name == 'farsight-recv-codecs-changed': elif name == 'farstream-recv-codecs-changed':
pass pass
elif name == 'farsight-codecs-changed': elif name == 'farstream-codecs-changed':
if self.sent and self.p2psession.get_property('codecs-ready'): if self.sent and self.p2psession.get_property('codecs'):
self.send_description_info() self.send_description_info()
elif name == 'farsight-local-candidates-prepared': elif name == 'farstream-local-candidates-prepared':
self.candidates_ready = True self.candidates_ready = True
if self.is_ready(): if self.is_ready():
self.session.on_session_state_changed(self) self.session.on_session_state_changed(self)
elif name == 'farsight-new-local-candidate': elif name == 'farstream-new-local-candidate':
candidate = message.structure['candidate'] candidate = message.structure['candidate']
self.transport.candidates.append(candidate) self.transport.candidates.append(candidate)
if self.sent: if self.sent:
# FIXME: Is this case even possible? # FIXME: Is this case even possible?
self.send_candidate(candidate) self.send_candidate(candidate)
elif name == 'farsight-component-state-changed': elif name == 'farstream-component-state-changed':
state = message.structure['state'] state = message.structure['state']
if state == farsight.STREAM_STATE_FAILED: if state == farstream.STREAM_STATE_FAILED:
reason = xmpp.Node('reason') reason = xmpp.Node('reason')
reason.setTag('failed-transport') reason.setTag('failed-transport')
self.session.remove_content(self.creator, self.name, reason) self.session.remove_content(self.creator, self.name, reason)
elif name == 'farsight-error': elif name == 'farstream-error':
log.error('Farsight error #%d!\nMessage: %s\nDebug: %s' % ( log.error('Farstream error #%d!\nMessage: %s' % (
message.structure['error-no'], message.structure['error-no'],
message.structure['error-msg'], message.structure['error-msg']))
message.structure['debug-msg']))
elif message.type == gst.MESSAGE_ERROR: elif message.type == gst.MESSAGE_ERROR:
# TODO: Fix it to fallback to videotestsrc anytime an error occur, # TODO: Fix it to fallback to videotestsrc anytime an error occur,
# or raise an error, Jingle way # or raise an error, Jingle way
@ -236,10 +235,10 @@ class JingleRTPContent(JingleContent):
def on_negotiated(self): def on_negotiated(self):
if self.accepted: if self.accepted:
if self.transport.remote_candidates: if self.transport.remote_candidates:
self.p2pstream.set_remote_candidates(self.transport.remote_candidates) self.p2pstream.add_remote_candidates(self.transport.remote_candidates)
self.transport.remote_candidates = [] self.transport.remote_candidates = []
# TODO: farsight.DIRECTION_BOTH only if senders='both' # TODO: farstream.DIRECTION_BOTH only if senders='both'
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH) self.p2pstream.set_property('direction', farstream.DIRECTION_BOTH)
JingleContent.on_negotiated(self) JingleContent.on_negotiated(self)
def __on_remote_codecs(self, stanza, content, error, action): def __on_remote_codecs(self, stanza, content, error, action):
@ -252,8 +251,8 @@ class JingleRTPContent(JingleContent):
if not codec['id'] or not codec['name'] or not codec['clockrate']: if not codec['id'] or not codec['name'] or not codec['clockrate']:
# ignore invalid payload-types # ignore invalid payload-types
continue continue
c = farsight.Codec(int(codec['id']), codec['name'], c = farstream.Codec(int(codec['id']), codec['name'],
self.farsight_media, int(codec['clockrate'])) self.farstream_media, int(codec['clockrate']))
if 'channels' in codec: if 'channels' in codec:
c.channels = int(codec['channels']) c.channels = int(codec['channels'])
else: else:
@ -318,7 +317,7 @@ class JingleAudio(JingleRTPContent):
self.out_volume.set_property('volume', vol) self.out_volume.set_property('volume', vol)
def setup_stream(self): def setup_stream(self):
JingleRTPContent.setup_stream(self) JingleRTPContent.setup_stream(self, self._on_src_pad_added)
# Configure SPEEX # Configure SPEEX
# Workaround for psi (not needed since rev # Workaround for psi (not needed since rev
@ -326,10 +325,10 @@ class JingleAudio(JingleRTPContent):
# place 16kHz before 8kHz, as buggy psi versions will take in # place 16kHz before 8kHz, as buggy psi versions will take in
# account only the first codec # account only the first codec
codecs = [farsight.Codec(farsight.CODEC_ID_ANY, 'SPEEX', codecs = [farstream.Codec(farstream.CODEC_ID_ANY, 'SPEEX',
farsight.MEDIA_TYPE_AUDIO, 16000), farstream.MEDIA_TYPE_AUDIO, 16000),
farsight.Codec(farsight.CODEC_ID_ANY, 'SPEEX', farstream.Codec(farstream.CODEC_ID_ANY, 'SPEEX',
farsight.MEDIA_TYPE_AUDIO, 8000)] farstream.MEDIA_TYPE_AUDIO, 8000)]
self.p2psession.set_codec_preferences(codecs) self.p2psession.set_codec_preferences(codecs)
# the local parts # the local parts
@ -348,9 +347,8 @@ class JingleAudio(JingleRTPContent):
self.src_bin.get_pad('src').link(self.p2psession.get_property( self.src_bin.get_pad('src').link(self.p2psession.get_property(
'sink-pad')) 'sink-pad'))
self.p2pstream.connect('src-pad-added', self._on_src_pad_added)
# The following is needed for farsight to process ICE requests: # The following is needed for farstream to process ICE requests:
self.pipeline.set_state(gst.STATE_PLAYING) self.pipeline.set_state(gst.STATE_PLAYING)
@ -363,7 +361,7 @@ class JingleVideo(JingleRTPContent):
# 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.setup_stream(self) JingleRTPContent.setup_stream(self, self._on_src_pad_added)
# the local parts # the local parts
if gajim.config.get('video_framerate'): if gajim.config.get('video_framerate'):
@ -395,9 +393,8 @@ class JingleVideo(JingleRTPContent):
self.src_bin.get_pad('src').link(self.p2psession.get_property( self.src_bin.get_pad('src').link(self.p2psession.get_property(
'sink-pad')) 'sink-pad'))
self.p2pstream.connect('src-pad-added', self._on_src_pad_added)
# The following is needed for farsight to process ICE requests: # The following is needed for farstream to process ICE requests:
self.pipeline.set_state(gst.STATE_PLAYING) self.pipeline.set_state(gst.STATE_PLAYING)
def get_fallback_src(self): def get_fallback_src(self):

View File

@ -73,7 +73,7 @@ class JingleTransport(object):
try: try:
import farsight import farstream
except Exception: except Exception:
pass pass
@ -82,11 +82,11 @@ class JingleTransportICEUDP(JingleTransport):
JingleTransport.__init__(self, TransportType.datagram) JingleTransport.__init__(self, TransportType.datagram)
def make_candidate(self, candidate): def make_candidate(self, candidate):
types = {farsight.CANDIDATE_TYPE_HOST: 'host', types = {farstream.CANDIDATE_TYPE_HOST: 'host',
farsight.CANDIDATE_TYPE_SRFLX: 'srflx', farstream.CANDIDATE_TYPE_SRFLX: 'srflx',
farsight.CANDIDATE_TYPE_PRFLX: 'prflx', farstream.CANDIDATE_TYPE_PRFLX: 'prflx',
farsight.CANDIDATE_TYPE_RELAY: 'relay', farstream.CANDIDATE_TYPE_RELAY: 'relay',
farsight.CANDIDATE_TYPE_MULTICAST: 'multicast'} farstream.CANDIDATE_TYPE_MULTICAST: 'multicast'}
attrs = { attrs = {
'component': candidate.component_id, 'component': candidate.component_id,
'foundation': '1', # hack 'foundation': '1', # hack
@ -98,7 +98,7 @@ class JingleTransportICEUDP(JingleTransport):
} }
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 == farstream.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
@ -117,29 +117,29 @@ class JingleTransportICEUDP(JingleTransport):
def parse_transport_stanza(self, transport): def parse_transport_stanza(self, transport):
candidates = [] candidates = []
for candidate in transport.iterTags('candidate'): for candidate in transport.iterTags('candidate'):
cand = farsight.Candidate() cand = farstream.Candidate()
cand.component_id = int(candidate['component']) cand.component_id = int(candidate['component'])
cand.ip = str(candidate['ip']) cand.ip = str(candidate['ip'])
cand.port = int(candidate['port']) cand.port = int(candidate['port'])
cand.foundation = str(candidate['foundation']) cand.foundation = str(candidate['foundation'])
#cand.type = farsight.CANDIDATE_TYPE_LOCAL #cand.type = farstream.CANDIDATE_TYPE_LOCAL
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 = farstream.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 = farstream.NETWORK_PROTOCOL_TCP
cand.username = str(transport['ufrag']) cand.username = str(transport['ufrag'])
cand.password = str(transport['pwd']) cand.password = str(transport['pwd'])
#FIXME: huh? #FIXME: huh?
types = {'host': farsight.CANDIDATE_TYPE_HOST, types = {'host': farstream.CANDIDATE_TYPE_HOST,
'srflx': farsight.CANDIDATE_TYPE_SRFLX, 'srflx': farstream.CANDIDATE_TYPE_SRFLX,
'prflx': farsight.CANDIDATE_TYPE_PRFLX, 'prflx': farstream.CANDIDATE_TYPE_PRFLX,
'relay': farsight.CANDIDATE_TYPE_RELAY, 'relay': farstream.CANDIDATE_TYPE_RELAY,
'multicast': farsight.CANDIDATE_TYPE_MULTICAST} 'multicast': farstream.CANDIDATE_TYPE_MULTICAST}
if 'type' in candidate and candidate['type'] in types: if 'type' in candidate and candidate['type'] in types:
cand.type = types[candidate['type']] cand.type = types[candidate['type']]
else: else:

View File

@ -103,9 +103,9 @@ class FeaturesWindow:
_('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'), _('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'),
_('Requires python-docutils.'), _('Requires python-docutils.'),
_('Requires python-docutils.')), _('Requires python-docutils.')),
_('Audio / Video'): (self.farsight_available, _('Audio / Video'): (self.farstream_available,
_('Ability to start audio and video chat.'), _('Ability to start audio and video chat.'),
_('Requires python-farsight and gstreamer-plugins-bad.'), _('Requires python-farstream and gstreamer-plugins-bad.'),
_('Feature not available under Windows.')), _('Feature not available under Windows.')),
_('UPnP-IGD'): (self.gupnp_igd_available, _('UPnP-IGD'): (self.gupnp_igd_available,
_('Ability to request your router to forward port for file transfer.'), _('Ability to request your router to forward port for file transfer.'),
@ -258,8 +258,8 @@ class FeaturesWindow:
return False return False
return True return True
def farsight_available(self): def farstream_available(self):
return gajim.HAVE_FARSIGHT return gajim.HAVE_FARSTREAM
def gupnp_igd_available(self): def gupnp_igd_available(self):
return gajim.HAVE_UPNP_IGD return gajim.HAVE_UPNP_IGD