-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAnsweringMachine.py
170 lines (138 loc) · 7.27 KB
/
AnsweringMachine.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Copyright (C) 2009-2011 AG Projects. See LICENSE for details.
#
from AppKit import NSApp
import datetime
import os
import uuid
import urllib
from application.notification import IObserver, NotificationCenter, NotificationData
from application.python import Null
from zope.interface import implements
from sipsimple.audio import WavePlayer
from sipsimple.application import SIPApplication
from sipsimple.configuration.settings import SIPSimpleSettings
from sipsimple.threading.green import run_in_green_thread
from sipsimple.util import ISOTimestamp
from BlinkLogger import BlinkLogger
from HistoryManager import ChatHistory
from resources import Resources
from util import allocate_autorelease_pool, format_identity_to_string
class AnsweringMachine(object):
implements(IObserver)
def __init__(self, session, audio_stream):
self.session = session
self.stream = audio_stream
self.start_time = None
notification_center = NotificationCenter()
notification_center.add_observer(self, sender=self.stream)
self.beep = WavePlayer(SIPApplication.voice_audio_mixer, Resources.get('answering_machine_tone.wav'))
notification_center.add_observer(self, sender=self.beep)
message_wav = SIPSimpleSettings().answering_machine.unavailable_message
if message_wav:
self.unavailable_message = WavePlayer(SIPApplication.voice_audio_mixer, message_wav.sound_file.path, message_wav.sound_file.volume, 1, 2, False)
notification_center.add_observer(self, sender=self.unavailable_message)
self.stream.bridge.add(self.unavailable_message)
else:
self.unavailable_message = None
self.stream.bridge.add(self.beep)
self.stream.device.input_muted = True
def mute_output(self):
BlinkLogger().log_info(u"Mute output of Answering Machine")
self.stream.device.output_muted = True
def unmute_output(self):
BlinkLogger().log_info(u"Unmute output of Answering Machine")
self.stream.device.output_muted = False
def start(self):
if self.unavailable_message:
self.unavailable_message.start()
else:
self.beep.start()
@property
def duration(self):
return (datetime.datetime.now() - self.start_time).seconds if self.start_time else None
def stop(self):
# Stop the answering machine and allow user to take the call
notification_center = NotificationCenter()
notification_center.remove_observer(self, sender=self.stream)
notification_center.remove_observer(self, sender=self.beep)
self.beep.stop()
self.beep = None
if self.unavailable_message:
notification_center.remove_observer(self, sender=self.unavailable_message)
self.unavailable_message.stop()
self.unavailable_message = None
self.stream.device.input_muted = False
if self.stream.recorder is not None:
self.stream.stop_recording()
@allocate_autorelease_pool
def handle_notification(self, notification):
handler = getattr(self, '_NH_%s' % notification.name, Null)
handler(notification)
def _NH_WavePlayerDidEnd(self, notification):
if notification.sender is self.unavailable_message:
# once message is played, beep
self.stream.bridge.remove(self.unavailable_message)
self.stream.bridge.add(self.beep)
self.beep.start()
elif notification.sender is self.beep:
# start recording after the beep
settings = SIPSimpleSettings()
self.stream.bridge.remove(self.beep)
direction = self.session.direction
remote = "%s@%s" % (self.session.remote_identity.uri.user, self.session.remote_identity.uri.host)
filename = "%s-%s-%s.wav" % (datetime.datetime.now().strftime("%Y%m%d-%H%M%S"), remote, direction)
path = os.path.join(settings.audio.directory.normalized, self.session.account.id)
self.stream.start_recording(os.path.join(path, filename))
self.start_time = datetime.datetime.now()
def _NH_MediaStreamDidFail(self, notification):
notification_center = NotificationCenter()
notification_center.remove_observer(self, sender=self.stream)
notification_center.remove_observer(self, sender=self.beep)
self.beep.stop()
self.beep = None
if self.unavailable_message:
notification_center.remove_observer(self, sender=self.unavailable_message)
self.unavailable_message.stop()
self.unavailable_message = None
def _NH_MediaStreamWillEnd(self, notification):
notification_center = NotificationCenter()
notification_center.remove_observer(self, sender=self.beep)
self.beep.stop()
self.beep = None
if self.unavailable_message:
notification_center.remove_observer(self, sender=self.unavailable_message)
self.unavailable_message.stop()
self.unavailable_message = None
def _NH_MediaStreamDidEnd(self, notification):
notification_center = NotificationCenter()
notification_center.remove_observer(self, sender=self.stream)
def _NH_AudioStreamDidStartRecordingAudio(self, notification):
BlinkLogger().log_info(u"Recording message from %s" % self.session.remote_identity)
def _NH_AudioStreamDidStopRecordingAudio(self, notification):
BlinkLogger().log_info(u"Message from %s finished recording (duration: %s seconds)" % (self.session.remote_identity, self.duration))
self.addAnsweringMachineRecordingToHistory(notification.data.filename, self.duration)
data = NotificationData(filename=notification.data.filename)
NotificationCenter().post_notification("AnsweringMachineRecordingDidEnd", sender=self.session, data=data)
def addAnsweringMachineRecordingToHistory(self, filename, duration):
message = "<h3>Answering Machine Recording</h3>"
message += "<p>%s" % filename
message += "<br>Duration: %s seconds" % duration
message += "<p><audio src='%s' controls='controls'>" % urllib.quote(filename)
media_type = 'voicemail'
local_uri = format_identity_to_string(self.session.account)
remote_uri = format_identity_to_string(self.session.remote_identity)
direction = 'incoming'
status = 'delivered'
cpim_from = format_identity_to_string(self.session.remote_identity)
cpim_to = format_identity_to_string(self.session.remote_identity)
timestamp = str(ISOTimestamp.now())
self.add_to_history(media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, status)
@run_in_green_thread
def add_to_history(self, media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, status):
try:
controller = (controller for controller in NSApp.delegate().contactsWindowController.sessionControllersManager.sessionControllers if controller.session == self.session).next()
except StopIteration:
history_id = str(uuid.uuid1())
else:
history_id = controller.history_id
ChatHistory().add_message(history_id, media_type, local_uri, remote_uri, direction, cpim_from, cpim_to, timestamp, message, "html", "0", status)