Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vmj-qt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
vmj-qt
Commits
4db1a33c
Commit
4db1a33c
authored
Jun 22, 2021
by
Adrian Georgescu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement auto answer
parent
bee71a13
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
116 additions
and
32 deletions
+116
-32
TODO
TODO
+0
-2
addressbook.py
blink/configuration/addressbook.py
+1
-1
settings.py
blink/configuration/settings.py
+2
-0
contacts.py
blink/contacts.py
+6
-0
mainwindow.py
blink/mainwindow.py
+9
-0
sessions.py
blink/sessions.py
+40
-1
blink.ui
resources/blink.ui
+13
-5
contact_editor.ui
resources/contact_editor.ui
+17
-10
incoming_dialog.ui
resources/incoming_dialog.ui
+28
-13
No files found.
TODO
View file @
4db1a33c
- 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)
blink/configuration/addressbook.py
View file @
4db1a33c
...
...
@@ -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 = Shared
Setting(type=bool, default=False)
auto_answer
=
Setting
(
type
=
bool
,
default
=
False
)
class
GroupExtension
(
GroupExtension
):
...
...
blink/configuration/settings.py
View file @
4db1a33c
...
...
@@ -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
):
...
...
blink/contacts.py
View file @
4db1a33c
...
...
@@ -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
:
...
...
blink/mainwindow.py
View file @
4db1a33c
...
...
@@ -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
)
...
...
blink/sessions.py
View file @
4db1a33c
...
...
@@ -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,8 +5263,9 @@ 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
)
self
.
dialog
.
finished
.
connect
(
self
.
_SH_DialogFinished
)
def
__eq__
(
self
,
other
):
return
self
is
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
)
...
...
resources/blink.ui
View file @
4db1a33c
...
...
@@ -1054,7 +1054,7 @@ padding: 2px;</string>
<x>
0
</x>
<y>
0
</y>
<width>
285
</width>
<height>
2
9
</height>
<height>
2
5
</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>
&
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>
...
...
resources/contact_editor.ui
View file @
4db1a33c
...
...
@@ -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>
...
...
resources/incoming_dialog.ui
View file @
4db1a33c
...
...
@@ -6,20 +6,20 @@
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
480
</width>
<height>
1
70
</height>
<width>
583
</width>
<height>
1
91
</height>
</rect>
</property>
<property
name=
"minimumSize"
>
<size>
<width>
480
</width>
<height>
1
70
</height>
<height>
1
88
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
16777215
</width>
<height>
17
0
</height>
<height>
30
0
</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>
1
2
</pointsize>
<pointsize>
1
4
</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>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment