Commit 4db1a33c authored by Adrian Georgescu's avatar Adrian Georgescu

Implement auto answer

parent bee71a13
- Auto answer
- Device switching window when detected at runtime
- Dial SIP URIs from the system
- Desktop notifications
......@@ -29,4 +28,3 @@
instance of blink and it publishes its old state on startup
- when accepting a new contact from a presence request it adds the URI but
it is not set as type SIP (it has no type selected)
......@@ -22,7 +22,7 @@ class ContactExtension(ContactExtension):
icon = Setting(type=IconDescriptor, nillable=True, default=None)
alternate_icon = Setting(type=IconDescriptor, nillable=True, default=None)
preferred_media = SharedSetting(type=str, default='audio')
#auto_answer = SharedSetting(type=bool, default=False)
auto_answer = Setting(type=bool, default=False)
class GroupExtension(GroupExtension):
......
......@@ -31,6 +31,8 @@ class AudioSettingsExtension(AudioSettings):
recordings_directory = Setting(type=ApplicationDataPath, default=ApplicationDataPath('recordings'))
sample_rate = Setting(type=SampleRate, default=32000)
echo_canceller = EchoCancellerSettingsExtension
auto_answer_interval = Setting(type=int, default=15)
auto_answer = Setting(type=bool, default=False)
class ChatSettingsExtension(ChatSettings):
......
......@@ -4651,6 +4651,7 @@ class ContactEditorDialog(base_class, ui_class):
self.name_editor.setText(contact.name)
self.icon_selector.init_with_contact(contact)
self.presence.setChecked(contact.presence.subscribe)
self.auto_answer.setChecked(contact.auto_answer)
self.preferred_media.setCurrentIndex(self.preferred_media.findData(contact.preferred_media))
self.accept_button.setText('Ok')
self.accept_button.setEnabled(True)
......@@ -4694,6 +4695,11 @@ class ContactEditorDialog(base_class, ui_class):
contact.presence.policy = 'block'
contact.presence.subscribe = False
if self.auto_answer.isChecked():
contact.auto_answer = True
else:
contact.auto_answer = False
if self.icon_selector.filename is self.icon_selector.NotSelected:
pass
elif self.icon_selector.filename is None:
......
......@@ -195,6 +195,7 @@ class MainWindow(base_class, ui_class):
self.video_devices_group.triggered.connect(self._AH_VideoDeviceChanged)
self.mute_action.triggered.connect(self._SH_MuteButtonClicked)
self.silent_action.triggered.connect(self._SH_SilentButtonClicked)
self.auto_answer_action.triggered.connect(self._SH_AutoAnswerButtonClicked)
# Tools menu actions
self.sip_server_settings_action.triggered.connect(self._AH_SIPServerSettings)
......@@ -741,6 +742,11 @@ class MainWindow(base_class, ui_class):
self.saved_account_state = None
self.account_state.setState(state, note)
def _SH_AutoAnswerButtonClicked(self, answer):
settings = SIPSimpleSettings()
settings.audio.auto_answer = not settings.audio.auto_answer
settings.save()
def _SH_SilentButtonClicked(self, silent):
settings = SIPSimpleSettings()
settings.audio.silent = silent
......@@ -768,6 +774,7 @@ class MainWindow(base_class, ui_class):
settings = SIPSimpleSettings()
self.silent_action.setChecked(settings.audio.silent)
self.silent_button.setChecked(settings.audio.silent)
self.auto_answer_action.setChecked(settings.audio.auto_answer)
self.answering_machine_action.setChecked(settings.answering_machine.enabled)
self.auto_accept_chat_action.setChecked(settings.chat.auto_accept)
self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts)
......@@ -826,6 +833,8 @@ class MainWindow(base_class, ui_class):
if 'audio.silent' in notification.data.modified:
self.silent_action.setChecked(settings.audio.silent)
self.silent_button.setChecked(settings.audio.silent)
if 'audio.auto_answer' in notification.data.modified:
self.auto_answer_action.setChecked(settings.audio.auto_answer)
if 'audio.output_device' in notification.data.modified:
action = next(action for action in self.output_devices_group.actions() if action.data() == settings.audio.output_device)
action.setChecked(True)
......
......@@ -5142,6 +5142,11 @@ class IncomingDialog(IncomingDialogBase, ui_class):
self.reject_button.released.connect(self._set_reject_mode)
self.screensharing_stream.hidden.connect(self.screensharing_label.hide)
self.screensharing_stream.shown.connect(self.screensharing_label.show)
self.auto_answer_label.setText('Auto-answer is inactive')
self.auto_answer_interval = None
self._auto_answer_timer = None
self.passed_time = 0
self.auto_answer_confirmed = False
def show(self, activate=True):
self.setAttribute(Qt.WA_ShowWithoutActivating, not activate)
......@@ -5167,6 +5172,22 @@ class IncomingDialog(IncomingDialogBase, ui_class):
if self.accept_button.isEnabled() != was_enabled:
self.accept_button.setFocus()
def setAutoAnswer(self, interval):
self.auto_answer_interval = interval
self._auto_answer_timer = QTimer()
self._auto_answer_timer.setInterval(1000)
self._auto_answer_timer.timeout.connect(self._update_auto_answer)
self._auto_answer_timer.start()
self.auto_answer_label.setText('Auto answer in %d seconds' % interval)
def _update_auto_answer(self):
self.passed_time = self.passed_time + 1
remaining_time = self.auto_answer_interval - self.passed_time
self.auto_answer_label.setText('Auto answer in %d seconds' % remaining_time)
if remaining_time == 0:
self._auto_answer_timer.stop()
self.hide()
def _update_streams_layout(self):
if len([stream for stream in self.streams if stream.in_use]) > 1:
self.audio_stream.active = True
......@@ -5210,6 +5231,7 @@ class IncomingRequest(QObject):
self.video_stream = video_stream
self.chat_stream = chat_stream
self.screensharing_stream = screensharing_stream
self._auto_answer_timer = None
if proposal:
self.dialog.setWindowTitle('Incoming Session Update')
......@@ -5219,6 +5241,16 @@ class IncomingRequest(QObject):
address = '%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host)
self.dialog.uri_label.setText(address)
self.dialog.username_label.setText(contact.name or session.remote_identity.display_name or address)
settings = SIPSimpleSettings()
if settings.audio.auto_answer and contact and contact.settings.auto_answer and settings.audio.auto_answer_interval:
self.dialog.setAutoAnswer(settings.audio.auto_answer_interval)
self._auto_answer_timer = QTimer()
self._auto_answer_timer.setInterval(settings.audio.auto_answer_interval * 1000)
self._auto_answer_timer.setSingleShot(True)
self._auto_answer_timer.timeout.connect(self._auto_answer)
self._auto_answer_timer.start()
self.dialog.user_icon.setPixmap(contact.icon.pixmap(48))
self.dialog.audio_stream.setVisible(self.audio_stream is not None)
self.dialog.video_stream.setVisible(self.video_stream is not None)
......@@ -5231,6 +5263,7 @@ class IncomingRequest(QObject):
self.dialog.screensharing_label.setText('is asking to share your screen')
# self.dialog.screensharing_stream.accepted = bool(proposal)
self.dialog.finished.connect(self._SH_DialogFinished)
def __eq__(self, other):
......@@ -5297,7 +5330,13 @@ class IncomingRequest(QObject):
def stream_types(self):
return {stream.type for stream in (self.audio_stream, self.video_stream, self.screensharing_stream, self.chat_stream) if stream is not None}
def _auto_answer(self):
self._SH_DialogFinished(QDialog.Accepted)
def _SH_DialogFinished(self, result):
if self._auto_answer_timer and self._auto_answer_timer.isActive():
self._auto_answer_timer.stop()
self.finished.emit(self)
if result == QDialog.Accepted:
self.accepted.emit(self)
......
......@@ -1054,7 +1054,7 @@ padding: 2px;</string>
<x>0</x>
<y>0</y>
<width>285</width>
<height>29</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="blink_menu">
......@@ -1173,6 +1173,7 @@ padding: 2px;</string>
<addaction name="separator"/>
<addaction name="mute_action"/>
<addaction name="silent_action"/>
<addaction name="auto_answer_action"/>
</widget>
<widget class="QMenu" name="window_menu">
<property name="title">
......@@ -1281,10 +1282,6 @@ padding: 2px;</string>
</property>
</action>
<action name="redial_action">
<property name="icon">
<iconset>
<normaloff>icons/retry.svg</normaloff>icons/retry.svg</iconset>
</property>
<property name="text">
<string>&amp;Redial</string>
</property>
......@@ -1424,6 +1421,17 @@ padding: 2px;</string>
<enum>Qt::ApplicationShortcut</enum>
</property>
</action>
<action name="auto_answer_action">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>Auto-answer</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......
......@@ -220,16 +220,6 @@
</attribute>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="presence">
<property name="text">
<string>Exchange Availability Information</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QComboBox" name="preferred_media">
<property name="sizePolicy">
......@@ -260,6 +250,23 @@
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="presence">
<property name="text">
<string>Enable Presence</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="auto_answer">
<property name="text">
<string>Auto-answer</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
......
......@@ -6,20 +6,20 @@
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>170</height>
<width>583</width>
<height>191</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>170</height>
<height>188</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>170</height>
<height>300</height>
</size>
</property>
<property name="windowTitle">
......@@ -29,10 +29,7 @@
<iconset>
<normaloff>icons/blink48.png</normaloff>icons/blink48.png</iconset>
</property>
<layout class="QVBoxLayout" name="dialog_layout">
<property name="spacing">
<number>32</number>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>8</number>
</property>
......@@ -45,7 +42,7 @@
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<property name="styleSheet">
<string>QFrame#frame {
......@@ -188,7 +185,7 @@
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
<pointsize>14</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
......@@ -531,7 +528,26 @@
</layout>
</widget>
</item>
<item>
<item row="1" column="0">
<widget class="QLabel" name="auto_answer_label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Auto answer in 10 seconds</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="button_layout">
<property name="spacing">
<number>5</number>
......@@ -564,7 +580,7 @@
<string>Refuse the call but leave other devices ringing</string>
</property>
<property name="text">
<string>Busy</string>
<string>Busy here</string>
</property>
</widget>
</item>
......@@ -609,7 +625,6 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>accept_button</tabstop>
<tabstop>reject_button</tabstop>
<tabstop>busy_button</tabstop>
</tabstops>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment