1
# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU Lesser General Public License as published
5
# by the Free Software Foundation; either version 2.1 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU Lesser General Public License for more details.
13
# You should have received a copy of the GNU Lesser General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
# Modified by Philippe Normand.
19
from dbus.connection import Connection
20
from dbus import PROPERTIES_IFACE
22
from telepathy.interfaces import CHANNEL_TYPE_DBUS_TUBE
24
from coherence import log
26
class TubeConnection(Connection, log.Loggable):
27
logCategory = "tube_connection"
29
def __new__(cls, conn, tube, address, group_iface=None, mainloop=None):
30
self = super(TubeConnection, cls).__new__(cls, address,
34
self.participants = {}
35
self.bus_name_to_handle = {}
36
self._mapping_watches = []
38
if group_iface is None:
39
method = conn.GetSelfHandle
41
method = group_iface.GetSelfHandle
43
method(reply_handler=self._on_get_self_handle_reply,
44
error_handler=self._on_get_self_handle_error)
48
def _on_get_self_handle_reply(self, handle):
49
self.self_handle = handle
50
tube_channel = self._tube[CHANNEL_TYPE_DBUS_TUBE]
51
match = tube_channel.connect_to_signal('DBusNamesChanged',
52
self._on_dbus_names_changed)
53
self._tube[PROPERTIES_IFACE].Get(CHANNEL_TYPE_DBUS_TUBE, 'DBusNames',
54
reply_handler=self._on_get_dbus_names_reply,
55
error_handler=self._on_get_dbus_names_error)
56
self._dbus_names_changed_match = match
58
def _on_get_self_handle_error(self, e):
59
self.warning('GetSelfHandle failed: %s', e)
62
self._dbus_names_changed_match.remove()
63
self._on_dbus_names_changed({}, self.participants.keys())
64
super(TubeConnection, self).close()
66
def _on_get_dbus_names_reply(self, names):
67
self._on_dbus_names_changed(names, ())
69
def _on_get_dbus_names_error(self, e):
70
self.warning('Get DBusNames property failed: %s', e)
72
def _on_dbus_names_changed(self, added, removed):
73
for handle, bus_name in added.items():
74
if handle == self.self_handle:
75
# I've just joined - set my unique name
76
self.set_unique_name(bus_name)
77
self.participants[handle] = bus_name
78
self.bus_name_to_handle[bus_name] = handle
80
# call the callback while the removed people are still in
81
# participants, so their bus names are available
82
for callback in self._mapping_watches:
83
callback(added, removed)
85
for handle in removed:
86
bus_name = self.participants.pop(handle, None)
87
self.bus_name_to_handle.pop(bus_name, None)
89
def watch_participants(self, callback):
90
self._mapping_watches.append(callback)
92
# GetDBusNames already returned: fake a participant add event
94
added = list(self.participants.iteritems())