new GUI to start audio and video sessions. TODO: ability to add/remove audio/video content to an existing session

This commit is contained in:
Yann Leboulanger 2009-09-25 13:52:44 +02:00
parent d7560ed764
commit 32965a948e
3 changed files with 157 additions and 74 deletions

View file

@ -102,7 +102,7 @@
</packing>
</child>
<child>
<widget class="GtkImage" id="audio_image">
<widget class="GtkImage" id="audio_banner_image">
<property name="visible">True</property>
<property name="stock">None</property>
<property name="icon-size">1</property>
@ -333,15 +333,13 @@
</packing>
</child>
<child>
<widget class="GtkButton" id="start_audio_button">
<widget class="GtkToggleButton" id="audio_togglebutton">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="tooltip" translatable="yes">Start audio session</property>
<property name="tooltip" translatable="yes">Toggle audio session</property>
<property name="relief">none</property>
<signal name="activate" handler="on_start_audio_button_activate"/>
<child>
<widget class="GtkImage" id="start_audio_image">
<widget class="GtkImage" id="audio_image">
<property name="visible">True</property>
<property name="stock">gtk-missing-image</property>
<property name="icon-size">1</property>
@ -354,15 +352,13 @@
</packing>
</child>
<child>
<widget class="GtkButton" id="stop_audio_button">
<widget class="GtkToggleButton" id="video_togglebutton">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="tooltip" translatable="yes">Stop audio session</property>
<property name="tooltip" translatable="yes">Toggle video session</property>
<property name="relief">none</property>
<signal name="activate" handler="on_stop_audio_button_activate"/>
<child>
<widget class="GtkImage" id="stop_audio_image">
<widget class="GtkImage" id="video_image">
<property name="visible">True</property>
<property name="stock">gtk-missing-image</property>
<property name="icon-size">1</property>

View file

