0fc14968ebceeefaabc4d516e2ad425cbf221edd
[theonering] / hand_tests / dbus_signals.py
1 #!/usr/bin/env python
2
3 import sys
4 sys.path.insert(0,"../src")
5 import logging
6 import pprint
7
8 import gobject
9 import dbus
10 import dbus.mainloop.glib
11 import telepathy
12
13 import gtk_toolbox
14
15
16 _moduleLogger = logging.getLogger("receptionist")
17 DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
18
19
20 class AutoAcceptCall(object):
21
22         def __init__(self, bus, conn, chan, on_success, on_error):
23                 self._sessionBus = bus
24                 self._conn = conn
25                 self._chan = chan
26                 self._outstandingRequests = []
27                 self._on_success = on_success
28                 self._on_error = on_error
29
30                 self._selfHandle = None
31                 self._initiatorHandle = None
32                 self._initiatorID = None
33                 self._targetHandle = None
34                 self._targetID = None
35                 self._pendingHandles = None
36
37                 if False:
38                         # @bug Unsure why this isn't working
39                         self._conn[DBUS_PROPERTIES].Get(
40                                 telepathy.interfaces.CONNECTION_INTERFACE,
41                                 'SelfHandle',
42                                 reply_handler = self._on_got_self_handle,
43                                 error_handler = self._custom_error(self._on_got_self_handle),
44                         )
45                 else:
46                         self._conn[telepathy.interfaces.CONNECTION].GetSelfHandle(
47                                 reply_handler = self._on_got_self_handle,
48                                 error_handler = self._custom_error(self._on_got_self_handle),
49                         )
50                 self._outstandingRequests.append(self._on_got_self_handle)
51
52
53                 self._chan[DBUS_PROPERTIES].GetAll(
54                         telepathy.interfaces.CHANNEL_INTERFACE,
55                         reply_handler = self._on_got_all,
56                         error_handler = self._custom_error(self._on_got_all),
57                 )
58                 self._outstandingRequests.append(self._on_got_all)
59
60                 if False:
61                         # @bug Unsure why this isn't working
62                         self._chan[DBUS_PROPERTIES].Get(
63                                 telepathy.interfaces.CHANNEL_INTERFACE_GROUP,
64                                 'LocalPendingMembers',
65                                 reply_handler = self._on_got_pending_members,
66                                 error_handler = self._custom_error(self._on_got_pending_members),
67                         )
68                 else:
69                         self._chan[telepathy.interfaces.CHANNEL_INTERFACE_GROUP].GetLocalPendingMembersWithInfo(
70                                 reply_handler = self._on_got_pending_members,
71                                 error_handler = self._custom_error(self._on_got_pending_members),
72                         )
73                 self._outstandingRequests.append(self._on_got_pending_members)
74
75         def is_inbound(self):
76                 isInbound = self._selfHandle == self._targetHandle and self._selfHandle != self._initiatorHandle
77                 print "is_inbound", self._selfHandle, self._targetHandle, self._initiatorHandle
78                 print "is_inbound", self._targetID, self._initiatorID
79                 return isInbound
80
81         @property
82         def initiator(self):
83                 return self._initiatorID
84
85         @property
86         def target(self):
87                 return self._targetID
88
89         def accept_call(self, on_accepted, on_error):
90                 self._chan[telepathy.interfaces.CHANNEL_INTERFACE_GROUP].AddMembers(
91                         self._pendingHandles,
92                         "",
93                         reply_handler = self._custom_on_accept(on_accepted),
94                         error_handler = self._custom_on_accept_error(on_error),
95                 )
96
97         def _custom_on_accept(self, callback):
98
99                 def on_accept(self):
100                         callback(self)
101
102                 return on_accept
103
104         def _custom_on_accept_error(self, callback):
105
106                 def on_error(self, *args):
107                         callback(self, *args)
108
109                 return on_error
110
111         def _custom_error(self, action):
112
113                 def _on_error(self, *args):
114                         _moduleLogger.error("Failed for %r (%r)" % (action, args))
115                         self._outstandingRequests.remove(action)
116                         if self._outstandingRequests:
117                                 return
118
119                         self._on_error(self)
120
121                 return _on_error
122
123         def _report_callback_done(self, action):
124                 _moduleLogger.debug("Succeded with %r" % (action, ))
125                 self._outstandingRequests.remove(action)
126                 if self._outstandingRequests:
127                         return
128
129                 assert None not in (
130                         self._selfHandle,
131                         self._initiatorHandle,
132                         self._initiatorID,
133                         self._targetHandle,
134                         self._targetID,
135                         self._pendingHandles,
136                 )
137
138                 self._on_success(self)
139
140         @gtk_toolbox.log_exception(_moduleLogger)
141         def _on_got_self_handle(self, selfHandle):
142                 self._selfHandle = selfHandle
143
144                 self._report_callback_done(self._on_got_self_handle)
145
146         @gtk_toolbox.log_exception(_moduleLogger)
147         def _on_got_all(self, properties):
148                 self._initiatorID = properties["InitiatorID"]
149                 self._initiatorHandle = properties["InitiatorHandle"]
150                 self._targetID = properties["InitiatorID"]
151                 self._targetHandle = properties["InitiatorHandle"]
152
153                 self._report_callback_done(self._on_got_all)
154
155         @gtk_toolbox.log_exception(_moduleLogger)
156         def _on_got_pending_members(self, pendings):
157                 for pendingHandle, instigatorHandle, reason, message in pendings:
158                         print pendingHandle, instigatorHandle, reason, message
159
160                 self._pendingHandles = [pendingWithInfo[0] for pendingWithInfo in pendings]
161
162                 self._report_callback_done(self._on_got_pending_members)
163
164
165 class NewChannelSignaller(object):
166
167         def __init__(self, on_new_channel):
168                 self._sessionBus = dbus.SessionBus()
169                 self._on_user_new_channel = on_new_channel
170
171         def start(self):
172                 self._sessionBus.add_signal_receiver(
173                         self._on_new_channel,
174                         "NewChannel",
175                         "org.freedesktop.Telepathy.Connection",
176                         None,
177                         None
178                 )
179
180         def stop(self):
181                 self._sessionBus.remove_signal_receiver(
182                         self._on_new_channel,
183                         "NewChannel",
184                         "org.freedesktop.Telepathy.Connection",
185                         None,
186                         None
187                 )
188
189         @gtk_toolbox.log_exception(_moduleLogger)
190         def _on_new_channel(
191                 self, channelObjectPath, channelType, handleType, handle, supressHandler
192         ):
193                 connObjectPath = channelObjectPath.rsplit("/", 1)[0]
194                 serviceName = connObjectPath[1:].replace("/", ".")
195                 conn = telepathy.client.Connection(serviceName, connObjectPath)
196                 chan = telepathy.client.Channel(serviceName, channelObjectPath)
197                 self._on_user_new_channel(self._sessionBus, conn, chan, channelType)
198
199
200 class Manager(object):
201
202         def __init__(self):
203                 self._newChannelSignaller = NewChannelSignaller(self._on_new_channel)
204
205         def start(self):
206                 self._newChannelSignaller.start()
207
208         @gtk_toolbox.log_exception(_moduleLogger)
209         def _on_new_channel(self, bus, conn, chan, channelType):
210                 pprint.pprint((bus, conn, chan, channelType))
211                 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
212                         return
213
214                 # @bug does not distinguish between preferred CMs
215                 attemptPickup = AutoAcceptCall(bus, conn, chan, self._on_inbound_call, self._on_inbound_call_error)
216
217         @gtk_toolbox.log_exception(_moduleLogger)
218         def _on_inbound_call(self, autoAcceptCall):
219                 # @todo Add a comparison for picking up for only certain contacts
220                 print autoAcceptCall.initiator, autoAcceptCall.target
221                 if autoAcceptCall.is_inbound():
222                         autoAcceptCall.accept_call(self._on_call_pickedup, self._on_pickup_error)
223                 else:
224                         _moduleLogger.debug(
225                                 "Not an inbound call (initiator=%r, target=%r)" % (autoAcceptCall.initiator, autoAcceptCall.target)
226                         )
227
228         @gtk_toolbox.log_exception(_moduleLogger)
229         def _on_inbound_call_error(self, *args):
230                 _moduleLogger.info("Inbound call error")
231
232         @gtk_toolbox.log_exception(_moduleLogger)
233         def _on_call_pickedup(self, autoAcceptCall):
234                 _moduleLogger.info("Call picked up")
235
236         @gtk_toolbox.log_exception(_moduleLogger)
237         def _on_pickup_error(self, autoAcceptCall, *args):
238                 _moduleLogger.info("Call failed to pick up (%r)" % (args, ))
239
240 if __name__ == "__main__":
241         logging.basicConfig(level=logging.DEBUG)
242         l = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
243         autoaccept = Manager()
244
245         gobject.threads_init()
246         gobject.idle_add(autoaccept.start)
247
248         mainloop = gobject.MainLoop(is_running=True)
249         mainloop.run()