00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 #ifndef OPAL_T38_T38PROTO_H
00032 #define OPAL_T38_T38PROTO_H
00033 
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037 
00038 #include <opal/buildopts.h>
00039 
00040 
00041 #if OPAL_FAX
00042 
00043 #include <ptlib/pipechan.h>
00044 
00045 #include <opal/mediafmt.h>
00046 #include <opal/mediastrm.h>
00047 #include <opal/endpoint.h>
00048 
00049 
00050 class OpalTransport;
00051 class T38_IFPPacket;
00052 class PASN_OctetString;
00053 class OpalFaxConnection;
00054 
00055 
00056 namespace PWLibStupidLinkerHacks {
00057   extern int t38Loader;
00058 };
00059 
00061 
00067 class OpalFaxAudioFormat : public OpalMediaFormat
00068 {
00069   friend class OpalPluginCodecManager;
00070     PCLASSINFO(OpalFaxAudioFormat, OpalMediaFormat);
00071   public:
00072     OpalFaxAudioFormat(
00073       const char * fullName,    
00074       RTP_DataFrame::PayloadTypes rtpPayloadType, 
00075       const char * encodingName,
00076       PINDEX   frameSize,       
00077       unsigned frameTime,       
00078       unsigned rxFrames,        
00079       unsigned txFrames,        
00080       unsigned maxFrames = 256, 
00081       unsigned clockRate = 8000, 
00082       time_t timeStamp = 0       
00083     );
00084 };
00085 
00086 
00088 
00089 class OpalFaxCallInfo {
00090   public:
00091     OpalFaxCallInfo();
00092     PUDPSocket socket;
00093     PPipeChannel spanDSP;
00094     PThread * stdoutThread;
00095     unsigned refCount;
00096     PIPSocket::Address spanDSPAddr;
00097     WORD spanDSPPort;
00098 };
00099 
00101 
00104 class OpalFaxMediaStream : public OpalMediaStream
00105 {
00106   PCLASSINFO(OpalFaxMediaStream, OpalMediaStream);
00107   public:
00112     OpalFaxMediaStream(
00113       OpalFaxConnection & conn,
00114       const OpalMediaFormat & mediaFormat, 
00115       unsigned sessionID, 
00116       bool isSource,                       
00117       const PString & token,               
00118       const PString & filename,
00119       bool  receive,
00120       const PString & stationId
00121     );
00123 
00130     virtual PBoolean Open();
00131 
00136     virtual PBoolean Close();
00137 
00141     virtual PBoolean ReadPacket(
00142       RTP_DataFrame & packet
00143     );
00144 
00148     virtual PBoolean WritePacket(
00149       RTP_DataFrame & packet
00150     );
00151 
00155     virtual PBoolean IsSynchronous() const;
00156 
00157 #if OPAL_STATISTICS
00158     virtual void GetStatistics(OpalMediaStatistics & statistics, bool fromPatch = false) const;
00159 #endif
00160 
00161 
00162     virtual PString GetSpanDSPCommandLine(OpalFaxCallInfo &);
00163 
00164   protected:
00165     PDECLARE_NOTIFIER(PThread, OpalFaxMediaStream, ReadStdOut);
00166 
00167     OpalFaxConnection & m_connection;
00168     PMutex              infoMutex;
00169     PString             sessionToken;
00170     OpalFaxCallInfo   * m_faxCallInfo;
00171     PFilePath           m_filename;
00172     bool                m_receive;
00173     BYTE                writeBuffer[320];
00174     PINDEX              writeBufferLen;
00175     PString             m_stationId;
00176 
00177 #if OPAL_STATISTICS
00178     OpalMediaStatistics::Fax m_statistics;
00179 #else
00180     int m_result;
00181 #endif
00182 };
00183 
00185 
00188 class OpalT38MediaStream : public OpalFaxMediaStream
00189 {
00190   PCLASSINFO(OpalT38MediaStream, OpalFaxMediaStream);
00191   public:
00192     OpalT38MediaStream(
00193       OpalFaxConnection & conn,
00194       const OpalMediaFormat & mediaFormat, 
00195       unsigned sessionID, 
00196       bool isSource,                       
00197       const PString & token,               
00198       const PString & filename,            
00199       bool receive,
00200       const PString & stationId
00201     );
00202 
00203     PString GetSpanDSPCommandLine(OpalFaxCallInfo &);
00204 
00205     virtual PBoolean ReadPacket(RTP_DataFrame & packet);
00206     virtual PBoolean WritePacket(RTP_DataFrame & packet);
00207 
00208     RTP_DataFrameList queuedFrames;
00209 };
00210 
00212 
00213 class OpalFaxConnection;
00214 
00223 class OpalFaxEndPoint : public OpalEndPoint
00224 {
00225   PCLASSINFO(OpalFaxEndPoint, OpalEndPoint);
00226   public:
00231     OpalFaxEndPoint(
00232       OpalManager & manager,        
00233       const char * g711Prefix = "fax", 
00234       const char * t38Prefix = "t38"  
00235     );
00236 
00239     ~OpalFaxEndPoint();
00241 
00242     virtual PBoolean MakeConnection(
00243       OpalCall & call,          
00244       const PString & party,    
00245       void * userData = NULL,          
00246       unsigned int options = 0,     
00247       OpalConnection::StringOptions * stringOptions = NULL
00248     );
00249 
00252     virtual OpalFaxConnection * CreateConnection(
00253       OpalCall & call,          
00254       void * userData,
00255       OpalConnection::StringOptions * stringOptions,
00256       const PString & filename, 
00257       bool receive,
00258       bool t38
00259     );
00260 
00270     virtual OpalMediaFormatList GetMediaFormats() const;
00271 
00275     virtual void AcceptIncomingConnection(
00276       const PString & connectionToken 
00277     );
00278 
00282     virtual void OnFaxCompleted(
00283       OpalFaxConnection & connection, 
00284       bool failed   
00285     );
00287 
00291     const PFilePath & GetSpanDSP() const { return m_spanDSP; }
00292 
00295     void SetSpanDSP(
00296       const PString & path    
00297     ) { m_spanDSP = path; }
00298 
00301     const PString & GetDefaultDirectory() const { return m_defaultDirectory; }
00302 
00305     void SetDefaultDirectory(
00306       const PString & dir    
00307     ) { m_defaultDirectory = dir; }
00308 
00309     const PString & GetT38Prefix() const { return m_t38Prefix; }
00311 
00312   protected:
00313     PString    m_t38Prefix;
00314     PFilePath  m_spanDSP;
00315     PDirectory m_defaultDirectory;
00316 };
00317 
00318 
00320 
00323 class OpalFaxConnection : public OpalConnection
00324 {
00325   PCLASSINFO(OpalFaxConnection, OpalConnection);
00326   public:
00331     OpalFaxConnection(
00332       OpalCall & call,                 
00333       OpalFaxEndPoint & endpoint,      
00334       const PString & filename,        
00335       bool receive,                    
00336       const PString & _token,          
00337       OpalConnection::StringOptions * stringOptions = NULL
00338     );
00339 
00342     ~OpalFaxConnection();
00344 
00355     virtual bool IsNetworkConnection() const { return false; }
00356 
00363     virtual PBoolean SetUpConnection();
00364 
00375     virtual PBoolean SetAlerting(
00376       const PString & calleeName,   
00377       PBoolean withMedia                
00378     );
00379 
00387     virtual OpalMediaFormatList GetMediaFormats() const;
00388 
00389     virtual void ApplyStringOptions(OpalConnection::StringOptions & stringOptions);
00390     virtual OpalMediaStream * CreateMediaStream(const OpalMediaFormat & mediaFormat, unsigned sessionID, PBoolean isSource);
00391     virtual void AdjustMediaFormats(OpalMediaFormatList & mediaFormats) const;
00392 
00397     virtual void AcceptIncoming();
00398 
00402     virtual void OnFaxCompleted(
00403       bool failed   
00404     );
00405 
00408     bool IsReceive() const { return m_receive; }
00410 
00411   protected:
00412     OpalFaxEndPoint & m_endpoint;
00413     PString           m_filename;
00414     bool              m_receive;
00415     PString           m_stationId;
00416 };
00417 
00419 
00422 class OpalT38Connection : public OpalFaxConnection
00423 {
00424   PCLASSINFO(OpalT38Connection, OpalFaxConnection);
00425   public:
00430     OpalT38Connection(
00431       OpalCall & call,                 
00432       OpalFaxEndPoint & endpoint,      
00433       const PString & filename,        
00434       bool receive,                    
00435       const PString & token,           
00436       OpalConnection::StringOptions * stringOptions = NULL
00437     );
00438 
00439     virtual PString GetPrefixName() const { return m_endpoint.GetT38Prefix(); }
00440     virtual void ApplyStringOptions(OpalConnection::StringOptions & stringOptions);
00441     virtual void OnEstablished();
00442     virtual OpalMediaStream * CreateMediaStream(const OpalMediaFormat & mediaFormat, unsigned sessionID, PBoolean isSource);
00443     virtual void OnMediaPatchStop(unsigned sessionId, bool isSource);
00444     virtual OpalMediaFormatList GetMediaFormats() const;
00445 
00446     
00447     enum Mode {
00448       Mode_Wait,      
00449       Mode_Timeout,   
00450       Mode_UserInput, 
00451       Mode_InBand     
00452     };
00453 
00454     virtual PBoolean SendUserInputTone(
00455       char tone,
00456       unsigned duration
00457     );
00458 
00459   protected:
00460     PDECLARE_NOTIFIER(PTimer,  OpalT38Connection, OnSendCNGCED);
00461     PDECLARE_NOTIFIER(PTimer,  OpalT38Connection, OnFaxChangeTimeout);
00462     PDECLARE_NOTIFIER(PThread, OpalT38Connection, OpenFaxStreams);
00463     void RequestFaxMode(bool fax);
00464 
00465     Mode m_syncMode;
00466 
00467     bool   m_faxMode;  
00468     PTimer m_faxTimer;
00469 };
00470 
00471 
00472 #endif // OPAL_FAX
00473 
00474 #endif // OPAL_T38_T38PROTO_H