Enabling call monitor
[watersofshiloah] / src / call_monitor.py
1 import logging
2
3 import gobject
4 import dbus
5 import telepathy
6
7 import gtk_toolbox
8
9
10 _moduleLogger = logging.getLogger(__name__)
11 DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
12
13
14 class NewChannelSignaller(object):
15
16         def __init__(self, on_new_channel):
17                 self._sessionBus = dbus.SessionBus()
18                 self._on_user_new_channel = on_new_channel
19
20         def start(self):
21                 self._sessionBus.add_signal_receiver(
22                         self._on_new_channel,
23                         "NewChannel",
24                         "org.freedesktop.Telepathy.Connection",
25                         None,
26                         None
27                 )
28
29         def stop(self):
30                 self._sessionBus.remove_signal_receiver(
31                         self._on_new_channel,
32                         "NewChannel",
33                         "org.freedesktop.Telepathy.Connection",
34                         None,
35                         None
36                 )
37
38         @gtk_toolbox.log_exception(_moduleLogger)
39         def _on_new_channel(
40                 self, channelObjectPath, channelType, handleType, handle, supressHandler
41         ):
42                 connObjectPath = channel_path_to_conn_path(channelObjectPath)
43                 serviceName = path_to_service_name(channelObjectPath)
44                 try:
45                         self._on_user_new_channel(
46                                 self._sessionBus, serviceName, connObjectPath, channelObjectPath, channelType
47                         )
48                 except Exception:
49                         _moduleLogger.exception("Blocking exception from being passed up")
50
51
52 class ChannelClosed(object):
53
54         def __init__(self, bus, conn, chan, on_closed):
55                 self.__on_closed = on_closed
56
57                 chan[telepathy.interfaces.CHANNEL].connect_to_signal(
58                         "Closed",
59                         self._on_closed,
60                 )
61
62         @gtk_toolbox.log_exception(_moduleLogger)
63         def _on_closed(self):
64                 self.__on_closed(self)
65
66
67 class CallMonitor(gobject.GObject):
68
69         __gsignals__ = {
70                 'call_start' : (
71                         gobject.SIGNAL_RUN_LAST,
72                         gobject.TYPE_NONE,
73                         (),
74                 ),
75                 'call_end' : (
76                         gobject.SIGNAL_RUN_LAST,
77                         gobject.TYPE_NONE,
78                         (),
79                 ),
80         }
81
82         def __init__(self):
83                 gobject.GObject.__init__(self)
84                 self._isActive = False
85                 self._newChannelMonitor = NewChannelSignaller(self._on_new_channel)
86                 self._channelClosedMonitors = []
87
88         def start(self):
89                 self._isActive = True
90                 self._newChannelMonitor.start()
91
92         def stop(self):
93                 self._isActive = False
94                 self._newChannelMonitor.stop()
95
96         def _on_new_channel(self, sessionBus, serviceName, connObjectPath, channelObjectPath, channelType):
97                 if not self._isActive:
98                         return
99
100                 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
101                         return
102
103                 cmName = cm_from_path(connObjectPath)
104                 conn = telepathy.client.Connection(serviceName, connObjectPath)
105                 try:
106                         chan = telepathy.client.Channel(serviceName, channelObjectPath)
107                 except dbus.exceptions.UnknownMethodException:
108                         _moduleLogger.exception("Client might not have implemented a deprecated method")
109                         return
110
111                 missDetection = ChannelClosed(
112                         sessionBus, conn, chan, self._on_close
113                 )
114                 self._outstandingRequests.append(missDetection)
115                 if len(self._outstandingRequests) == 1:
116                         self.emit("call_start")
117
118         def _on_close(self, channelCloseMonitor):
119                 self._outstandingRequests.remove(channelCloseMonitor)
120                 if not self._outstandingRequests:
121                         self.emit("call_stop")
122
123
124 def channel_path_to_conn_path(channelObjectPath):
125         """
126         >>> channel_path_to_conn_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
127         '/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME'
128         """
129         return channelObjectPath.rsplit("/", 1)[0]
130
131
132 def path_to_service_name(path):
133         """
134         >>> path_to_service_name("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
135         'org.freedesktop.Telepathy.ConnectionManager.theonering.gv.USERNAME'
136         """
137         return ".".join(path[1:].split("/")[0:7])
138
139
140 def cm_from_path(path):
141         """
142         >>> cm_from_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
143         'theonering'
144         """
145         return path[1:].split("/")[4]