1 /*
2  * call.h
3  *
4  * Telephone call management
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (c) 2001 Equivalence Pty. Ltd.
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24  *
25  * Contributor(s): ______________________________________.
26  *
27  * $Revision: 28690 $
28  * $Author: rjongbloed $
29  * $Date: 2012-12-18 20:47:15 -0600 (Tue, 18 Dec 2012) $
30  */
31 
32 #ifndef OPAL_OPAL_CALL_H
33 #define OPAL_OPAL_CALL_H
34 
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38 
39 #include <opal/buildopts.h>
40 
41 #include <opal/connection.h>
42 #include <opal/recording.h>
43 #include <opal/guid.h>
44 
45 #include <ptlib/safecoll.h>
46 
47 
48 class OpalManager;
49 
50 
51 /**This class manages a call.
52    A call consists of one or more OpalConnection instances. While these
53    connections may be created elsewhere this class is responsible for their
54    disposal.
55 
56    An OpalCall could manage (for example) a H323Connection and
57    PCSSConnection instance, which allows the user to use opal in a
58    H.323 application. Alternatively, if OpalCall manages a
59    H323Connection and a SIPConnection instance, the call is being
60    gatewayed from one protocol to another.
61 
62    In a conference situation, one OpalCall would manage lots of
63    H323Connection/SIPConnection classes.
64  */
65 class OpalCall : public PSafeObject
66 {
67     PCLASSINFO(OpalCall, PSafeObject);
68   public:
69   /**@name Construction */
70   //@{
71     /**Create a new call.
72      */
73     OpalCall(
74       OpalManager & manager   ///<  Manager for the opal system
75     );
76 
77     /**Destroy call.
78      */
79     ~OpalCall();
80   //@}
81 
82   /**@name Overrides from PObject */
83   //@{
84     /**Standard stream print function.
85        The PObject class has a << operator defined that calls this function
86        polymorphically.
87       */
88     void PrintOn(
89       ostream & strm    ///<  Stream to output text representation
90     ) const;
91   //@}
92 
93   /**@name Basic operations */
94   //@{
95     /**Indicate tha all connections in call are connected and media is going.
96       */
IsEstablished()97     PBoolean IsEstablished() const { return isEstablished; }
98 
99     /**Call back to indicate that the call has been established.
100        At this point in time every connection in the call is in the
101        "Established" state. This is a better function than using
102        OnEstablished() on a particular connection as it assures that
103        bi-direction media is flowing.
104 
105        The default behaviour is to call OpalManager::OnEstablishedCall().
106       */
107     virtual void OnEstablishedCall();
108 
109     /**Get the call clearand reason for this connection shutting down.
110        Note that this function is only generally useful in the
111        OpalEndPoint::OnClearedCall() function. This is due to the
112        connection not being cleared before that, and the object not even
113        existing after that.
114 
115        If the call is still active then this will return OpalConnection::NumCallEndReasons.
116       */
GetCallEndReason()117     OpalConnection::CallEndReason GetCallEndReason() const { return callEndReason; }
118 
119     /**Get the reason for this connection shutting down as text.
120       */
GetCallEndReasonText()121     PString GetCallEndReasonText() const { return OpalConnection::GetCallEndReasonText(callEndReason); }
122 
123     /**Set the call clearance reason.
124        An application should have no cause to use this function. It is present
125        for the H323EndPoint::ClearCall() function to set the clearance reason.
126       */
127     void SetCallEndReason(
128       OpalConnection::CallEndReason reason   ///<  Reason for clearance of connection.
129     );
130 
131     /**Clear call.
132        This releases all connections currently attached to the call. Note that
133        this function will return quickly as the release and disposal of the
134        connections is done by another thread.
135 
136        The sync parameter is a PSyncPoint that will be signalled during the
137        destructor for the OpalCall. Note only one thread may do this at a time.
138      */
139     void Clear(
140       OpalConnection::CallEndReason reason = OpalConnection::EndedByLocalUser, ///<  Reason for call clearing
141       PSyncPoint * sync = NULL                                                 ///<  Sync point to signal on call destruction
142     );
143 
144     /**Call back to indicate that the call has been cleared.
145        At this point in time there are no connections left in the call.
146 
147        The default behaviour is to call OpalManager::OnClearedCall().
148       */
149     virtual void OnCleared();
150   //@}
151 
152   /**@name Connection management */
153   //@{
154     /**Call back for a new connection has been constructed.
155        This is called after CreateConnection has returned a new connection.
156        It allows an application to make any custom adjustments to the
157        connection before it begins to process the protocol. behind it.
158       */
159     virtual void OnNewConnection(
160       OpalConnection & connection   ///< New connection just created
161     );
162 
163     /**Call back for SetUp conenction.
164 
165        The default behaviour is to call SetUpConnection() on all the other
166        connections in the call.
167       */
168     virtual PBoolean OnSetUp(
169       OpalConnection & connection   ///<  Connection that indicates it is alerting
170     );
171 
172     /**Call back for remote party is now responsible for completing the call.
173        This function is called when the remote system has been contacted and it
174        has accepted responsibility for completing, or failing, the call. This
175        is distinct from OnAlerting() in that it is not known at this time if
176        anything is ringing. This indication may be used to distinguish between
177        "transport" level error, in which case another host may be tried, and
178        that finalising the call has moved "upstream" and the local system has
179        no more to do but await a result.
180 
181        If an application overrides this function, it should generally call the
182        ancestor version for correct operation.
183 
184        The default behaviour does nothing.
185      */
186     virtual void OnProceeding(
187       OpalConnection & connection   ///<  Connection that is proceeeding
188     );
189 
190     /**Call back for remote party being alerted.
191        This function is called after the connection is informed that the
192        remote endpoint is "ringing". Generally some time after the
193        MakeConnection() function was called, this is function is called.
194 
195        If false is returned the connection is aborted.
196 
197        If an application overrides this function, it should generally call the
198        ancestor version for correct operation. An application would typically
199        only intercept this function if it wishes to do some form of logging.
200        For this you can obtain the name of the caller by using the function
201        OpalConnection::GetRemotePartyName().
202 
203        The default behaviour is to call SetAlerting() on all the other
204        connections in the call.
205       */
206     virtual PBoolean OnAlerting(
207       OpalConnection & connection   ///<  Connection that indicates it is alerting
208     );
209 
210     /**Call back for answering an incoming call.
211        This function is called after the connection has been acknowledged
212        but before the connection is established
213 
214        This gives the application time to wait for some event before
215        signalling to the endpoint that the connection is to proceed. For
216        example the user pressing an "Answer call" button.
217 
218        If AnswerCallDenied is returned the connection is aborted and the
219        connetion specific end call PDU is sent. If AnswerCallNow is returned
220        then the connection proceeding, Finally if AnswerCallPending is returned then the
221        protocol negotiations are paused until the AnsweringCall() function is
222        called.
223 
224        The default behaviour returns AnswerCallPending.
225      */
226     virtual OpalConnection::AnswerCallResponse OnAnswerCall(
227       OpalConnection & connection,
228       const PString & caller
229     );
230 
231     /**A call back function whenever a connection is "connected".
232        This indicates that a connection to an endpoint was connected. That
233        is the endpoint received acknowledgement via whatever protocol it uses
234        that the connection may now start media streams.
235 
236        In the context of H.323 this means that the CONNECT pdu has been
237        received.
238 
239        The default behaviour is to call SetConnected() on all other
240        connections in the call.
241       */
242     virtual PBoolean OnConnected(
243       OpalConnection & connection   ///<  Connection that indicates it is alerting
244     );
245 
246     /**A call back function whenever a connection is "established".
247        This indicates that a connection to an endpoint was established. This
248        usually occurs after OnConnected() and indicates that the connection
249        is both connected and has media flowing.
250 
251        In the context of H.323 this means that the CONNECT pdu has been
252        received and either fast start was in operation or the subsequent Open
253        Logical Channels have occurred. For SIP it indicates the INVITE/OK/ACK
254        sequence is complete.
255 
256        The default behaviour is to check that all connections in call are
257        established and if so, marks the call as established and calls
258        OnEstablishedCall().
259       */
260     virtual PBoolean OnEstablished(
261       OpalConnection & connection   ///<  Connection that indicates it is alerting
262     );
263 
264     /**A call back function whenever a connection is released.
265 
266        The default behaviour releases the remaining connection if there is
267        only one left.
268       */
269     virtual void OnReleased(
270       OpalConnection & connection   ///<  Connection that was established
271     );
272 
273     /**A call back function whenever a connection is "held" or "retrieved".
274        This indicates that a connection of a call was held, or
275        retrieved, either locally or by the remote endpoint.
276 
277        The default behaviour does nothing.
278       */
279     virtual void OnHold(
280       OpalConnection & connection,   ///<  Connection that was held/retrieved
281       bool fromRemote,               ///<  Indicates remote has held local connection
282       bool onHold                    ///<  Indicates have just been held/retrieved.
283     );
284 
285     /**Get the other party's connection object.
286        This will return the other party in the call. It will return NULL if
287        there is no other party yet, or there are more than two parties in the
288        call. Usefull during certain stages during initial call set up.
289       */
290     PSafePtr<OpalConnection> GetOtherPartyConnection(
291       const OpalConnection & connection  ///<  Source requesting formats
292     ) const;
293 
294     /**Get the specified active connection in call.
295       */
296     PSafePtr<OpalConnection> GetConnection(
297       PINDEX idx,
298       PSafetyMode mode = PSafeReference
299     ) { return connectionsActive.GetAt(idx, mode); }
300 
301     /**Find a connection of the specified class.
302        This searches the call for the Nth connection of the specified class.
303       */
304     template <class ConnClass>
305     PSafePtr<ConnClass> GetConnectionAs(
306       PINDEX count = 0,
307       PSafetyMode mode = PSafeReadWrite
308     )
309     {
310       PSafePtr<ConnClass> connection;
311       for (PSafePtr<OpalConnection> iterConn(connectionsActive, PSafeReference); iterConn != NULL; ++iterConn) {
312         if ((connection = PSafePtrCast<OpalConnection, ConnClass>(iterConn)) != NULL && count-- == 0) {
313           if (!connection.SetSafetyMode(mode))
314             connection.SetNULL();
315           break;
316         }
317       }
318       return connection;
319     }
320 
321     /**Put call on hold.
322        This function places the remote user of the network connection in the
323        call on hold.
324       */
325     bool Hold();
326 
327     /**Retrieve call from hold.
328        This function retrieves the remote user of the network connection in
329        the call from hold.
330       */
331     bool Retrieve();
332 
333     /**Indicate if call is in hold.
334        This function determines if the remote user of the network connection
335        in the call is currently on hold.
336       */
337     bool IsOnHold() const;
338 
339     /**Transfer connection.
340        There are several scenarios for this function.
341 
342        If 'connection' is not NULL and the protocol type for 'address' is
343        the same, or the protocol type is "*", or the address is a valid and
344        current call token, then this simply calls TransferConnection() on the
345        'connection' variable.
346 
347        e.g. connection="sip:fred@bloggs.com" and address="*:1234", then
348        connection->TransferConnection("sip:1234") is called, which sends a
349        REFER command to the remote. The connection and call are subsequently
350        released in this case.
351 
352        Another example, if connection="pc:Speakers" and address="pc:Headset",
353        then the sound device in the 'connection' instance is changed and the
354        call and media is continued unchanged. The connection and call are
355        <b>not</b> released in this case.
356 
357        If there is a protocol change, e.g. "pc:" to "t38:", then 'connection'
358        is completely released, all media streams to the second conection in
359        the call (if any) are severed and a new connection established and new
360        media streams started.
361 
362        If 'connection' is NULL, it will choose the first connection in the call
363        of the same protocol type. For example, in the previous example above
364        where address="pc:Headset", and the call is from "pc:Speakers" to
365        "sip:fred@bloggs.com", the function would operate the same even if
366        'connection' is NULL.
367 
368        If there are no connections of the same protocol type, then nothing is
369        done and false is returned.
370       */
371     bool Transfer(
372       const PString & address,           ///< New address to transfer to
373       OpalConnection * connection = NULL ///< Connection to transfer
374     );
375   //@}
376 
377   /**@name Media management */
378   //@{
379     /**Get the media formats of the connections in call.
380        This returns the intersection of all the media formats available in
381        connections in the call, not including the parameter. It is in
382        esence the "local" media formats available to the connection.
383 
384        This will also add to the list all media formats for which there are
385        transcoders registered.
386       */
387     virtual OpalMediaFormatList GetMediaFormats(
388       const OpalConnection & connection  ///<  Connection requesting formats
389     );
390 
391     /**Adjust media formats available on a connection.
392        This is called by a connection after it has called
393        OpalCall::GetMediaFormats() to get all media formats that it can use so
394        that an application may remove or reorder the media formats before they
395        are used to open media streams.
396 
397        The default behaviour calls the OpalManager function of the same name.
398       */
399     virtual void AdjustMediaFormats(
400       bool local,                         ///<  Media formats a local ones to be presented to remote
401       const OpalConnection & connection,  ///<  Connection that is about to use formats
402       OpalMediaFormatList & mediaFormats  ///<  Media formats to use
403     ) const;
404 
405     /**Open source media streams for the specified connection.
406        A source media stream is opened for the connection, if successful then
407        sink media streams are created for every other connection in the call.
408        If at least one sink is created then an OpalMediaPatch is created to
409        transfer data from the source to the sinks.
410 
411        If session ID is zero a new session is created. If session ID is non
412        zero then that existing session is replaced.
413       */
414     virtual bool OpenSourceMediaStreams(
415       OpalConnection & connection,              ///<  Connection requesting open
416       const OpalMediaType & mediaType,          ///<  Media type of channel to open
417       unsigned sessionID = 0,                   ///<  Session to start streams on
418       const OpalMediaFormat & preselectedFormat = OpalMediaFormat()  ///< Format for source stream to choose from
419 #if OPAL_VIDEO
420       , OpalVideoFormat::ContentRole contentRole = OpalVideoFormat::eNoRole ///< Content role for video
421 #endif
422     );
423 
424     /**Select media format pair from the source/destination list.
425 
426        Default behavour calls OpalTranscoder::SelectFormats().
427       */
428     virtual bool SelectMediaFormats(
429       const OpalMediaType & mediaType,        ///< Media type for selection.
430       const OpalMediaFormatList & srcFormats, ///<  Names of possible source formats
431       const OpalMediaFormatList & dstFormats, ///<  Names of possible destination formats
432       const OpalMediaFormatList & allFormats, ///<  Master list of formats for merging options
433       OpalMediaFormat & srcFormat,            ///<  Selected source format to be used
434       OpalMediaFormat & dstFormat             ///<  Selected destination format to be used
435     ) const;
436 
437     /**Callback from the RTP session for statistics monitoring.
438        This is called every so many packets on the transmitter and receiver
439        threads of the RTP session indicating that the statistics have been
440        updated.
441 
442        The default behaviour does nothing.
443       */
444     virtual void OnRTPStatistics(
445       const OpalConnection & connection,  ///<  Connection for the channel
446       const RTP_Session & session         ///<  Session with statistics
447     );
448 
449     /**Start the media streams on the connections.
450      */
451     virtual void StartMediaStreams();
452 
453     /**Close the media streams on the connections.
454      */
455     virtual void CloseMediaStreams();
456 
457     /**See if the media can bypass the local host.
458      */
459     virtual PBoolean IsMediaBypassPossible(
460       const OpalConnection & connection,  ///<  Source connection
461       unsigned sessionID                  ///<  Session ID for media channel
462     ) const;
463   //@}
464 
465   /**@name User indications */
466   //@{
467     /**Call back for remote endpoint has sent user input as a string.
468 
469        The default behaviour call OpalConnection::SetUserInput() which
470        saves the value so the GetUserInput() function can return it.
471       */
472     virtual void OnUserInputString(
473       OpalConnection & connection,  ///<  Connection input has come from
474       const PString & value         ///<  String value of indication
475     );
476 
477     /**Call back for remote enpoint has sent user input as tones.
478        If duration is zero then this indicates the beginning of the tone. If
479        duration is non-zero then it indicates the end of the tone output.
480 
481        The default behaviour calls connection.OnUserInputString(tone) if there
482        are no other connections in the call, otherwise it calls
483        SendUserInputTone() for each of the other connections in the call.
484       */
485     virtual void OnUserInputTone(
486       OpalConnection & connection,  ///<  Connection input has come from
487       char tone,                    ///<  Tone received
488       int duration                  ///<  Duration of tone in milliseconds
489     );
490   //@}
491 
492   /**@name Member variable access */
493   //@{
494     /**Get the manager for this endpoint.
495      */
GetManager()496     OpalManager & GetManager() const { return manager; }
497 
498     /**Get the internal identifier token for this connection.
499      */
GetToken()500     const PString & GetToken() const { return myToken; }
501 
502     /**Get the A party for the call.
503        Note this will be available even after the A party connection has been
504        released from the call.
505      */
GetPartyA()506     const PString & GetPartyA() const { return m_partyA; }
507 
508     /**Get the B party for the call.
509        Note this will be available even after the B party connection has been
510        released from the call. Also this will only be the first B party if the
511        object represents a conference call with more that 2 parties.
512      */
GetPartyB()513     const PString & GetPartyB() const { return m_partyB; }
514 
515     /**Set the B party for a call.
516        This is used when we wish to make two outgoing calls and bridge them.
517        When the OnConnected() call back occurs for the first outgoing call
518        (the A-Party) then this variable ised to make teh second outgoing call.
519       */
SetPartyB(const PString & b)520     void SetPartyB(
521       const PString & b
522     ) { m_partyB = b; }
523 
524     /**Get indication that A-Party is the network.
525        This will indicate if the call is "incoming" or "outgoing" by looking at
526        the type of the A-party connection.
527       */
528     bool IsNetworkOriginated() const;
529 
530     /**Get the time the call started.
531      */
GetStartTime()532     const PTime & GetStartTime() const { return startTime; }
533   //@}
534 
535 #if OPAL_HAS_MIXER
536     /**Start recording a call.
537        Current version saves to a WAV file. It may either mix the receive and
538        transmit audio stream to a single mono file, or the streams are placed
539        into the left and right channels of a stereo WAV file.
540       */
541     bool StartRecording(
542       const PFilePath & filename, ///< File into which to record
543       const OpalRecordManager::Options & options = false ///< Record mixing options
544     );
545 
546     /**Indicate if recording is currently active on call.
547       */
548     bool IsRecording() const;
549 
550     /** Stop a recording.
551         Returns true if the call does exists, an active call is not indicated.
552       */
553     void StopRecording();
554 
555     /** Call back on recording started.
556       */
557     virtual bool OnStartRecording(
558       const PString & streamId,       ///< Unique ID for stream within call
559       const OpalMediaFormat & format  ///< Media format for stream
560     );
561 
562     /** Call back on recording stopped.
563       */
564     virtual void OnStopRecording(
565       const PString & streamId       ///< Unique ID for stream within call
566     );
567 
568     /** Call back for having a frame of audio to record.
569       */
570     virtual void OnRecordAudio(
571       const PString & streamId,       ///< Unique ID for stream within call
572       const RTP_DataFrame & frame     ///< Media data
573     );
574 
575 #if OPAL_VIDEO
576     /** Call back for having a frame of video to record.
577       */
578     virtual void OnRecordVideo(
579       const PString & streamId,       ///< Unique ID for stream within call
580       const RTP_DataFrame & frame     ///< Media data
581     );
582 #endif
583 #endif // OPAL_HAS_MIXER
584 
585     void InternalOnClear();
586 
587     void SetPartyNames();
588 
589   protected:
590     bool EnumerateConnections(
591       PSafePtr<OpalConnection> & connection,
592       PSafetyMode mode,
593       const OpalConnection * skipConnection = NULL
594     ) const;
595 
596     OpalManager & manager;
597 
598     PString myToken;
599 
600     PString m_partyA;
601     PString m_partyB;
602     PTime   startTime;
603     bool    isEstablished;
604     bool    isClearing;
605     PAtomicBoolean m_isCleared;
606 
607     OpalConnection::CallEndReason callEndReason;
608     std::list<PSyncPoint *> m_endCallSyncPoint;
609 
610     PSafeList<OpalConnection> connectionsActive;
611 
612 #if OPAL_HAS_MIXER
613     OpalRecordManager * m_recordManager;
614 #endif
615 
616   //use to add the connection to the call's connection list
617   friend OpalConnection::OpalConnection(OpalCall &, OpalEndPoint &, const PString &, unsigned int, OpalConnection::StringOptions *);
618   //use to remove the connection from the call's connection list
619   friend OpalConnection::~OpalConnection();
620 };
621 
622 
623 #endif // OPAL_OPAL_CALL_H
624 
625 
626 // End of File ///////////////////////////////////////////////////////////////
627