@ -1167,12 +1167,12 @@ class ChatControlBase(MessageControl, CommonCommands):
class ChatControl(ChatControlBase, ChatCommands):
'''A control for standard 1-1 chat'''
(
AUDIO_STATE_NOT_AVAILABLE,
AUDIO_STATE_AVAILABLE,
AUDIO_STATE_CONNECTING,
AUDIO_STATE_CONNECTION_RECEIVED,
AUDIO_STATE_CONNECTED,
AUDIO_STATE_ERROR
JINGLE_STATE_NOT_AVAILABLE,
JINGLE_STATE_AVAILABLE,
JINGLE_STATE_CONNECTING,
JINGLE_STATE_CONNECTION_RECEIVED,
JINGLE_STATE_CONNECTED,
JINGLE_STATE_ERROR
) = range(6)
TYPE_ID = message_control.TYPE_CHAT
@ -1200,15 +1200,13 @@ class ChatControl(ChatControlBase, ChatCommands):
self._on_add_to_roster_menuitem_activate)
self.handlers[id_] = self._add_to_roster_button
self._start_audio_button = self.xml.get_widget('start_audio_button')
id_ = self._start_audio_button.connect('clicked',
self.on_start_audio_button_activate)
self.handlers[id_] = self._start_audio_button
self._audio_button = self.xml.get_widget('audio_togglebutton')
id_ = self._audio_button.connect('toggled', self.on_audio_button_toggled)
self.handlers[id_] = self._audio_button
self._stop_audio_button = self.xml.get_widget('stop_audio_button')
id_ = self._stop_audio_button.connect('clicked',
self.on_stop_audio_button_activate)
self.handlers[id_] = self._stop_audio_button
self._video_button = self.xml.get_widget('video_togglebutton')
id_ = self._video_button.connect('toggled', self.on_video_button_toggled)
self.handlers[id_] = self._video_button
self._send_file_button = self.xml.get_widget('send_file_button')
# add a special img for send file button
@ -1252,13 +1250,20 @@ class ChatControl(ChatControlBase, ChatCommands):
img.set_from_pixbuf(gtkgui_helpers.load_icon(
'muc_active').get_pixbuf())
self._audio_image = self.xml.get_widget('audio_image')
self._audio_banner_image = self.xml.get_widget('audio_banner_image')
self._video_banner_image = self.xml.get_widget('video_banner_image')
if gajim.capscache.is_supported(contact, NS_JINGLE_RTP_AUDIO) and \
gajim.HAVE_FARSIGHT:
self.set_audio_state('available')
else:
self.set_audio_state('not_available')
if gajim.capscache.is_supported(contact, NS_JINGLE_RTP_VIDEO) and \
gajim.HAVE_FARSIGHT:
self.set_video_state('available')
else:
self.set_video_state('not_available')
self.audio_sid = None
self.video_sid = None
self.update_toolbar()
@ -1369,18 +1374,16 @@ class ChatControl(ChatControlBase, ChatCommands):
self._add_to_roster_button.hide()
# Audio buttons
if self.audio_state == self.AUDIO_STATE_NOT_AVAILABLE:
self._start_audio_button.show()
self._start_audio_button.set_sensitive(False)
self._stop_audio_button.hide()
elif self.audio_state in (self.AUDIO_STATE_AVAILABLE,
self.AUDIO_STATE_ERROR):
self._start_audio_button.show()
self._start_audio_button.set_sensitive(True)
self._stop_audio_button.hide()
if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE:
self._audio_button.set_sensitive(False)
else:
self._start_audio_button.hide()
self._stop_audio_button.show()
self._audio_button.set_sensitive(True)
# Video buttons
if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE:
self._video_button.set_sensitive(False)
else:
self._video_button.set_sensitive(True)
# Send file
if gajim.capscache.is_supported(self.contact, NS_FILE) and \
@ -1515,19 +1518,35 @@ class ChatControl(ChatControlBase, ChatCommands):
self._tune_image.hide()
def update_audio(self):
if self.audio_state in (self.AUDIO_STATE_NOT_AVAILABLE,
self.AUDIO_STATE_AVAILABLE):
self._audio_image.hide()
if self.audio_state in (self.JINGLE_STATE_NOT_AVAILABLE,
self.JINGLE_STATE_AVAILABLE):
self._audio_banner_image.hide()
else:
self._audio_image.show()
if self.audio_state == self.AUDIO_STATE_CONNECTING:
self._audio_image.set_from_stock(gtk.STOCK_CONVERT, 1)
elif self.audio_state == self.AUDIO_STATE_CONNECTION_RECEIVED:
self._audio_image.set_from_stock(gtk.STOCK_NETWORK, 1)
elif self.audio_state == self.AUDIO_STATE_CONNECTED:
self._audio_image.set_from_stock(gtk.STOCK_CONNECT, 1)
elif self.audio_state == self.AUDIO_STATE_ERROR:
self._audio_image.set_from_stock(gtk.STOCK_DIALOG_WARNING, 1)
self._audio_banner_image.show()
if self.audio_state == self.JINGLE_STATE_CONNECTING:
self._audio_banner_image.set_from_stock(gtk.STOCK_CONVERT, 1)
elif self.audio_state == self.JINGLE_STATE_CONNECTION_RECEIVED:
self._audio_banner_image.set_from_stock(gtk.STOCK_NETWORK, 1)
elif self.audio_state == self.JINGLE_STATE_CONNECTED:
self._audio_banner_image.set_from_stock(gtk.STOCK_CONNECT, 1)
elif self.audio_state == self.JINGLE_STATE_ERROR:
self._audio_banner_image.set_from_stock(gtk.STOCK_DIALOG_WARNING, 1)
self.update_toolbar()
def update_video(self):
if self.video_state in (self.JINGLE_STATE_NOT_AVAILABLE,
self.JINGLE_STATE_AVAILABLE):
self._video_banner_image.hide()
else:
self._video_banner_image.show()
if self.video_state == self.JINGLE_STATE_CONNECTING:
self._video_banner_image.set_from_stock(gtk.STOCK_CONVERT, 1)
elif self.video_state == self.JINGLE_STATE_CONNECTION_RECEIVED:
self._video_banner_image.set_from_stock(gtk.STOCK_NETWORK, 1)
elif self.video_state == self.JINGLE_STATE_CONNECTED:
self._video_banner_image.set_from_stock(gtk.STOCK_CONNECT, 1)
elif self.video_state == self.JINGLE_STATE_ERROR:
self._video_banner_image.set_from_stock(gtk.STOCK_DIALOG_WARNING, 1)
self.update_toolbar()
def change_resource(self, resource):
@ -1550,26 +1569,53 @@ class ChatControl(ChatControlBase, ChatCommands):
str += ', ' + _('reason: %s') % reason
self.print_conversation(str, 'info')
if state == 'not_available':
self.audio_state = self.AUDIO_STATE_NOT_AVAILABLE
self.audio_state = self.JINGLE_STATE_NOT_AVAILABLE
self.audio_sid = None
elif state == 'available':
self.audio_state = self.AUDIO_STATE_AVAILABLE
self.audio_state = self.JINGLE_STATE_AVAILABLE
self.audio_sid = None
elif state == 'connecting':
self.audio_state = self.AUDIO_STATE_CONNECTING
self.audio_state = self.JINGLE_STATE_CONNECTING
self.audio_sid = sid
elif state == 'connection_received':
self.audio_state = self.AUDIO_STATE_CONNECTION_RECEIVED
self.audio_state = self.JINGLE_STATE_CONNECTION_RECEIVED
self.audio_sid = sid
elif state == 'connected':
self.audio_state = self.AUDIO_STATE_CONNECTED
self.audio_state = self.JINGLE_STATE_CONNECTED
elif state == 'stop':
self.audio_state = self.AUDIO_STATE_AVAILABLE
self.audio_state = self.JINGLE_STATE_AVAILABLE
self.audio_sid = None
elif state == 'error':
self.audio_state = self.AUDIO_STATE_ERROR
self.audio_state = self.JINGLE_STATE_ERROR
self.update_audio()
def set_video_state(self, state, sid=None, reason=None):
if state in ('connecting', 'connected', 'stop'):
str = _('Video state : %s') % state
if reason:
str += ', ' + _('reason: %s') % reason
self.print_conversation(str, 'info')
if state == 'not_available':
self.video_state = self.JINGLE_STATE_NOT_AVAILABLE
self.video_sid = None
elif state == 'available':
self.video_state = self.JINGLE_STATE_AVAILABLE
self.video_sid = None
elif state == 'connecting':
self.video_state = self.JINGLE_STATE_CONNECTING
self.video_sid = sid
elif state == 'connection_received':
self.video_state = self.JINGLE_STATE_CONNECTION_RECEIVED
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
elif state == 'error':
self.video_state = self.JINGLE_STATE_ERROR
self.update_video()
def on_avatar_eventbox_enter_notify_event(self, widget, event):
'''
we enter the eventbox area so we under conditions add a timeout
@ -1770,16 +1816,29 @@ class ChatControl(ChatControlBase, ChatCommands):
banner_name_label.set_markup(label_text)
banner_name_tooltip.set_tip(banner_name_label, label_tooltip)
def on_start_audio_button_activate(self, *things):
sid = gajim.connections[self.account].startVoIP(self.contact.get_full_jid(
))
self.set_audio_state('connecting', sid)
def on_audio_button_toggled(self, widget):
if widget.get_active():
sid = gajim.connections[self.account].startVoIP(
self.contact.get_full_jid())
self.set_audio_state('connecting', sid)
else:
session = gajim.connections[self.account].get_jingle_session(
self.contact.get_full_jid(), self.audio_sid)
if session:
# TODO: end only audio
session.end_session()
def on_stop_audio_button_activate(self, *things):
session = gajim.connections[self.account].get_jingle_session(
self.contact.get_full_jid(), self.audio_sid)
if session:
session.end_session()
def on_video_button_toggled(self, widget):
if widget.get_active():
sid = gajim.connections[self.account].startVideoIP(
self.contact.get_full_jid())
self.set_video_state('connecting', sid)
else:
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()
def _toggle_gpg(self):
if not self.gpg_is_active and not self.contact.keyID:

View file

@ -953,14 +953,42 @@ class ConnectionJingle(object):
raise xmpp.NodeProcessed
def startVoIP(self, jid):
jingle = JingleSession(self, weinitiate=True, jid=jid)
self.add_jingle(jingle)
jingle.add_content('voice', JingleVoIP(jingle))
jingle.start_session()
jingle = self.get_jingle_session(jid, media='video')
if jingle:
jingle.add_content('voice', JingleVoIP(jingle))
else:
jingle = JingleSession(self, weinitiate=True, jid=jid)
self.add_jingle(jingle)
jingle.add_content('voice', JingleVoIP(jingle))
jingle.start_session()
return jingle.sid
def get_jingle_session(self, jid, sid):
try:
return self.__sessions[(jid, sid)]
except KeyError:
return None
def startVideoIP(self, jid):
jingle = self.get_jingle_session(jid, media='audio')
if jingle:
jingle.add_content('video', JingleVideo(jingle))
else:
jingle = JingleSession(self, weinitiate=True, jid=jid)
self.add_jingle(jingle)
jingle.add_content('video', JingleVideo(jingle))
jingle.start_session()
return jingle.sid
def get_jingle_session(self, jid, sid=None, media=None):
if sid:
if (jid, sid) in self.__sessions:
return self.__sessions[(jid, sid)]
else:
return None
elif media:
if media == 'audio':
cls = JingleVoIP
elif media == 'video':
cls = JingleVideo
else:
return None
for session in self.__sessions.values():
for content in session.contents.values():
if isinstance(content, cls):
return session
return None