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
f853be5a
Commit
f853be5a
authored
Jun 25, 2010
by
Luci Stanescu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for incoming session ringing
parent
1a71a3b9
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
174 additions
and
9 deletions
+174
-9
__init__.py
blink/__init__.py
+4
-0
account.py
blink/configuration/account.py
+24
-0
datatypes.py
blink/configuration/datatypes.py
+46
-2
settings.py
blink/configuration/settings.py
+2
-1
sessions.py
blink/sessions.py
+98
-6
beeping_ringtone.wav
resources/sounds/beeping_ringtone.wav
+0
-0
inbound_ringtone.wav
resources/sounds/inbound_ringtone.wav
+0
-0
outbound_ringtone.wav
resources/sounds/outbound_ringtone.wav
+0
-0
No files found.
blink/__init__.py
View file @
f853be5a
...
...
@@ -11,10 +11,12 @@ from application.notification import IObserver, NotificationCenter
from
application.python.util
import
Null
from
zope.interface
import
implements
from
sipsimple.account
import
Account
,
BonjourAccount
from
sipsimple.application
import
SIPApplication
from
sipsimple.configuration.backend.file
import
FileBackend
from
sipsimple.configuration.settings
import
SIPSimpleSettings
from
blink.configuration.account
import
AccountExtension
,
BonjourAccountExtension
from
blink.configuration.settings
import
SIPSimpleSettingsExtension
from
blink.mainwindow
import
MainWindow
from
blink.resources
import
ApplicationData
...
...
@@ -32,6 +34,8 @@ class Blink(QApplication):
self
.
application
=
SIPApplication
()
self
.
main_window
=
MainWindow
()
Account
.
register_extension
(
AccountExtension
)
BonjourAccount
.
register_extension
(
BonjourAccountExtension
)
SIPSimpleSettings
.
register_extension
(
SIPSimpleSettingsExtension
)
session_manager
=
SessionManager
()
session_manager
.
initialize
(
self
.
main_window
,
self
.
main_window
.
session_model
)
...
...
blink/configuration/account.py
0 → 100644
View file @
f853be5a
# Copyright (C) 2010 AG Projects. See LICENSE for details.
#
"""Blink account settings extensions."""
__all__
=
[
'AccountExtension'
,
'BonjourAccountExtension'
]
from
sipsimple.configuration
import
Setting
,
SettingsGroup
,
SettingsObjectExtension
from
blink.configuration.datatypes
import
CustomSoundFile
,
DefaultPath
class
SoundSettings
(
SettingsGroup
):
inbound_ringtone
=
Setting
(
type
=
CustomSoundFile
,
default
=
CustomSoundFile
(
DefaultPath
),
nillable
=
True
)
class
AccountExtension
(
SettingsObjectExtension
):
sounds
=
SoundSettings
class
BonjourAccountExtension
(
SettingsObjectExtension
):
sounds
=
SoundSettings
blink/configuration/datatypes.py
View file @
f853be5a
...
...
@@ -3,9 +3,10 @@
"""Definitions of datatypes for use in settings extensions."""
__all__
=
[
'ApplicationDataPath'
,
'SoundFile'
]
__all__
=
[
'ApplicationDataPath'
,
'SoundFile'
,
'DefaultPath'
,
'CustomSoundFile'
]
import
os
import
re
from
blink.resources
import
ApplicationData
...
...
@@ -26,7 +27,7 @@ class SoundFile(object):
def
__init__
(
self
,
path
,
volume
=
100
):
self
.
path
=
path
self
.
volume
=
int
(
volume
)
if
self
.
volume
<
0
or
self
.
volume
>
100
:
if
not
(
0
<=
self
.
volume
<=
100
)
:
raise
ValueError
(
'illegal volume level:
%
d'
%
self
.
volume
)
def
__getstate__
(
self
):
...
...
@@ -54,3 +55,46 @@ class SoundFile(object):
del
_get_path
,
_set_path
class
DefaultPath
(
object
):
def
__repr__
(
self
):
return
self
.
__class__
.
__name__
class
CustomSoundFile
(
object
):
def
__init__
(
self
,
path
=
DefaultPath
,
volume
=
100
):
self
.
path
=
path
self
.
volume
=
int
(
volume
)
if
self
.
volume
<
0
or
self
.
volume
>
100
:
raise
ValueError
(
'illegal volume level:
%
d'
%
self
.
volume
)
def
__getstate__
(
self
):
if
self
.
path
is
DefaultPath
:
return
u'default'
else
:
return
u'file:
%
s,
%
s'
%
(
self
.
__dict__
[
'path'
],
self
.
volume
)
def
__setstate__
(
self
,
state
):
match
=
re
.
match
(
r'^(?P<type>default|file:)(?P<path>.+?)?(,(?P<volume>\d+))?$'
,
state
)
if
match
is
None
:
raise
ValueError
(
'illegal value:
%
r'
%
state
)
data
=
match
.
groupdict
()
if
data
.
pop
(
'type'
)
==
'default'
:
data
[
'path'
]
=
DefaultPath
data
[
'volume'
]
=
data
[
'volume'
]
or
100
self
.
__init__
(
**
data
)
def
__repr__
(
self
):
return
'
%
s(
%
r,
%
r)'
%
(
self
.
__class__
.
__name__
,
self
.
path
,
self
.
volume
)
def
_get_path
(
self
):
path
=
self
.
__dict__
[
'path'
]
return
path
if
path
is
DefaultPath
else
ApplicationData
.
get
(
path
)
def
_set_path
(
self
,
path
):
if
path
is
not
DefaultPath
:
path
=
os
.
path
.
normpath
(
path
)
if
path
.
startswith
(
ApplicationData
.
directory
+
os
.
path
.
sep
):
path
=
path
[
len
(
ApplicationData
.
directory
+
os
.
path
.
sep
):]
self
.
__dict__
[
'path'
]
=
path
path
=
property
(
_get_path
,
_set_path
)
del
_get_path
,
_set_path
blink/configuration/settings.py
View file @
f853be5a
...
...
@@ -17,7 +17,8 @@ class AudioSettingsExtension(AudioSettings):
class
SoundSettings
(
SettingsGroup
):
outbound_ringtone
=
Setting
(
type
=
SoundFile
,
default
=
SoundFile
(
Resources
.
get
(
'sounds/ring_outbound.wav'
)),
nillable
=
True
)
inbound_ringtone
=
Setting
(
type
=
SoundFile
,
default
=
SoundFile
(
Resources
.
get
(
'sounds/inbound_ringtone.wav'
)),
nillable
=
True
)
outbound_ringtone
=
Setting
(
type
=
SoundFile
,
default
=
SoundFile
(
Resources
.
get
(
'sounds/outbound_ringtone.wav'
)),
nillable
=
True
)
class
SIPSimpleSettingsExtension
(
SettingsObjectExtension
):
...
...
blink/sessions.py
View file @
f853be5a
...
...
@@ -31,6 +31,7 @@ from sipsimple.session import Session
from
sipsimple.streams
import
MediaStreamRegistry
from
sipsimple.util
import
limit
from
blink.configuration.datatypes
import
DefaultPath
from
blink.resources
import
Resources
from
blink.util
import
call_later
,
run_in_gui_thread
from
blink.widgets.buttons
import
LeftSegment
,
MiddleSegment
,
RightSegment
,
SwitchViewButton
...
...
@@ -971,6 +972,10 @@ class SessionModel(QAbstractListModel):
self
.
session_list
=
parent
.
session_list
self
.
ignore_selection_changes
=
False
@
property
def
active_sessions
(
self
):
return
[
session
for
session
in
self
.
sessions
if
not
session
.
pending_removal
]
def
flags
(
self
,
index
):
if
index
.
isValid
():
return
QAbstractListModel
.
flags
(
self
,
index
)
|
Qt
.
ItemIsDropEnabled
|
Qt
.
ItemIsDragEnabled
|
Qt
.
ItemIsEditable
...
...
@@ -1588,6 +1593,24 @@ class IncomingSession(QObject):
self
.
dialog
.
accepted
.
connect
(
self
.
_SH_DialogAccepted
)
self
.
dialog
.
rejected
.
connect
(
self
.
_SH_DialogRejected
)
def
__eq__
(
self
,
other
):
return
self
is
other
def
__ne__
(
self
,
other
):
return
self
is
not
other
def
__lt__
(
self
,
other
):
return
self
.
priority
<
other
.
priority
def
__le__
(
self
,
other
):
return
self
.
priority
<=
other
.
priority
def
__gt__
(
self
,
other
):
return
self
.
priority
>
other
.
priority
def
__ge__
(
self
,
other
):
return
self
.
priority
>=
other
.
priority
@
property
def
accepted_streams
(
self
):
streams
=
[]
...
...
@@ -1617,6 +1640,35 @@ class IncomingSession(QObject):
def
desktopsharing_accepted
(
self
):
return
self
.
dialog
.
desktopsharing_stream
.
in_use
and
self
.
dialog
.
desktopsharing_stream
.
accepted
@
property
def
priority
(
self
):
if
self
.
audio_stream
:
return
0
elif
self
.
video_stream
:
return
1
elif
self
.
desktopsharing_stream
:
return
2
elif
self
.
chat_stream
:
return
3
else
:
return
4
@
property
def
ringtone
(
self
):
if
'ringtone'
not
in
self
.
__dict__
:
if
self
.
audio_stream
or
self
.
video_stream
or
self
.
desktopsharing_stream
:
sound_file
=
self
.
session
.
account
.
sounds
.
inbound_ringtone
if
sound_file
is
not
None
and
sound_file
.
path
is
DefaultPath
:
settings
=
SIPSimpleSettings
()
sound_file
=
settings
.
sounds
.
inbound_ringtone
ringtone
=
WavePlayer
(
SIPApplication
.
alert_audio_mixer
,
sound_file
.
path
,
volume
=
sound_file
.
volume
,
loop_count
=
0
,
pause_time
=
6
)
if
sound_file
is
not
None
else
Null
ringtone
.
bridge
=
SIPApplication
.
alert_audio_bridge
else
:
ringtone
=
WavePlayer
(
SIPApplication
.
alert_audio_mixer
,
Resources
.
get
(
'sounds/beeping_ringtone.wav'
),
volume
=
70
,
loop_count
=
0
,
pause_time
=
6
)
ringtone
.
bridge
=
SIPApplication
.
alert_audio_bridge
self
.
__dict__
[
'ringtone'
]
=
ringtone
return
self
.
__dict__
[
'ringtone'
]
def
_SH_DialogAccepted
(
self
):
self
.
accepted
.
emit
()
...
...
@@ -1634,10 +1686,12 @@ class SessionManager(object):
self
.
session_model
=
None
self
.
incoming_sessions
=
[]
self
.
dialog_positions
=
range
(
1
,
100
)
self
.
current_ringtone
=
Null
def
initialize
(
self
,
main_window
,
session_model
):
self
.
main_window
=
main_window
self
.
session_model
=
session_model
session_model
.
structureChanged
.
connect
(
self
.
update_ringtone
)
session_model
.
session_list
.
selectionModel
()
.
selectionChanged
.
connect
(
self
.
_SH_SessionListSelectionChanged
)
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
name
=
'SIPSessionNewIncoming'
)
...
...
@@ -1674,6 +1728,38 @@ class SessionManager(object):
self
.
main_window
.
search_box
.
update
()
session_item
.
connect
()
def
update_ringtone
(
self
):
if
not
self
.
incoming_sessions
:
self
.
current_ringtone
=
Null
elif
self
.
session_model
.
active_sessions
:
self
.
current_ringtone
=
self
.
beeping_ringtone
else
:
self
.
current_ringtone
=
self
.
incoming_sessions
[
0
]
.
ringtone
@
property
def
beeping_ringtone
(
self
):
if
'beeping_ringtone'
not
in
self
.
__dict__
:
ringtone
=
WavePlayer
(
SIPApplication
.
voice_audio_mixer
,
Resources
.
get
(
'sounds/beeping_ringtone.wav'
),
volume
=
70
,
loop_count
=
0
,
pause_time
=
6
)
ringtone
.
bridge
=
SIPApplication
.
voice_audio_bridge
self
.
__dict__
[
'beeping_ringtone'
]
=
ringtone
return
self
.
__dict__
[
'beeping_ringtone'
]
def
_get_current_ringtone
(
self
):
return
self
.
__dict__
[
'current_ringtone'
]
def
_set_current_ringtone
(
self
,
ringtone
):
old_ringtone
=
self
.
__dict__
.
get
(
'current_ringtone'
,
Null
)
if
ringtone
is
not
Null
and
ringtone
is
old_ringtone
:
return
old_ringtone
.
stop
()
old_ringtone
.
bridge
.
remove
(
old_ringtone
)
ringtone
.
bridge
.
add
(
ringtone
)
ringtone
.
start
()
self
.
__dict__
[
'current_ringtone'
]
=
ringtone
current_ringtone
=
property
(
_get_current_ringtone
,
_set_current_ringtone
)
del
_get_current_ringtone
,
_set_current_ringtone
@
staticmethod
def
create_stream
(
account
,
type
):
for
cls
in
MediaStreamRegistry
():
...
...
@@ -1713,18 +1799,19 @@ class SessionManager(object):
if
incoming_session
.
dialog
.
position
is
not
None
:
bisect
.
insort_left
(
self
.
dialog_positions
,
incoming_session
.
dialog
.
position
)
self
.
incoming_sessions
.
remove
(
incoming_session
)
self
.
update_ringtone
()
session
=
incoming_session
.
session
if
incoming_session
.
audio_accepted
and
incoming_session
.
video_accepted
:
session_item
=
SessionItem
(
session
.
remote_identity
.
display_name
,
session
.
remote_identity
.
uri
,
session
,
audio_stream
=
incoming_session
.
audio_stream
,
video_stream
=
incoming_session
.
video_stream
)
elif
incoming_session
.
audio_accepted
:
try
:
session_item
=
(
session_item
for
session_item
in
self
.
session_model
.
sessions
if
session_item
.
session
is
session
and
session_item
.
audio_stream
is
None
and
not
session_item
.
pending_removal
)
.
next
()
session_item
=
(
session_item
for
session_item
in
self
.
session_model
.
active_sessions
if
session_item
.
session
is
session
and
session_item
.
audio_stream
is
None
)
.
next
()
session_item
.
audio_stream
=
incoming_session
.
audio_stream
except
StopIteration
:
session_item
=
SessionItem
(
session
.
remote_identity
.
display_name
,
session
.
remote_identity
.
uri
,
session
,
audio_stream
=
incoming_session
.
audio_stream
)
elif
incoming_session
.
video_accepted
:
try
:
session_item
=
(
session_item
for
session_item
in
self
.
session_model
.
sessions
if
session_item
.
session
is
session
and
session_item
.
video_stream
is
None
and
not
session_item
.
pending_removal
)
.
next
()
session_item
=
(
session_item
for
session_item
in
self
.
session_model
.
active_sessions
if
session_item
.
session
is
session
and
session_item
.
video_stream
is
None
)
.
next
()
session_item
.
video_stream
=
incoming_session
.
video_stream
except
StopIteration
:
session_item
=
SessionItem
(
session
.
remote_identity
.
display_name
,
session
.
remote_identity
.
uri
,
session
,
video_stream
=
incoming_session
.
video_stream
)
...
...
@@ -1762,6 +1849,7 @@ class SessionManager(object):
if
incoming_session
.
dialog
.
position
is
not
None
:
bisect
.
insort_left
(
self
.
dialog_positions
,
incoming_session
.
dialog
.
position
)
self
.
incoming_sessions
.
remove
(
incoming_session
)
self
.
update_ringtone
()
if
incoming_session
.
proposal
:
incoming_session
.
session
.
reject_proposal
(
488
)
elif
mode
==
'busy'
:
...
...
@@ -1826,7 +1914,7 @@ class SessionManager(object):
desktopsharing_stream
=
desktopsharing_streams
[
0
]
if
desktopsharing_streams
else
None
dialog
=
IncomingDialog
()
incoming_session
=
IncomingSession
(
dialog
,
session
,
proposal
=
False
,
audio_stream
=
audio_stream
,
video_stream
=
video_stream
,
chat_stream
=
chat_stream
,
desktopsharing_stream
=
desktopsharing_stream
)
self
.
incoming_sessions
.
append
(
incoming_session
)
bisect
.
insort_right
(
self
.
incoming_sessions
,
incoming_session
)
incoming_session
.
accepted
.
connect
(
partial
(
self
.
_SH_IncomingSessionAccepted
,
incoming_session
))
incoming_session
.
rejected
.
connect
(
partial
(
self
.
_SH_IncomingSessionRejected
,
incoming_session
))
from
blink
import
Blink
...
...
@@ -1834,7 +1922,8 @@ class SessionManager(object):
position
=
self
.
dialog_positions
.
pop
(
0
)
except
IndexError
:
position
=
None
incoming_session
.
dialog
.
show
(
activate
=
Blink
()
.
activeWindow
()
is
not
None
,
position
=
position
)
incoming_session
.
dialog
.
show
(
activate
=
Blink
()
.
activeWindow
()
is
not
None
and
self
.
incoming_sessions
.
index
(
incoming_session
)
==
0
,
position
=
position
)
self
.
update_ringtone
()
def
_NH_SIPSessionGotProposal
(
self
,
notification
):
session
=
notification
.
sender
...
...
@@ -1859,7 +1948,7 @@ class SessionManager(object):
desktopsharing_stream
=
desktopsharing_streams
[
0
]
if
desktopsharing_streams
else
None
dialog
=
IncomingDialog
()
incoming_session
=
IncomingSession
(
dialog
,
session
,
proposal
=
True
,
audio_stream
=
audio_stream
,
video_stream
=
video_stream
,
chat_stream
=
chat_stream
,
desktopsharing_stream
=
desktopsharing_stream
)
self
.
incoming_sessions
.
append
(
incoming_session
)
bisect
.
insort_right
(
self
.
incoming_sessions
,
incoming_session
)
incoming_session
.
accepted
.
connect
(
partial
(
self
.
_SH_IncomingSessionAccepted
,
incoming_session
))
incoming_session
.
rejected
.
connect
(
partial
(
self
.
_SH_IncomingSessionRejected
,
incoming_session
))
from
blink
import
Blink
...
...
@@ -1867,7 +1956,8 @@ class SessionManager(object):
position
=
self
.
dialog_positions
.
pop
(
0
)
except
IndexError
:
position
=
None
incoming_session
.
dialog
.
show
(
activate
=
Blink
()
.
activeWindow
()
is
not
None
,
position
=
position
)
incoming_session
.
dialog
.
show
(
activate
=
Blink
()
.
activeWindow
()
is
not
None
and
self
.
incoming_sessions
.
index
(
incoming_session
)
==
0
,
position
=
position
)
self
.
update_ringtone
()
def
_NH_SIPSessionDidFail
(
self
,
notification
):
if
notification
.
data
.
code
!=
487
:
...
...
@@ -1881,6 +1971,7 @@ class SessionManager(object):
bisect
.
insort_left
(
self
.
dialog_positions
,
incoming_session
.
dialog
.
position
)
incoming_session
.
dialog
.
hide
()
self
.
incoming_sessions
.
remove
(
incoming_session
)
self
.
update_ringtone
()
def
_NH_SIPSessionGotRejectProposal
(
self
,
notification
):
if
notification
.
data
.
code
!=
487
:
...
...
@@ -1894,5 +1985,6 @@ class SessionManager(object):
bisect
.
insort_left
(
self
.
dialog_positions
,
incoming_session
.
dialog
.
position
)
incoming_session
.
dialog
.
hide
()
self
.
incoming_sessions
.
remove
(
incoming_session
)
self
.
update_ringtone
()
resources/sounds/beeping_ringtone.wav
0 → 100644
View file @
f853be5a
File added
resources/sounds/inbound_ringtone.wav
0 → 100644
View file @
f853be5a
File added
resources/sounds/
ring_outbound
.wav
→
resources/sounds/
outbound_ringtone
.wav
View file @
f853be5a
File moved
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