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