SipMiddlewareApi » History » Version 28
Adrian Georgescu, 03/31/2009 04:49 PM
1 | 1 | Adrian Georgescu | = Middleware API = |
---|---|---|---|
2 | |||
3 | [[TOC(WikiStart, Sip*, depth=3)]] |
||
4 | 11 | Adrian Georgescu | [[Image(sipsimple-middleware.png, align=right, 400px)]] |
5 | 1 | Adrian Georgescu | |
6 | 21 | Adrian Georgescu | This chapter describes the event driven middleware API that can be used by a developer to build a user interface for SIP SIMPLE client library. |
7 | 14 | Adrian Georgescu | |
8 | 25 | Adrian Georgescu | * To communicate with other sub-systems, the middleware uses the notification system provided by the [http://pypi.python.org/pypi/python-application python-application] package |
9 | * The middleware use the [wiki:SipSettingsAPI configuration API] to access general and SIP account settings |
||
10 | |||
11 | 1 | Adrian Georgescu | |
12 | == Classes == |
||
13 | |||
14 | === SessionManager === |
||
15 | |||
16 | The {{{sipsimple.session.SessionManager}}} class is a singleton which acts as the central aggregation point for sessions within the middleware. |
||
17 | 17 | Ruud Klaver | Although it is mainly used internally, the application can use it to query information about all active sessions. |
18 | The SessionManager is implemented as a singleton, meaning that only one instance of this class exists within the middleware. |
||
19 | 19 | Ruud Klaver | Note that, in order to be able to receive calls, the application has to instantiate this object. |
20 | 1 | Adrian Georgescu | |
21 | ==== attributes ==== |
||
22 | |||
23 | '''sessions''':: |
||
24 | A property providing a copy of the list of all active {{{Sesssion}}} objects within the application, meaning any {{{Session}}} object that exists globally within the application and is not in the {{{NULL}}} or {{{TERMINATED}}} state. |
||
25 | |||
26 | ==== methods ==== |
||
27 | |||
28 | '''!__init!__'''(''self''):: |
||
29 | This either returns a new {{{SessionManager}}} object with default configuration objects, or returns a copy of the already existing instance. |
||
30 | |||
31 | === Session === |
||
32 | |||
33 | A {{{sipsimple.session.Session}}} object represents a complete SIP session between the local and a remote endpoints, including media streams. |
||
34 | The currently supported media streams are audio and MSRP chat. |
||
35 | Both incoming and outgoing sessions are represented by this class. |
||
36 | |||
37 | A {{{Session}}} instance is a stateful object, meaning that it has a {{{state}}} attribute and that the lifetime of the session traverses different states, from session creation to termination. |
||
38 | State changes are triggered by methods called on the object by the application or by received network events. |
||
39 | 26 | Luci Stanescu | Every time this attribute changes, a {{{SIPSessionChangedState}}} notification is sent by the object. |
40 | 1 | Adrian Georgescu | These states and their transitions are represented in the following diagram: |
41 | |||
42 | 2 | Adrian Georgescu | [[Image(sipsimple-session-state-machine.png)]] |
43 | 1 | Adrian Georgescu | |
44 | Although these states are crucial to the correct operation of the {{{Session}}} object, an application using this object does not need to keep track of these states, as a different set of notifications is also emitted, which provide all the necessary information to the application. |
||
45 | |||
46 | ==== attributes ==== |
||
47 | |||
48 | '''state''':: |
||
49 | The state the object is currently in, being one of the states from the diagram above. |
||
50 | 18 | Ruud Klaver | '''account''':: |
51 | The {{{sipsimple.account.Account}}} or {{{sipsimple.account.BonjourAccount}}} object that the {{{Session}}} is associated with. |
||
52 | On an outbound session, this is the account the application specified on object instantiation. |
||
53 | 1 | Adrian Georgescu | '''direction''':: |
54 | A string indicating the direction of the initial negotiation of the session. |
||
55 | This can be either {{{None}}}, "incoming" or "outgoing". |
||
56 | '''start_time''':: |
||
57 | The time the session started as a {{{datetime.datetime}}} object, or {{{None}}} if the session was not yet started. |
||
58 | '''stop_time''':: |
||
59 | The time the session stopped as a {{{datetime.datetime}}} object, or {{{None}}} if the session has not yet terminated. |
||
60 | '''on_hold_by_local''':: |
||
61 | Boolean indicating whether the session was put on hold by the local party. |
||
62 | '''on_hold_by_remote''':: |
||
63 | Boolean indicating whether the session was put on hold by the remote party. |
||
64 | '''on_hold''':: |
||
65 | Boolean indicating whether the session was put on hold, either by the local or the remote party. |
||
66 | '''remote_user_agent''':: |
||
67 | A string indicating the remote user agent, if it provided one. |
||
68 | Initially this will be {{{None}}}, it will be set as soon as this information is received from the remote party (which may be never). |
||
69 | '''local_uri''':: |
||
70 | The {{{sipsimple.core.SIPURI}}} of the local party, if the session is active. |
||
71 | '''remote_uri''':: |
||
72 | The {{{sipsimple.core.SIPURI}}} of the remote party, if the session is active. |
||
73 | '''caller_uri''':: |
||
74 | The {{{sipsimple.core.SIPURI}}} of the calling party, if the session is active. |
||
75 | Depending on the direction, this is either {{{local_uri}}} or {{{remote_uri}}}. |
||
76 | '''callee_uri''':: |
||
77 | The {{{sipsimple.core.SIPURI}}} of the called party, if the session is active. |
||
78 | Depending on the direction, this is either {{{local_uri}}} or {{{remote_uri}}}. |
||
79 | '''route''':: |
||
80 | 20 | Ruud Klaver | A copy of the {{{sipsimple.core.Route}}} object passed when the {{{connect()}}} method was called. |
81 | 1 | Adrian Georgescu | On incoming or inactive sessions this is {{{None}}}. |
82 | '''audio_transport''':: |
||
83 | The {{{sipsimple.core.AudioTransport}}} object used by the session, if it currently contains an audio stream. |
||
84 | Normally the application will not need to access this directly. |
||
85 | '''has_audio''':: |
||
86 | 23 | Ruud Klaver | A boolean indicating if this {{{Session}}} currently has an active audio stream. |
87 | 1 | Adrian Georgescu | '''audio_sample_rate''':: |
88 | If the audio stream was started, this attribute contains the sample rate of the audio negotiated. |
||
89 | '''audio_codec''':: |
||
90 | If the audio stream was started, this attribute contains the name of the audio codec that was negotiated. |
||
91 | '''audio_srtp_active''':: |
||
92 | If the audio stream was started, this boolean attribute indicates if SRTP is currently being used on the stream. |
||
93 | '''audio_local_rtp_address''':: |
||
94 | If an audio stream is present within the session, this attribute contains the local IP address used for the audio stream. |
||
95 | '''audio_local_rtp_port''':: |
||
96 | If an audio stream is present within the session, this attribute contains the local UDP port used for the audio stream. |
||
97 | '''audio_remote_rtp_address_sdp''':: |
||
98 | If the audio stream was started, this attribute contains the IP address that the remote party gave to send audio to. |
||
99 | '''audio_remote_rtp_port_sdp''':: |
||
100 | If the audio stream was started, this attribute contains the UDP port that the remote party gave to send audio to. |
||
101 | '''audio_remote_rtp_address_received''':: |
||
102 | If the audio stream was started, this attribute contains the remote IP address from which the audio stream is being received. |
||
103 | '''audio_remote_rtp_port_received''':: |
||
104 | If the audio stream was started, this attribute contains the remote UDP port from which the audio stream is being received. |
||
105 | '''audio_was_received''':: |
||
106 | This boolean property indicates if audio was actually received on the audio stream contained within this session. |
||
107 | '''audio_recording_file_name''':: |
||
108 | If the audio stream is currently being recorded to disk, this property contains the name of the {{{.wav}}} file being recorded to. |
||
109 | '''chat_transport''':: |
||
110 | The {{{sipsimple.msrp.MSRPChat}}} object used by the session as chat transport, if the session currently contains a chat stream. |
||
111 | Normally the application will not need to access this directly. |
||
112 | '''has_chat''':: |
||
113 | 23 | Ruud Klaver | A boolean property indicating if this {{{Session}}} currently has an active chat stream. |
114 | 1 | Adrian Georgescu | |
115 | ==== methods ==== |
||
116 | |||
117 | 18 | Ruud Klaver | '''!__init!__'''(''self'', '''account'''):: |
118 | 1 | Adrian Georgescu | Creates a new {{{Session}}} object in the {{{NULL}}} state. |
119 | 19 | Ruud Klaver | [[BR]]''account'':[[BR]] |
120 | The local account to be associated with this {{{Session}}}. |
||
121 | '''connect'''(''self'', '''callee_uri''', '''routes''', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
||
122 | 1 | Adrian Georgescu | Will set up the {{{Session}}} as outbound and propose the new session to the specified remote party and move the state machine to the {{{CALLING}}} state. |
123 | 26 | Luci Stanescu | Before contacting the remote party, a {{{SIPSessionNewOutgoing}}} notification will be emitted. |
124 | If there is a failure or the remote party rejected the offer, a {{{SIPSessionDidFail}}} notification will be sent, followed by a {{{SIPSessionDidEnd}}}. |
||
125 | Any time a ringing indication is received from the remote party, a {{{SIPSessionGotRingIndication}}} notification is sent. |
||
126 | If the remote party accepted the session, a {{{SIPSessionWillStart}}} notification will be sent, followed by a {{{SIPSessionDidStart}}} notification when the session is actually established. |
||
127 | 1 | Adrian Georgescu | This method may only be called while in the {{{NULL}}} state. |
128 | [[BR]]''callee_uri'':[[BR]] |
||
129 | A {{{sipsimple.core.SIPURI}}} object representing the remote host to initiate the session to. |
||
130 | 19 | Ruud Klaver | [[BR]]''routes'':[[BR]] |
131 | An iterable of {{{sipsimple.core.Route}}} objects, specifying the IP, port and transport to the outbound proxy. |
||
132 | These routes will be tried in order, until one of them succeeds. |
||
133 | 1 | Adrian Georgescu | [[BR]]''audio'':[[BR]] |
134 | A boolean indicating whether an audio stream should be initially included in this session. |
||
135 | [[BR]]''chat'':[[BR]] |
||
136 | A boolean indicating whether a chat stream should be initially included in this session. |
||
137 | 19 | Ruud Klaver | '''accept'''(''self'', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
138 | 1 | Adrian Georgescu | Calling this methods will accept an incoming session and move the state machine to the {{{ACCEPTING}}} state. |
139 | 26 | Luci Stanescu | When there is a new incoming session, a {{{SIPSessionNewIncoming}}} notification is sent, after which the application can call this method on the sender of the notification. |
140 | After this method is called, {{{SIPSessionWillStart}}} followed by {{{SIPSessionDidStart}}} will be emitted, or {{{SIPSessionDidFail}}} followed by {{{SIPSessionDidEnd}}} on an error. |
||
141 | 1 | Adrian Georgescu | This method may only be called while in the {{{INCOMING}}} state. |
142 | [[BR]]''audio'':[[BR]] |
||
143 | A boolean indicating whether an audio stream should be accepted for this session. |
||
144 | Note that this may only be set to {{{True}}} if an audio stream was actually proposed by the remote party. |
||
145 | [[BR]]''chat'':[[BR]] |
||
146 | A boolean indicating whether a chat stream should be accepted for this session. |
||
147 | Note that this may only be set to {{{True}}} if a chat stream was actually proposed by the remote party. |
||
148 | '''reject'''(''self''):: |
||
149 | Reject an incoming session and move it to the {{{TERMINATING}}} state, which eventually leads to the {{{TERMINATED}}} state. |
||
150 | 26 | Luci Stanescu | Calling this method will cause the {{{Session}}} object to emit a {{{SIPSessionWillEnd}}} notification, followed by a {{{SIPSessionDidEnd}}} notification. |
151 | 1 | Adrian Georgescu | This method may only be called while in the {{{INCOMING}}} state. |
152 | '''hold'''(''self''):: |
||
153 | Put the session on hold. |
||
154 | 26 | Luci Stanescu | This will cause a {{{SIPGotHoldRequest}}} notification to be sent. |
155 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
156 | '''unhold'''(''self''):: |
||
157 | Take the session out of hold. |
||
158 | 26 | Luci Stanescu | This will cause a {{{SIPGotUnholdRequest}}} notification to be sent. |
159 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
160 | 19 | Ruud Klaver | '''start_recording_audio'''(''self'', '''file_name'''={{{None}}}):: |
161 | 1 | Adrian Georgescu | If an audio stream is present within this session, calling this method will record the audio to a {{{.wav}}} file. |
162 | Note that when the session is on hold, nothing will be recorded to the file. |
||
163 | 26 | Luci Stanescu | Right before starting the recording a {{{SIPSessionWillStartRecordingAudio}}} notification will be emitted, followed by a {{{SIPSessionDidStartRecordingAudio}}}. |
164 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
165 | [[BR]]''file_name'':[[BR]] |
||
166 | The name of the {{{.wav}}} file to record to. |
||
167 | If this is set to {{{None}}}, a default file name including the session participants and the timestamp will be generated. |
||
168 | '''stop_recording_audio'''(''self''):: |
||
169 | This will stop a previously started recording. |
||
170 | 26 | Luci Stanescu | Before stopping, a {{{SIPSessionWillStopRecordingAudio}}} notification will be sent, followed by a {{{SIPSessionDidStopRecordingAudio}}}. |
171 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
172 | '''send_dtmf'''(''self'', '''digit'''):: |
||
173 | If this session currently has an active audio stream, send a DTMF digit to the remote party over it. |
||
174 | 23 | Ruud Klaver | This method may only be called while in the {{{ESTABLISHED}}} state and if the session has an active audio stream. |
175 | 1 | Adrian Georgescu | [[BR]]''digit'':[[BR]] |
176 | This should a string of length 1, containing a valid DTMF digit value. |
||
177 | 13 | Luci Stanescu | '''send_message'''(''self'', '''content''', '''content_type'''="text/plain", '''to_uri'''={{{None}}}, '''dt'''={{{None}}}):: |
178 | 1 | Adrian Georgescu | If this session currently has an active MSRP chat with the remote party, send a message over with the with the specified parameters. |
179 | 26 | Luci Stanescu | This will result in either a {{{SIPSessionDidDeliverMessage}}} or a {{{SIPSessionDidNotDeliverMessage}}} notification being sent. |
180 | 1 | Adrian Georgescu | These notifications include a unique ID as data attribute which is also returned by this method. |
181 | This method may only be called while in the {{{ESTABLISHED}}} state. |
||
182 | [[BR]]''content'':[[BR]] |
||
183 | The body of the MSRP message as a string. |
||
184 | [[BR]]''content_type'':[[BR]] |
||
185 | The Content-Type of the body as a string |
||
186 | 22 | Ruud Klaver | [[BR]]''to_uri'':[[BR]] |
187 | 1 | Adrian Georgescu | The {{{sipsimple.core.SIPURI}}} that should be put in the {{{To:}}} header of the CPIM wrapper of the message. |
188 | This defaults to the SIP URI of the remote party of the session if the argument is set to {{{None}}} |
||
189 | [[BR]]''dt'':[[BR]] |
||
190 | A {{{datetime.datetime}}} object representing the timestamp to put on the CPIM wrapper of the message. |
||
191 | When set to {{{None}}}, this defaults to now. |
||
192 | '''add_audio'''(''self''):: |
||
193 | Propose the remote party to add an audio stream to this session. |
||
194 | 26 | Luci Stanescu | Calling this method will cause a {{{SIPSessionGotStreamProposal}}} notification to be emitted. |
195 | After this, the state machine will move into the {{{PROPOSING}}} state until either a {{{SIPSessionAcceptedStreamProposal}}} or {{{SIPSessionRejectedStreamProposal}}} notification is sent, informing the application if the remote party accepted the proposal. |
||
196 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that does not currently have an audio stream. |
197 | '''remove_audio'''(''self''):: |
||
198 | Stop the audio stream currently active within the session and inform the remote party of this. |
||
199 | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that has an audio stream. |
||
200 | '''add_chat'''(''self''):: |
||
201 | Propose the remote party to add a chat stream to this session. |
||
202 | 26 | Luci Stanescu | Calling this method will cause a {{{SIPSessionGotStreamProposal}}} notification to be emitted. |
203 | After this, the state machine will move into the {{{PROPOSING}}} state until either a {{{SIPSessionAcceptedStreamProposal}}} or {{{SIPSessionRejectedStreamProposal}}} notification is sent, informing the application if the remote party accepted the proposal. |
||
204 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that does not currently have a chat stream. |
205 | '''remove_chat'''(''self''):: |
||
206 | Stop the chat stream currently active within the session and inform the remote party of this. |
||
207 | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that has a chat stream. |
||
208 | 19 | Ruud Klaver | '''accept_proposal'''(''self'', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
209 | 26 | Luci Stanescu | When the remote party proposes to add a new stream, signaled by the {{{SIPSessionGotStreamProposal}}} notification, the application can use this method to accept the stream(s) being proposed. |
210 | After calling this method a {{{SIPSessionAcceptedStreamProposal}}} notification is sent, unless an error occurs while setting up the new stream, in which case a {{{SIPSessionRejectedStreamProposal}}} notification is sent and a rejection is sent to the remote party. |
||
211 | 1 | Adrian Georgescu | This method may only be called while in the {{{PROPOSED}}} state. |
212 | 19 | Ruud Klaver | [[BR]]''audio'':[[BR]] |
213 | A boolean indicating whether an audio stream should be accepted for this proposal. |
||
214 | Note that this may only be set to {{{True}}} if an audio stream was actually proposed by the remote party. |
||
215 | [[BR]]''chat'':[[BR]] |
||
216 | A boolean indicating whether a chat stream should be accepted for this proposal. |
||
217 | Note that this may only be set to {{{True}}} if a chat stream was actually proposed by the remote party. |
||
218 | 1 | Adrian Georgescu | '''reject_proposal'''(''self''):: |
219 | 26 | Luci Stanescu | When the remote party proposes (a) stream(s) that the application does not want to accept, this method can be used to reject the proposal, after which a {{{SIPSessionRejectedStreamProposal}}} notification is sent. |
220 | 1 | Adrian Georgescu | This method may only be called while in the {{{PROPOSED}}} state. |
221 | 23 | Ruud Klaver | '''end'''(''self''):: |
222 | 1 | Adrian Georgescu | This method may be called any time when the {{{Session}}} object is active (i.e. not in the {{{NULL}}}, {{{TERMINATING}}} or {{{TERMINATED}}} states) in order to terminate the session. |
223 | 26 | Luci Stanescu | Right before termination a {{{SIPSessionWillEnd}}} notification is sent, after termination {{{SIPSessionDidEnd}}} is sent. |
224 | 1 | Adrian Georgescu | |
225 | ==== notifications ==== |
||
226 | |||
227 | 26 | Luci Stanescu | '''SIPSessionChangedState''':: |
228 | 1 | Adrian Georgescu | Will be sent whenever the {{{Session}}} object changes its state. |
229 | [[BR]]''timestamp'':[[BR]] |
||
230 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
231 | [[BR]]''prev_state'':[[BR]] |
||
232 | The previous state state the object was in. |
||
233 | [[BR]]''state'':[[BR]] |
||
234 | The new state the object is in. |
||
235 | 26 | Luci Stanescu | '''SIPSessionNewIncoming''':: |
236 | 1 | Adrian Georgescu | Will be sent when a new incoming {{{Session}}} is received. |
237 | The application should listen for this notification from all objects specifically to get informed of incoming sessions. |
||
238 | [[BR]]''timestamp'':[[BR]] |
||
239 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
240 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
241 | A list of strings indicating the streams that were proposed by the remote party. |
||
242 | 26 | Luci Stanescu | '''SIPSessionNewOutgoing''':: |
243 | 1 | Adrian Georgescu | Will be sent when the applcation requests a new outgoing {{{Session}}}. |
244 | [[BR]]''timestamp'':[[BR]] |
||
245 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
246 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
247 | A list of strings indicating the streams that were proposed by the remote party. |
||
248 | 26 | Luci Stanescu | '''SIPSessionGotRingIndication''':: |
249 | 1 | Adrian Georgescu | Will be sent when an outgoing {{{Session}}} receives an indication that a remote device is ringing. |
250 | [[BR]]''timestamp'':[[BR]] |
||
251 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
252 | 26 | Luci Stanescu | '''SIPSessionWillStart''':: |
253 | 1 | Adrian Georgescu | Will be sent just before a {{{Session}}} completes negotiation. |
254 | In terms of SIP, this is sent after the final response to the {{{INVITE}}}, but before the {{{ACK}}}. |
||
255 | [[BR]]''timestamp'':[[BR]] |
||
256 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
257 | 26 | Luci Stanescu | '''SIPSessionDidStart''':: |
258 | 1 | Adrian Georgescu | Will be sent when a {{{Session}}} completes negotiation. |
259 | In terms of SIP this is sent after the {{{ACK}}} was sent or received. |
||
260 | [[BR]]''timestamp'':[[BR]] |
||
261 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
262 | 26 | Luci Stanescu | '''SIPSessionDidFail''':: |
263 | 1 | Adrian Georgescu | This notification is sent whenever the session fails. |
264 | The failure reason is included in the data attributes. |
||
265 | 26 | Luci Stanescu | This notification is always followed by {{{SIPSessionDidEnd}}}. |
266 | 1 | Adrian Georgescu | [[BR]]''timestamp'':[[BR]] |
267 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
268 | [[BR]]''originator'':[[BR]] |
||
269 | A string indicating the origin of the failure. |
||
270 | This will either be "local" or "remote". |
||
271 | [[BR]]''code'':[[BR]] |
||
272 | The SIP error code of the failure. |
||
273 | If this is 0, the error was an internal exception. |
||
274 | [[BR]]''reason'':[[BR]] |
||
275 | A string explaining the reason of the failure. |
||
276 | 26 | Luci Stanescu | '''SIPSessionWillEnd''':: |
277 | 1 | Adrian Georgescu | Will be sent just before terminating a {{{Session}}} at the request of the application. |
278 | [[BR]]''timestamp'':[[BR]] |
||
279 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
280 | 26 | Luci Stanescu | '''SIPSessionDidEnd''':: |
281 | Will be sent always when a {{{Session}}} ends, either because of a failure (in which case it is preceded by {{{SIPSessionDidFail}}}), remote or local session termination. |
||
282 | 1 | Adrian Georgescu | [[BR]]''timestamp'':[[BR]] |
283 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
284 | [[BR]]''originator'':[[BR]] |
||
285 | A string indicating who originated the termination. |
||
286 | This will either be "local" or "remote". |
||
287 | 26 | Luci Stanescu | '''SIPSessionGotHoldRequest''':: |
288 | 1 | Adrian Georgescu | Will be sent when the session got put on hold, either by the local or the remote party. |
289 | [[BR]]''timestamp'':[[BR]] |
||
290 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
291 | [[BR]]''originator'':[[BR]] |
||
292 | A string indicating who originated the hold request, and consequently in which direction the session got put on hold. |
||
293 | 26 | Luci Stanescu | '''SIPSessionGotUnholdRequest''':: |
294 | 1 | Adrian Georgescu | Will be sent when the session got taken out of hold, either by the local or the remote party. |
295 | [[BR]]''timestamp'':[[BR]] |
||
296 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
297 | [[BR]]''originator'':[[BR]] |
||
298 | A string indicating who sent the original hold request, and consequently in which direction the session got taken out of hold. |
||
299 | 26 | Luci Stanescu | '''SIPSessionWillStartRecordingAudio''':: |
300 | 1 | Adrian Georgescu | Will be sent when the application requested that the audio stream active within the session be record to a {{{.wav}}} file, just before recording starts. |
301 | [[BR]]''timestamp'':[[BR]] |
||
302 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
303 | [[BR]]''file_name'':[[BR]] |
||
304 | The name of the recording {{{.wav}}} file, including full path. |
||
305 | 26 | Luci Stanescu | '''SIPSessionDidStartRecordingAudio''':: |
306 | 1 | Adrian Georgescu | Will be sent when the application requested that the audio stream active within the session be record to a {{{.wav}}} file, just after recording starts. |
307 | [[BR]]''timestamp'':[[BR]] |
||
308 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
309 | [[BR]]''file_name'':[[BR]] |
||
310 | The name of the recording {{{.wav}}} file, including full path. |
||
311 | 26 | Luci Stanescu | '''SIPSessionWillStopRecordingAudio''':: |
312 | 1 | Adrian Georgescu | Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops. |
313 | [[BR]]''timestamp'':[[BR]] |
||
314 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
315 | [[BR]]''file_name'':[[BR]] |
||
316 | The name of the recording {{{.wav}}} file, including full path. |
||
317 | 26 | Luci Stanescu | '''SIPSessionDidStopRecordingAudio''':: |
318 | 1 | Adrian Georgescu | Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops. |
319 | [[BR]]''timestamp'':[[BR]] |
||
320 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
321 | [[BR]]''file_name'':[[BR]] |
||
322 | The name of the recording {{{.wav}}} file, including full path. |
||
323 | 26 | Luci Stanescu | '''SIPSessionGotNoAudio''':: |
324 | 1 | Adrian Georgescu | This notification will be sent if 5 seconds after the audio stream starts, no audio was received from the remote party. |
325 | [[BR]]''timestamp'':[[BR]] |
||
326 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
327 | 26 | Luci Stanescu | '''SIPSessionGotDTMF''':: |
328 | 1 | Adrian Georgescu | Will be send if there is a DMTF digit received from the remote party on the audio stream. |
329 | [[BR]]''timestamp'':[[BR]] |
||
330 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
331 | [[BR]]''digit'':[[BR]] |
||
332 | The DTMF digit that was received, in the form of a string of length 1. |
||
333 | 26 | Luci Stanescu | '''SIPSessionGotMessage''':: |
334 | 1 | Adrian Georgescu | Will be sent whenever a MSRP message is received on the chat stream of the session. |
335 | [[BR]]''content'':[[BR]] |
||
336 | The body of the message. |
||
337 | [[BR]]''content_type'':[[BR]] |
||
338 | The Content-Type of the body. |
||
339 | [[BR]]''cpim_headers'':[[BR]] |
||
340 | A dictionary of headers included in the CPIM wrapper. |
||
341 | [[BR]]''message'':[[BR]] |
||
342 | 5 | Redmine Admin | Raw MSRP message, an msrplib.protocol.MSRPData instance |
343 | 26 | Luci Stanescu | '''SIPSessionDidDeliverMessage''':: |
344 | 1 | Adrian Georgescu | Will be sent when a previously sent MSRP chat message got delivered to the remote party. |
345 | [[BR]]''message_id'':[[BR]] |
||
346 | The unique identifier of this message as a string, as previously returned by the {{{send_message()}}} method. |
||
347 | [[BR]]''code'':[[BR]] |
||
348 | The response code of the confirmation report. |
||
349 | [[BR]]''reason'':[[BR]] |
||
350 | 5 | Redmine Admin | The reason string of the confirmation report. |
351 | 1 | Adrian Georgescu | [[BR]]''message'':[[BR]] |
352 | Raw MSRP message, an msrplib.protocol.MSRPData instance |
||
353 | 26 | Luci Stanescu | '''SIPSessionDidDeliverMessage''':: |
354 | 1 | Adrian Georgescu | Will be sent when a previously sent MSRP chat message did not get delivered to the remote party. |
355 | [[BR]]''message_id'':[[BR]] |
||
356 | The unique identifier of this message as a string, as previously returned by the {{{send_message()}}} method. |
||
357 | [[BR]]''code'':[[BR]] |
||
358 | The response code of the confirmation report. |
||
359 | [[BR]]''reason'':[[BR]] |
||
360 | 5 | Redmine Admin | The reason string of the confirmation report. |
361 | 1 | Adrian Georgescu | [[BR]]''message'':[[BR]] |
362 | Raw MSRP message, an msrplib.protocol.MSRPData instance |
||
363 | 26 | Luci Stanescu | '''SIPSessionGotStreamProposal''':: |
364 | 1 | Adrian Georgescu | Will be sent when either the local or the remote party proposes to add a stream to the session. |
365 | [[BR]]''timestamp'':[[BR]] |
||
366 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
367 | [[BR]]''proposer'':[[BR]] |
||
368 | The party that did the stream proposal, can be either "local" or "remote". |
||
369 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
370 | A list of strings indicating the streams that were proposed. |
||
371 | 26 | Luci Stanescu | '''SIPSessionRejectedStreamProposal''':: |
372 | 1 | Adrian Georgescu | Will be sent when either the local or the remote party rejects a proposal to have (a) stream(s) added to the session. |
373 | [[BR]]''timestamp'':[[BR]] |
||
374 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
375 | [[BR]]''proposer'':[[BR]] |
||
376 | The party that did the stream proposal, can be either "local" or "remote". |
||
377 | [[BR]]''reason'':[[BR]] |
||
378 | The reason for rejecting the stream proposal. |
||
379 | 26 | Luci Stanescu | '''SIPSessionRejectedStreamProposal''':: |
380 | 1 | Adrian Georgescu | Will be sent when either the local or the remote party accepts a proposal to have (a) stream(s) added to the session. |
381 | [[BR]]''timestamp'':[[BR]] |
||
382 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
383 | [[BR]]''proposer'':[[BR]] |
||
384 | The party that did the stream proposal, can be either "local" or "remote". |
||
385 | 26 | Luci Stanescu | '''SIPSessionGotStreamUpdate''':: |
386 | 23 | Ruud Klaver | Will be sent when a media stream is either activated or deactivated. |
387 | An application should listen to this notification in order to know when a media stream can be used. |
||
388 | [[BR]]''timestamp'':[[BR]] |
||
389 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
390 | [[BR]]''streams'':[[BR]] |
||
391 | A list indicating which streams are active on the session from this point onwards. |
||
392 | 1 | Adrian Georgescu | |
393 | ==== examples ==== |
||
394 | |||
395 | 6 | Ruud Klaver | As an example of how to use the {{{Session}}} object, the following provides a very basic Python program that places an outbound call: |
396 | |||
397 | {{{ |
||
398 | 24 | Ruud Klaver | import sys |
399 | 6 | Ruud Klaver | from threading import Event |
400 | from zope.interface import implements |
||
401 | from application.notification import IObserver, NotificationCenter |
||
402 | 1 | Adrian Georgescu | |
403 | 24 | Ruud Klaver | from sipsimple.configuration import ConfigurationManager |
404 | from sipsimple.account import AccountManager |
||
405 | from sipsimple.engine import Engine |
||
406 | from sipsimple.session import Session |
||
407 | from sipsimple.core import SIPURI, Route |
||
408 | |||
409 | 1 | Adrian Georgescu | class SimpleOutboundCall(object): |
410 | # indicate that we implement the application.notification.IObserver interface |
||
411 | implements(IObserver) |
||
412 | |||
413 | 24 | Ruud Klaver | def __init__(self, remote_uri, route): |
414 | 1 | Adrian Georgescu | # setup a threading.Event to signal that the Engine has stopped |
415 | self.engine_ended_event = Event() |
||
416 | 24 | Ruud Klaver | # start the configuration manager |
417 | ConfigurationManager().start() |
||
418 | # start the account manager |
||
419 | am = AccountManager() |
||
420 | am.start() |
||
421 | # start the Engine with configuration framework parameters |
||
422 | Engine().start_cfg() |
||
423 | # create a new Session using the default account |
||
424 | self.session = Session(am.default_account) |
||
425 | 6 | Ruud Klaver | # listen for the notification that the Engine stopped |
426 | 26 | Luci Stanescu | NotificationCenter().add_observer(self, "SIPEngineDidEnd", Engine()) |
427 | 6 | Ruud Klaver | # listen for the notification that the Session ended |
428 | 26 | Luci Stanescu | NotificationCenter().add_observer(self, "SIPSessionDidEnd", self.session) |
429 | 6 | Ruud Klaver | # start a new outbound session |
430 | 24 | Ruud Klaver | self.session.connect(remote_uri, [route], audio=True) |
431 | 6 | Ruud Klaver | |
432 | 23 | Ruud Klaver | def end(self): |
433 | 6 | Ruud Klaver | # if the Session is still active, terminate it |
434 | self.session.end() |
||
435 | # wait for the engine to stop, processed in handle_notification |
||
436 | self.engine_ended_event.wait() |
||
437 | # quit the progam, as this can only be done from the main thread |
||
438 | sys.exit() |
||
439 | |||
440 | 1 | Adrian Georgescu | def handle_notification(self, notification): |
441 | 26 | Luci Stanescu | if notification.name == "SIPSessionDidEnd": |
442 | 6 | Ruud Klaver | # if for whatever reason the session ended, stop the Engine |
443 | print "Session ended" |
||
444 | Engine().stop() |
||
445 | 26 | Luci Stanescu | elif notification.name == "SIPEngineDidEnd": |
446 | 6 | Ruud Klaver | # once the Engine has stopped, signal the (possibly) waiting main |
447 | # thread through a threading.Event |
||
448 | self.engine_ended_event.set() |
||
449 | |||
450 | # place an audio call from the specified account to the specified URI, through |
||
451 | # the specified SIP proxy |
||
452 | # edit this to reflect real settings |
||
453 | 24 | Ruud Klaver | call = SimpleOutboundCall(SIPURI(user="bob", host="example.com"), Route("1.2.3.4")) |
454 | 6 | Ruud Klaver | # block waiting for user input |
455 | print "Placing call, press enter to quit program" |
||
456 | raw_input() |
||
457 | # block in end() until the Engine has stopped |
||
458 | call.end() |
||
459 | }}} |
||
460 | |||
461 | 1 | Adrian Georgescu | === SIP Registration === |
462 | |||
463 | 26 | Luci Stanescu | * SIPRegistrationDidSucceed |
464 | * SIPRegistrationDidFail |
||
465 | * SIPRegistrationWillEnd |
||
466 | * SIPRegistrationDidEnd |
||
467 | 1 | Adrian Georgescu | |
468 | === SIP Subscription === |
||
469 | |||
470 | 26 | Luci Stanescu | * SIPSubscriptionDidSucceed |
471 | * SIPSubscriptionDidFail |
||
472 | * SIPSubscriptionWillEnd |
||
473 | * SIPSubscriptionDidEnd |
||
474 | * SIPSubscriptionGotNotify |
||
475 | 1 | Adrian Georgescu | |
476 | === SIP Publication === |
||
477 | |||
478 | 26 | Luci Stanescu | * SIPPublicationDidSucceed |
479 | * SIPPublicationDidFail |
||
480 | * SIPPublicationWillEnd |
||
481 | * SIPPublicationDidEnd |