text: /*
   * rfc2833.h
   *
   * Open Phone Abstraction Library (OPAL)
   * Formally known as the Open H323 project.
   *
   * Copyright (c) 2001 Equivalence Pty. Ltd.
   *
   * The contents of this file are subject to the Mozilla Public License
   * Version 1.0 (the "License"); you may not use this file except in
   * compliance with the License. You may obtain a copy of the License at
   * http://www.mozilla.org/MPL/
   *
   * Software distributed under the License is distributed on an "AS IS"
   * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   * the License for the specific language governing rights and limitations
   * under the License.
   *
   * The Original Code is Open Phone Abstraction Library.
   *
   * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
   *
   * Contributor(s): ______________________________________.
   */
  
  #ifndef OPAL_CODEC_RFC2833_H
  #define OPAL_CODEC_RFC2833_H
  
  #ifdef P_USE_PRAGMA
  #pragma interface
  #endif
  
  #include <opal_config.h>
  
  #include <opal/mediafmt.h>
  #include <rtp/rtp_session.h>
  
  
  class OpalRTPConnection;
  
  
  ///////////////////////////////////////////////////////////////////////////////
  
  class OpalRFC2833EventsMask : public std::vector<bool>
  {
    public:
      enum { NumEvents = 256 };
      OpalRFC2833EventsMask(bool defaultValue = false);
      OpalRFC2833EventsMask(const char * defaultValues);
      OpalRFC2833EventsMask & operator&=(const OpalRFC2833EventsMask & other);
      friend ostream & operator<<(ostream & strm, const OpalRFC2833EventsMask & mask);
      friend istream & operator>>(istream & strm,       OpalRFC2833EventsMask & mask);
  };
  
  typedef OpalMediaOptionValue<OpalRFC2833EventsMask> OpalRFC288EventsOption;
  const PCaselessString & OpalRFC288EventsName();
  
  
  ///////////////////////////////////////////////////////////////////////////////
  
  class OpalRFC2833Info : public PObject
  {
      PCLASSINFO(OpalRFC2833Info, PObject);
    public:
      // the following values are mandated by RFC 2833
      enum NTEEvent {
        Digit0 = 0,
        Digit1 = 1,
        Digit2 = 2,
        Digit3 = 3,
        Digit4 = 4,
        Digit5 = 5,
        Digit6 = 6,
        Digit7 = 7,
        Digit8 = 8,
        Digit9 = 9,
        Star   = 10,
        Hash   = 11,
        A      = 12,
        B      = 13,
        C      = 14,
        D      = 15,
        Flash  = 16,
        CED    = 32,
        CNG    = 36
      };
  
      OpalRFC2833Info(
        char tone,
        unsigned duration = 0,
        unsigned timestamp = 0
      );
  
      char GetTone() const { return tone; }
      unsigned GetDuration() const { return duration; }
      unsigned GetTimestamp() const { return timestamp; }
      bool IsToneStart() const { return duration == 0; }
  
    protected:
      char     tone;
      unsigned duration;
      unsigned timestamp;
  };
  
  
  ///////////////////////////////////////////////////////////////////////////////
  
  class OpalRFC2833Proto : public PObject
  {
      PCLASSINFO(OpalRFC2833Proto, PObject);
    public:
      enum NotifyState { Started, Ended };
      typedef PNotifierTemplate<NotifyState> Notifier;
      OpalRFC2833Proto(
        const Notifier & receiveNotifier,
        const OpalMediaFormat & mediaFormat
      );
      ~OpalRFC2833Proto();
  
      virtual bool SendToneAsync(
        char tone, 
        unsigned milliseconds
      );
  
      virtual void OnStartReceive(
        char tone,
        unsigned timestamp
      );
      virtual void OnEndReceive();
  
      void UseRTPSession(bool rx, OpalRTPSession * session);
  
      OpalMediaFormat GetTxMediaFormat() const;
      OpalMediaFormat GetRxMediaFormat() const;
      void SetTxMediaFormat(const OpalMediaFormat & mediaFormat);
      void SetRxMediaFormat(const OpalMediaFormat & mediaFormat);
  
      static PINDEX ASCIIToRFC2833(char tone, bool hasNSE);
      static char RFC2833ToASCII(PINDEX rfc2833, bool hasNSE);
  
    protected:
      bool InternalTransmitFrame();
      bool AbortTransmit();
      WORD GetTimestampSince(const PTime & when) const;
  
      PDECLARE_RTPDataNotifier(OpalRFC2833Proto, ReceivedPacket);
      PDECLARE_NOTIFIER(PTimer, OpalRFC2833Proto, ReceiveTimeout);
      PDECLARE_NOTIFIER(PTimer, OpalRFC2833Proto, TransmitTimeout);
  
      OpalMediaFormat                m_baseMediaFormat;
      RTP_DataFrame::PayloadTypes    m_txPayloadType;
      RTP_DataFrame::PayloadTypes    m_rxPayloadType;
      OpalRFC2833EventsMask          m_txEvents;
      OpalRFC2833EventsMask          m_rxEvents;
      Notifier                       m_receiveNotifier;
      OpalRTPSession::DataNotifier   m_receiveHandler;
  
      OpalRTPSession * m_rtpSession;
  
      enum {
        TransmitIdle,
        TransmitActive,
        TransmitEnding1,
        TransmitEnding2,
        TransmitEnding3,
      }      m_transmitState;
      PTimer m_transmitUpdateTimer;
      PTimer m_transmitDurationTimer;
      DWORD  m_transmitTimestamp;
      PTime  m_transmitStartTime;
      BYTE   m_transmitCode;
      WORD   m_transmitDuration;
  
      PDECLARE_MUTEX(m_transmitMutex);
  
      bool     m_receiveIdle;
      BYTE     m_receivedTone;
      DWORD    m_receivedTimestamp;
      WORD     m_receivedDuration;
      PTimer   m_receiveTimer;
      PDECLARE_MUTEX(m_receiveMutex);
  
    P_REMOVE_VIRTUAL_VOID(OnStartReceive(char));
    P_REMOVE_VIRTUAL_VOID(OnEndReceive(char, unsigned, unsigned));
  };
  
  
  #endif // OPAL_CODEC_RFC2833_H
  
  
  /////////////////////////////////////////////////////////////////////////////
  