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