Prefixing more hacks with HACK to make it easier to remove later
[theonering] / src / channel_manager.py
1 import logging
2
3 import dbus
4 import telepathy
5
6 import channel
7
8
9 _moduleLogger = logging.getLogger("channel_manager")
10
11
12 class TelepathyChannelManager(object):
13
14         def __init__(self, connection):
15                 self._conn = connection
16
17                 self._requestable_channel_classes = dict()
18                 self._channels = dict()
19                 self._fixed_properties = dict()
20                 self._available_properties = dict()
21
22         def close(self):
23                 for channel_type in self._requestable_channel_classes:
24                         for chan in self._channels[channel_type].values():
25                                 try:
26                                         _moduleLogger.info("Closing %s %s" % (channel_type, chan._object_path))
27                                         chan.Close()
28                                 except Exception:
29                                         _moduleLogger.exception("Shutting down %r" % (chan, ))
30
31         def remove_channel(self, chan):
32                 for channel_type in self._requestable_channel_classes:
33                         for handle, ichan in self._channels[channel_type].items():
34                                 if chan == ichan:
35                                         del self._channels[channel_type][handle]
36
37         def _get_type_requested_handle(self, props):
38                 type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType']
39                 requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
40                 target_handle = props[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle']
41                 target_handle_type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType']
42
43                 handle = self._conn._handles[target_handle_type, target_handle]
44
45                 return (type, requested, handle)
46
47         def channel_exists(self, props):
48                 type, _, handle = self._get_type_requested_handle(props)
49
50                 if type in self._channels:
51                         if handle in self._channels[type]:
52                                 return True
53
54                 return False
55
56         def channel_for_props(self, props, signal=True, **args):
57                 type, suppress_handler, handle = self._get_type_requested_handle(props)
58
59                 if type not in self._requestable_channel_classes:
60                         raise NotImplemented('Unknown channel type "%s"' % type)
61
62                 if self.channel_exists(props):
63                         return self._channels[type][handle]
64
65                 chan = self._requestable_channel_classes[type](props, **args)
66
67                 if hasattr(self._conn, "add_channels"):
68                         # HACK Newer python-telepathy
69                         self._conn.add_channels([chan], signal=signal)
70                 elif hasattr(self._conn, "add_channel"):
71                         # HACK Older python-telepathy
72                         self._conn.add_channel(chan, handle, suppress_handler)
73                 else:
74                         raise RuntimeError("Uhh, what just happened with the connection")
75                 self._channels[type][handle] = chan
76
77                 return chan
78
79         def _implement_channel_class(self, type, make_channel, fixed, available):
80                 self._requestable_channel_classes[type] = make_channel
81                 self._channels.setdefault(type, {})
82
83                 self._fixed_properties[type] = fixed
84                 self._available_properties[type] = available
85
86         def get_requestable_channel_classes(self):
87                 retval = []
88
89                 for channel_type in self._requestable_channel_classes:
90                         retval.append((self._fixed_properties[channel_type],
91                                 self._available_properties[channel_type]))
92
93                 return retval
94
95
96 class ChannelManager(TelepathyChannelManager):
97
98         def __init__(self, connection):
99                 TelepathyChannelManager.__init__(self, connection)
100
101                 fixed = {
102                         telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT,
103                         telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
104                 }
105                 self._implement_channel_class(
106                         telepathy.CHANNEL_TYPE_TEXT,
107                         self._get_text_channel,
108                         fixed,
109                         []
110                 )
111
112                 fixed = {
113                         telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST
114                 }
115                 self._implement_channel_class(
116                         telepathy.CHANNEL_TYPE_CONTACT_LIST,
117                         self._get_list_channel,
118                         fixed,
119                         []
120                 )
121
122                 fixed = {
123                         telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
124                         telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
125                 }
126                 self._implement_channel_class(
127                         telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
128                         self._get_media_channel,
129                         fixed,
130                         [telepathy.CHANNEL_INTERFACE + '.TargetHandle']
131                 )
132
133         def _get_list_channel(self, props):
134                 _, surpress_handler, handle = self._get_type_requested_handle(props)
135
136                 _moduleLogger.debug('New contact list channel')
137                 chan = channel.contact_list.create_contact_list_channel(self._conn, self, props, handle)
138                 return chan
139
140         def _get_text_channel(self, props):
141                 _, surpress_handler, handle = self._get_type_requested_handle(props)
142
143                 _moduleLogger.debug('New text channel')
144                 chan = channel.text.TextChannel(self._conn, self, props, handle)
145                 return chan
146
147         def _get_media_channel(self, props):
148                 _, surpress_handler, handle = self._get_type_requested_handle(props)
149
150                 _moduleLogger.debug('New media channel')
151                 chan = channel.call.CallChannel(self._conn, self, props, handle)
152                 return chan