Include _generated now so I get all the latest fancy stuff
[theonering] / src / tp / channel.py
1 # telepathy-python - Base classes defining the interfaces of the Telepathy framework
2 #
3 # Copyright (C) 2005, 2006 Collabora Limited
4 # Copyright (C) 2005, 2006 Nokia Corporation
5 #
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
20 import dbus
21 import dbus.service
22
23 from telepathy.constants import (CONNECTION_HANDLE_TYPE_NONE,
24                                  CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
25                                  HANDLE_TYPE_NONE)
26
27 from telepathy.errors import InvalidArgument
28
29 from telepathy.interfaces import (CHANNEL_INTERFACE,
30                                   CHANNEL_INTERFACE_DTMF,
31                                   CHANNEL_INTERFACE_GROUP,
32                                   CHANNEL_INTERFACE_HOLD,
33                                   CHANNEL_INTERFACE_PASSWORD,
34                                   CHANNEL_TYPE_CONTACT_LIST,
35                                   CHANNEL_TYPE_FILE_TRANSFER,
36                                   CHANNEL_TYPE_ROOM_LIST,
37                                   CHANNEL_TYPE_STREAMED_MEDIA,
38                                   CHANNEL_TYPE_TEXT,
39                                   MEDIA_SESSION_HANDLER,
40                                   MEDIA_STREAM_HANDLER)
41
42 from _generated.Channel import Channel as _Channel
43
44 from properties import DBusProperties
45
46 from handle import NoneHandle
47
48 class Channel(_Channel, DBusProperties):
49
50     def __init__(self, connection, manager, props, object_path=None):
51         """
52         Initialise the base channel object.
53
54         Parameters:
55         connection - the parent Connection object
56         props - initial channel properties
57         """
58         self._conn = connection
59         self._chan_manager = manager
60
61         object_path = self._conn.get_channel_path(object_path)
62         _Channel.__init__(self, self._conn._name, object_path)
63
64         self._type = props[CHANNEL_INTERFACE + '.ChannelType']
65         self._requested = props[CHANNEL_INTERFACE + '.Requested']
66
67         self._immutable_properties = dict()
68
69         tht = props.get(CHANNEL_INTERFACE + '.TargetHandleType', HANDLE_TYPE_NONE)
70
71         if tht == HANDLE_TYPE_NONE:
72             self._handle = NoneHandle()
73         else:
74             self._handle = self._conn.get_handle_by_id(
75                 props[CHANNEL_INTERFACE + '.TargetHandleType'],
76                 props[CHANNEL_INTERFACE + '.TargetHandle'])
77
78         self._interfaces = set()
79
80         DBusProperties.__init__(self)
81         self._implement_property_get(CHANNEL_INTERFACE,
82             {'ChannelType': lambda: dbus.String(self.GetChannelType()),
83              'Interfaces': lambda: dbus.Array(self.GetInterfaces(), signature='s'),
84              'TargetHandle': lambda: dbus.UInt32(self._handle.get_id()),
85              'TargetHandleType': lambda: dbus.UInt32(self._handle.get_type()),
86              'TargetID': lambda: dbus.String(self._handle.get_name()),
87              'Requested': lambda: self._requested})
88
89         self._add_immutables({
90             'ChannelType': CHANNEL_INTERFACE,
91             'TargetHandle': CHANNEL_INTERFACE,
92             'Interfaces': CHANNEL_INTERFACE,
93             'TargetHandleType': CHANNEL_INTERFACE,
94             'TargetID': CHANNEL_INTERFACE,
95             'Requested': CHANNEL_INTERFACE
96             })
97
98     def _add_immutables(self, props):
99         self._immutable_properties.update(props)
100
101     def get_props(self):
102         """Despite its name, this function actually only returns immutable channel
103         properties."""
104         props = dict()
105         for prop, iface in self._immutable_properties.items():
106             props[iface + '.' + prop] = \
107                 self._prop_getters[iface][prop]()
108         return props
109
110     @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='')
111     def Close(self):
112         self.Closed()
113         self._chan_manager.remove_channel(self)
114         self._conn.remove_channel(self)
115
116     @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='s')
117     def GetChannelType(self):
118         """ Returns the interface name for the type of this channel. """
119         return self._type
120
121     @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='uu')
122     def GetHandle(self):
123         """ Returns the handle type and number if this channel represents a
124         communication with a particular contact, room or server-stored list, or
125         zero if it is transient and defined only by its contents. """
126         return (self._handle.get_type(), self._handle.get_id())
127
128     @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as')
129     def GetInterfaces(self):
130         """
131         Get the optional interfaces implemented by the channel.
132
133         Returns:
134         an array of the D-Bus interface names
135         """
136         return self._interfaces
137
138 from _generated.Channel_Type_Contact_List \
139         import ChannelTypeContactList as _ChannelTypeContactListIface
140
141 class ChannelTypeContactList(Channel, _ChannelTypeContactListIface):
142     __doc__ = _ChannelTypeContactListIface.__doc__
143
144     def __init__(self, connection, manager, props, object_path=None):
145         """
146         Initialise the channel.
147
148         Parameters:
149         connection - the parent Telepathy Connection object
150         """
151         Channel.__init__(self, connection, manager, props,
152             object_path=object_path)
153
154
155 from _generated.Channel_Type_File_Transfer \
156         import ChannelTypeFileTransfer as _ChannelTypeFileTransferIface
157
158 class ChannelTypeFileTransfer(Channel, _ChannelTypeFileTransferIface):
159     __doc__ = _ChannelTypeFileTransferIface.__doc__
160
161     def __init__(self, connection, manager, props, object_path=None):
162         """
163         Initialise the channel.
164
165         Parameters:
166         connection - the parent Telepathy Connection object
167         """
168         Channel.__init__(self, connection, manager, props,
169             object_path=object_path)
170
171
172 from _generated.Channel_Type_Streamed_Media \
173         import ChannelTypeStreamedMedia as _ChannelTypeStreamedMediaIface
174
175 class ChannelTypeStreamedMedia(Channel, _ChannelTypeStreamedMediaIface):
176     __doc__ = _ChannelTypeStreamedMediaIface.__doc__
177
178     def __init__(self, connection, manager, props, object_path=None):
179         """
180         Initialise the channel.
181
182         Parameters:
183         connection - the parent Telepathy Connection object
184         """
185         Channel.__init__(self, connection, manager, props,
186             object_path=object_path)
187
188
189 from _generated.Channel_Type_Room_List \
190         import ChannelTypeRoomList as _ChannelTypeRoomListIface
191
192 class ChannelTypeRoomList(Channel, _ChannelTypeRoomListIface):
193     __doc__ = _ChannelTypeRoomListIface.__doc__
194
195     def __init__(self, connection, manager, props, object_path=None):
196         """
197         Initialise the channel.
198
199         Parameters:
200         connection - the parent Telepathy Connection object
201         """
202         Channel.__init__(self, connection, manager, props,
203             object_path=object_path)
204         self._listing_rooms = False
205         self._rooms = {}
206
207         self._add_immutables({'Server': CHANNEL_TYPE_ROOM_LIST})
208
209     @dbus.service.method(CHANNEL_TYPE_ROOM_LIST, in_signature='', out_signature='b')
210     def GetListingRooms(self):
211         return self._listing_rooms
212
213     @dbus.service.signal(CHANNEL_TYPE_ROOM_LIST, signature='b')
214     def ListingRooms(self, listing):
215         self._listing_rooms = listing
216
217
218 from _generated.Channel_Type_Text \
219         import ChannelTypeText as _ChannelTypeTextIface
220
221 class ChannelTypeText(Channel, _ChannelTypeTextIface):
222     __doc__ = _ChannelTypeTextIface.__doc__
223
224     def __init__(self, connection, manager, props, object_path=None):
225         """
226         Initialise the channel.
227
228         Parameters:
229         connection - the parent Telepathy Connection object
230         """
231         Channel.__init__(self, connection, manager, props,
232             object_path=object_path)
233
234         self._pending_messages = {}
235         self._message_types = [CHANNEL_TEXT_MESSAGE_TYPE_NORMAL]
236
237     @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='', out_signature='au')
238     def GetMessageTypes(self):
239         """
240         Return an array indicating which types of message may be sent on this
241         channel.
242
243         Returns:
244         an array of integer message types as defined above
245         """
246         return self._message_types
247
248     @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='au', out_signature='')
249     def AcknowledgePendingMessages(self, ids):
250         """
251         Inform the channel that you have handled messages by displaying them to
252         the user (or equivalent), so they can be removed from the pending queue.
253
254         Parameters:
255         ids - the message to acknowledge
256
257         Possible Errors:
258         InvalidArgument (a given message ID was not found, no action taken)
259         """
260         for id in ids:
261             if id not in self._pending_messages:
262                 raise InvalidArgument("the given message ID was not found")
263
264         for id in ids:
265             del self._pending_messages[id]
266
267     @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='b', out_signature='a(uuuuus)')
268     def ListPendingMessages(self, clear):
269         """
270         List the messages currently in the pending queue, and optionally
271         remove then all.
272
273         Parameters:
274         clear - a boolean indicating whether the queue should be cleared
275
276         Returns:
277         an array of structs containing:
278             a numeric identifier
279             a unix timestamp indicating when the message was received
280             an integer handle of the contact who sent the message
281             an integer of the message type
282             a bitwise OR of the message flags
283             a string of the text of the message
284         """
285         messages = []
286         for id in self._pending_messages.keys():
287             (timestamp, sender, type, flags, text) = self._pending_messages[id]
288             message = (id, timestamp, sender, type, flags, text)
289             messages.append(message)
290             if clear:
291                 del self._pending_messages[id]
292         messages.sort(cmp=lambda x,y:cmp(x[1], y[1]))
293         return messages
294
295     @dbus.service.signal(CHANNEL_TYPE_TEXT, signature='uuuuus')
296     def Received(self, id, timestamp, sender, type, flags, text):
297         if id in self._pending_messages:
298             raise ValueError("You can't receive the same message twice.")
299         else:
300             self._pending_messages[id] = (timestamp, sender, type, flags, text)
301
302
303 from _generated.Channel_Interface_Chat_State \
304         import ChannelInterfaceChatState
305
306
307 from _generated.Channel_Interface_DTMF import ChannelInterfaceDTMF
308
309
310 from _generated.Channel_Interface_Group \
311         import ChannelInterfaceGroup as _ChannelInterfaceGroup
312
313 class ChannelInterfaceGroup(_ChannelInterfaceGroup, DBusProperties):
314
315     def __init__(self):
316         _ChannelInterfaceGroup.__init__(self)
317         DBusProperties.__init__(self)
318
319         self._implement_property_get(CHANNEL_INTERFACE_GROUP,
320             {'GroupFlags': lambda: dbus.UInt32(self.GetGroupFlags()),
321              'Members': lambda: dbus.Array(self.GetMembers(), signature='u'),
322              'RemotePendingMembers': lambda: dbus.Array(self.GetRemotePendingMembers(), signature='u'),
323              'SelfHandle': lambda: dbus.UInt32(self.GetSelfHandle())})
324
325         self._group_flags = 0
326         self._members = set()
327         self._local_pending = set()
328         self._remote_pending = set()
329
330     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='u')
331     def GetGroupFlags(self):
332         return self._group_flags
333
334     @dbus.service.signal(CHANNEL_INTERFACE_GROUP, signature='uu')
335     def GroupFlagsChanged(self, added, removed):
336         self._group_flags |= added
337         self._group_flags &= ~removed
338
339     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
340     def GetMembers(self):
341         return self._members
342
343     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='u')
344     def GetSelfHandle(self):
345         self_handle = self._conn.GetSelfHandle()
346         if (self_handle in self._members or
347             self_handle in self._local_pending or
348             self_handle in self._remote_pending):
349             return self_handle
350         else:
351             return 0
352
353     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
354     def GetLocalPendingMembers(self):
355         return self._local_pending
356
357     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
358     def GetRemotePendingMembers(self):
359         return self._remote_pending
360
361     @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='auauau')
362     def GetAllMembers(self):
363         return (self._members, self._local_pending, self._remote_pending)
364
365     @dbus.service.signal(CHANNEL_INTERFACE_GROUP, signature='sauauauauuu')
366     def MembersChanged(self, message, added, removed, local_pending, remote_pending, actor, reason):
367
368         self._members.update(added)
369         self._members.difference_update(removed)
370
371         self._local_pending.update(local_pending)
372         self._local_pending.difference_update(added)
373         self._local_pending.difference_update(removed)
374
375         self._remote_pending.update(remote_pending)
376         self._remote_pending.difference_update(added)
377         self._remote_pending.difference_update(removed)
378
379
380 from _generated.Channel_Interface_Hold import ChannelInterfaceHold
381
382
383 # ChannelInterfaceMediaSignalling is in telepathy.server.media
384
385
386 from _generated.Channel_Interface_Password \
387         import ChannelInterfacePassword as _ChannelInterfacePassword
388
389 class ChannelInterfacePassword(_ChannelInterfacePassword):
390     def __init__(self):
391         _ChannelInterfacePassword.__init__(self)
392         self._password_flags = 0
393         self._password = ''
394
395     @dbus.service.method(CHANNEL_INTERFACE_PASSWORD, in_signature='', out_signature='u')
396     def GetPasswordFlags(self):
397         return self._password_flags
398
399     @dbus.service.signal(CHANNEL_INTERFACE_PASSWORD, signature='uu')
400     def PasswordFlagsChanged(self, added, removed):
401         self._password_flags |= added
402         self._password_flags &= ~removed
403
404
405 from _generated.Channel_Interface_Call_State import ChannelInterfaceCallState