1 | #!/usr/bin/env python |
||
2 | # -*- coding: utf-8 -*- |
||
3 | |||
4 | import logging |
||
5 | logger = logging.getLogger(__name__) |
||
6 | logger.debug("%s loaded", __name__) |
||
7 | |||
8 | from time import sleep |
||
9 | import linphone |
||
10 | from doorpi import DoorPi |
||
11 | |||
12 | class LinphoneCallbacks: |
||
13 | |||
14 | @property |
||
15 | def used_callbacks(self): return { |
||
16 | #http://www.linphone.org/docs/liblinphone/struct__LinphoneCoreVTable.html |
||
17 | #'global_state_changed': self.global_state_changed, #Notifies global state changes |
||
18 | #'registration_state_changed': self.registration_state_changed, #Notifies registration state changes |
||
19 | 'call_state_changed': self.call_state_changed, #Notifies call state changes |
||
20 | #'notify_presence_received': self.notify_presence_received, #Notify received presence events |
||
21 | #'new_subscription_requested': self.new_subscription_requested, #Notify about pending presence subscription request |
||
22 | #'auth_info_requested': self.auth_info_requested, #Ask the application some authentication information |
||
23 | #'call_log_updated': self.call_log_updated, #Notifies that call log list has been updated |
||
24 | #'message_received': self.message_received, #a message is received, can be text or external body |
||
25 | #'is_composing_received': self.is_composing_received, #An is-composing notification has been received |
||
26 | 'dtmf_received': self.dtmf_received, #A dtmf has been received received |
||
27 | #'refer_received': self.refer_received, #An out of call refer was received |
||
28 | #'call_encryption_changed': self.call_encryption_changed, #Notifies on change in the encryption of call streams |
||
29 | #'transfer_state_changed': self.transfer_state_changed, #Notifies when a transfer is in progress |
||
30 | #'buddy_info_updated': self.buddy_info_updated, #a LinphoneFriend's BuddyInfo has changed |
||
31 | #'call_stats_updated': self.call_stats_updated, #Notifies on refreshing of call's statistics. |
||
32 | #'info_received': self.info_received, #Notifies an incoming informational message received. |
||
33 | #'subscription_state_changed': self.subscription_state_changed, #Notifies subscription state change |
||
34 | #'notify_received': self.notify_received, #Notifies a an event notification, see linphone_core_subscribe() |
||
35 | #'configuring_status': self.configuring_status, #Notifies publish state change (only from LinphoneEvent api) |
||
36 | #'network_reachable': self.network_reachable, #Callback to report IP network status (I.E up/down ) |
||
37 | #'log_collection_upload_state_changed': self.log_collection_upload_state_changed, #Callback to upload collected logs |
||
38 | #'log_collection_upload_progress_indication': self.log_collection_upload_progress_indication #Callback to indicate log collection upload progress |
||
39 | } |
||
40 | |||
41 | @property |
||
42 | def whitelist(self): return DoorPi().config.get_keys('AdminNumbers') |
||
43 | |||
44 | def is_admin_number(self, remote_uri): |
||
45 | logger.debug("is_admin_number (%s)",remote_uri) |
||
46 | for admin_number in self.whitelist: |
||
47 | if admin_number == "*": |
||
48 | logger.info("admin numbers are deactivated by using '*' as single number") |
||
49 | return True |
||
50 | if "sip:"+admin_number+"@" in remote_uri: |
||
51 | logger.debug("%s is adminnumber %s", remote_uri, admin_number) |
||
52 | return True |
||
53 | if "sip:"+admin_number is remote_uri: |
||
54 | logger.debug("%s is adminnumber %s", remote_uri, admin_number) |
||
55 | return True |
||
56 | logger.debug("%s is not an adminnumber", remote_uri) |
||
57 | return False |
||
58 | |||
59 | __DTMF = '' |
||
60 | __possible_DTMF = [] |
||
61 | |||
62 | def __init__(self): |
||
63 | logger.debug("__init__") |
||
64 | |||
65 | self._last_number_of_calls = 0 |
||
66 | |||
67 | DoorPi().event_handler.register_action('OnSipPhoneDestroy', self.destroy) |
||
68 | |||
69 | DoorPi().event_handler.register_event('OnCallMediaStateChange', __name__) |
||
70 | DoorPi().event_handler.register_event('OnMediaRequired', __name__) |
||
71 | DoorPi().event_handler.register_event('OnMediaNotRequired', __name__) |
||
72 | |||
73 | DoorPi().event_handler.register_event('OnCallStateChange', __name__) |
||
74 | DoorPi().event_handler.register_event('OnCallStateConnect', __name__) |
||
75 | DoorPi().event_handler.register_event('AfterCallStateConnect', __name__) |
||
76 | DoorPi().event_handler.register_event('OnCallStateDisconnect', __name__) |
||
77 | DoorPi().event_handler.register_event('AfterCallStateDisconnect', __name__) |
||
78 | DoorPi().event_handler.register_event('OnCallStateDismissed', __name__) |
||
79 | DoorPi().event_handler.register_event('OnCallStateReject', __name__) |
||
80 | DoorPi().event_handler.register_event('OnCallStart', __name__) |
||
81 | DoorPi().event_handler.register_event('OnDTMF', __name__) |
||
82 | |||
83 | self.__possible_DTMF = DoorPi().config.get_keys('DTMF') |
||
84 | for DTMF in self.__possible_DTMF: |
||
85 | DoorPi().event_handler.register_event('OnDTMF_'+DTMF, __name__) |
||
86 | |||
87 | DoorPi().event_handler.register_event('OnCallStart', __name__) |
||
88 | DoorPi().event_handler.register_event('BeforeCallIncoming', __name__) |
||
89 | DoorPi().event_handler.register_event('OnCallReconnect', __name__) |
||
90 | DoorPi().event_handler.register_event('AfterCallReconnect', __name__) |
||
91 | DoorPi().event_handler.register_event('OnCallBusy', __name__) |
||
92 | DoorPi().event_handler.register_event('AfterCallBusy', __name__) |
||
93 | DoorPi().event_handler.register_event('OnCallIncoming', __name__) |
||
94 | DoorPi().event_handler.register_event('AfterCallIncoming', __name__) |
||
95 | DoorPi().event_handler.register_event('OnCallReject', __name__) |
||
96 | DoorPi().event_handler.register_event('AfterCallReject', __name__) |
||
97 | #DoorPi().event_handler.register_event('AfterAccountRegState', __name__) |
||
98 | |||
99 | DoorPi().event_handler('OnCallStart', __name__) |
||
100 | |||
101 | def destroy(self): |
||
102 | logger.debug("destroy") |
||
103 | DoorPi().event_handler.unregister_source(__name__, True) |
||
104 | |||
105 | def global_state_changed(self, core, global_state, message): pass |
||
106 | def registration_state_changed(self, core, linphone_proxy_config, state, message): pass |
||
107 | def call_state_changed(self, core, call, call_state, message): |
||
108 | self.call_state_changed_handle(core, call, call_state, message) |
||
109 | |||
110 | if core.calls_nb > 0 and self._last_number_of_calls == 0: |
||
111 | DoorPi().event_handler('OnMediaRequired', __name__) |
||
112 | elif self._last_number_of_calls is not core.calls_nb: |
||
113 | DoorPi().event_handler('OnMediaNotRequired', __name__) |
||
114 | self._last_number_of_calls = core.calls_nb |
||
115 | |||
116 | def call_state_changed_handle(self, core, call, call_state, message): |
||
117 | logger.debug("call_state_changed (%s - %s)", call_state, message) |
||
118 | |||
119 | remote_uri = call.remote_address.as_string_uri_only() |
||
120 | |||
121 | DoorPi().event_handler('OnCallStateChange', __name__, { |
||
122 | 'remote_uri': remote_uri, |
||
123 | 'call_state': call_state, |
||
124 | 'state': message |
||
125 | }) |
||
126 | |||
127 | if call_state == linphone.CallState.Idle: |
||
128 | pass |
||
129 | elif call_state == linphone.CallState.IncomingReceived: |
||
130 | DoorPi().event_handler('BeforeCallIncoming', __name__, {'remote_uri': remote_uri}) |
||
131 | if core.current_call and core.current_call.state > linphone.CallState.IncomingReceived: |
||
132 | logger.debug("Incoming call while another call is active") |
||
133 | logger.debug("- incoming.remote_uri: %s", call) |
||
134 | logger.debug("- current.remote_uri : %s", core.current_call) |
||
135 | |||
136 | if core.current_call.remote_address.as_string_uri_only() == remote_uri: |
||
137 | logger.info("Current call is incoming call - quitting current and connecting to incoming. Maybe connection reset?") |
||
138 | DoorPi().event_handler('OnCallReconnect', __name__, {'remote_uri': remote_uri}) |
||
139 | core.terminate_call(core.current_call) |
||
140 | DoorPi().sipphone.reset_call_start_datetime() |
||
141 | core.accept_call_with_params(call, DoorPi().sipphone.base_config) |
||
142 | DoorPi().event_handler('AfterCallReconnect', __name__) |
||
143 | return |
||
144 | else: |
||
145 | if self.is_admin_number(remote_uri): |
||
146 | logger.info("Incoming and current call are different - incoming is AdminNumber, so hanging up current call") |
||
147 | DoorPi().event_handler('OnCallIncoming', __name__, {'remote_uri': remote_uri}) |
||
148 | core.terminate_call(core.current_call) |
||
149 | DoorPi().sipphone.reset_call_start_datetime() |
||
150 | core.accept_call_with_params(call, DoorPi().sipphone.base_config) |
||
151 | DoorPi().event_handler('AfterCallIncoming', __name__, {'remote_uri': remote_uri}) |
||
152 | return |
||
153 | else: |
||
154 | logger.info("Incoming and current call are different - sending busy signal to incoming call") |
||
155 | DoorPi().event_handler('OnCallBusy', __name__, {'remote_uri': remote_uri}) |
||
156 | core.decline_call(call, linphone.Reason.Busy) |
||
157 | DoorPi().event_handler('AfterCallBusy', __name__) |
||
158 | return |
||
159 | if self.is_admin_number(remote_uri): |
||
160 | DoorPi().event_handler('OnCallIncoming', __name__, {'remote_uri': remote_uri}) |
||
161 | DoorPi().sipphone.reset_call_start_datetime() |
||
162 | core.accept_call_with_params(call, DoorPi().sipphone.base_config) |
||
163 | DoorPi().event_handler('AfterCallIncoming', __name__, {'remote_uri': remote_uri}) |
||
164 | return |
||
165 | else: |
||
166 | DoorPi().event_handler('OnCallReject', __name__) |
||
167 | core.decline_call(call, linphone.Reason.Forbidden) #Declined |
||
168 | DoorPi().event_handler('AfterCallReject', __name__) |
||
169 | return |
||
170 | elif call_state == linphone.CallState.OutgoingInit: |
||
171 | pass |
||
172 | elif call_state == linphone.CallState.OutgoingProgress: |
||
173 | pass |
||
174 | elif call_state == linphone.CallState.OutgoingRinging: |
||
175 | pass |
||
176 | elif call_state == linphone.CallState.OutgoingEarlyMedia: |
||
177 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
178 | elif call_state == linphone.CallState.Connected: |
||
179 | DoorPi().event_handler('OnCallStateConnect', __name__) |
||
180 | elif call_state == linphone.CallState.StreamsRunning: |
||
181 | DoorPi().event_handler('AfterCallStateConnect', __name__) |
||
182 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
183 | elif call_state == linphone.CallState.Pausing: |
||
184 | pass |
||
185 | elif call_state == linphone.CallState.Paused: |
||
186 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
187 | elif call_state == linphone.CallState.Resuming: |
||
188 | DoorPi().event_handler('OnCallStateConnect', __name__) |
||
189 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
190 | elif call_state == linphone.CallState.Refered: |
||
191 | pass |
||
192 | elif call_state == linphone.CallState.Error: |
||
193 | if message == "Busy here": DoorPi().event_handler('OnCallStateDismissed', __name__) |
||
194 | elif call_state == linphone.CallState.End: |
||
195 | if message == "Call declined.": DoorPi().event_handler('OnCallStateReject', __name__) |
||
196 | DoorPi().event_handler('OnCallStateDisconnect', __name__) |
||
197 | elif call_state == linphone.CallState.PausedByRemote: |
||
198 | pass |
||
199 | elif call_state == linphone.CallState.UpdatedByRemote: |
||
200 | pass |
||
201 | elif call_state == linphone.CallState.IncomingEarlyMedia: |
||
202 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
203 | elif call_state == linphone.CallState.Updating: |
||
204 | DoorPi().event_handler('OnCallStateConnect', __name__) |
||
205 | DoorPi().event_handler('OnCallMediaStateChange', __name__) |
||
206 | elif call_state == linphone.CallState.Released: |
||
207 | pass |
||
208 | elif call_state == linphone.CallState.EarlyUpdatedByRemote: |
||
209 | pass |
||
210 | elif call_state == linphone.CallState.EarlyUpdating: |
||
211 | pass |
||
212 | def notify_presence_received(self, core, linphone_friend): pass |
||
213 | def new_subscription_requested(self, core, linphone_friend, url): pass |
||
214 | def auth_info_requested(self, core, realm, username): pass |
||
215 | def call_log_updated(self, core, new_call_log_entry): pass |
||
216 | def message_received(self, core, linphone_chat_room, message): pass |
||
217 | def is_composing_received(self, core, linphone_chat_room): pass |
||
218 | def dtmf_received(self, core, call, digits): |
||
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||
219 | logger.debug("on_dtmf_digit (%s)", str(digits)) |
||
220 | digits = chr(digits) |
||
221 | DoorPi().event_handler('OnDTMF', __name__, {'digits':digits}) |
||
222 | self.__DTMF += str(digits) |
||
223 | for DTMF in self.__possible_DTMF: |
||
224 | if self.__DTMF.endswith(DTMF[1:-1]): |
||
225 | DoorPi().event_handler('OnDTMF_'+DTMF+'', __name__, { |
||
226 | 'remote_uri': str(call.remote_address.as_string_uri_only()), |
||
227 | 'DTMF': str(self.__DTMF) |
||
228 | }) |
||
229 | def refer_received(self, core, refer_to): pass |
||
230 | def call_encryption_changed(self, core, call, on, authentication_token): pass |
||
231 | def transfer_state_changed(self, core, call, transfer_state): pass |
||
232 | def buddy_info_updated(self, core, linphone_friend): pass |
||
233 | def call_stats_updated(self, core, call, stats): pass |
||
234 | def info_received(self, core, call, message): pass |
||
235 | def subscription_state_changed(self, core, linphone_event, linphone_subscription_state): pass |
||
236 | def notify_received(self, core, linphone_event, linphone_subscription_state, linphone_body): pass |
||
237 | def configuring_status(self, core, linphone_configuring_state, message): pass |
||
238 | def network_reachable(self, core, reachable): pass |
||
239 | def log_collection_upload_state_changed(self, core, linphone_core_log_collection_upload_state, info): pass |
||
240 | def log_collection_upload_progress_indication(self, core, offset, total): pass |
||
241 | |||
242 | __del__ = destroy |