/*
 * main.h
 *
 * OpenH323 call generator
 *
 * Copyright (c) 2001 Benny L. Prijono <seventhson@theseventhson.freeserve.co.uk>
 *
 * 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 CallGen323.
 *
 * The Initial Developer of the Original Code is Benny L. Prijono
 *
 * Contributor(s): Equivalence Pty. Ltd.
 *
 * $Log: main.h,v $
 * Revision 1.8  2002/11/16 00:31:28  robertj
 * Added wait for establishment timeout.
 *
 * Revision 1.7  2002/08/27 03:49:47  robertj
 * Added no media transmission if no WAV file supplied, still opens the
 *   logical channels though. Uses silence suppression.
 * Added detection of completion of run and exit of program.
 *
 * Revision 1.6  2002/07/26 02:14:12  robertj
 * Added ability to prefer and delete codecs.
 * Added fake G.723.1 codec.
 *
 * Revision 1.5  2002/07/23 06:30:39  robertj
 * Another set of enhancements, highlights are continually sending ogm WAV
 *   file and putting received audio into WAV files. As well as more
 *   statistics including a CDR file drop for every call.
 *
 *
 * 25 Jan 2002 Substantial improvement [Equivalence Pty. Ltd.]
 * 25 Jan 2000 Update to incorporate openh323 v.01 alpha2 and fix gatekeeper
 *              related codes [bennylp]
 */


#include <ptclib/delaychan.h>
#include <ptclib/pwavfile.h>


///////////////////////////////////////////////////////////////////////////////

class PlayMessage : public PDelayChannel
{
    PCLASSINFO(PlayMessage, PDelayChannel);
  public:
    PlayMessage(const PString & filename, unsigned frameDelay, unsigned frameSize);
    virtual BOOL Read(void *, PINDEX);
    virtual BOOL Close();
  protected:
    PWAVFile wavFile;
    BOOL     reallyClose;
};


///////////////////////////////////////////////////////////////////////////////

class RecordMessage : public PDelayChannel
{
    PCLASSINFO(RecordMessage, PDelayChannel);
  public:
    RecordMessage(const PString & filename, unsigned frameDelay, unsigned frameSize);
    virtual BOOL Write(const void *, PINDEX);
    virtual BOOL Close();
  protected:
    BOOL reallyClose;
};


///////////////////////////////////////////////////////////////////////////////

class MyH323EndPoint;

class MyH323Connection : public H323Connection
{
    PCLASSINFO(MyH323Connection, H323Connection);
  public:
    MyH323Connection(MyH323EndPoint & ep, unsigned callRef);

    virtual void OnCleared();
    virtual BOOL OpenAudioChannel(
      BOOL isEncoding,              /// Direction of data flow
      unsigned bufferSize,          /// Size of each sound buffer
      H323AudioCodec & codec        /// codec that is doing the opening
    );
    virtual void OnRTPStatistics(
      const RTP_Session & session   /// Session with statistics
    ) const;

  protected:
    MyH323EndPoint     & endpoint;
    PTime                openedMedia;
    PTime                receivedMedia;
    H323TransportAddress mediaGateway;
};


///////////////////////////////////////////////////////////////////////////////

class MyH323EndPoint : public H323EndPoint 
{
    PCLASSINFO(MyH323EndPoint, H323EndPoint);
  public:
    MyH323EndPoint();
    ~MyH323EndPoint();

    // override from H323EndPoint
    virtual H323Connection * CreateConnection(
      unsigned callReference
    );
    virtual void OnConnectionEstablished(
      H323Connection & connection,    /// Connection that was established
      const PString & token           /// Token for identifying connection
    );

    // new functions
    BOOL Initialise(const PArgList & args);

    BOOL StartCall(const PString & addr, PString & token);
    const PString & GetOutgoingMessageFile() const { return outgoingMessageFile; }
    const PString & GetIncomingAudioDirectory() const { return incomingAudioDirectory; }
    PTextFile & GetCdrFile() { return cdrFile; }

    unsigned  totalAttempts;

  protected:
    unsigned  totalEstablished;
    PString   outgoingMessageFile;
    PString   incomingAudioDirectory;
    PTextFile cdrFile;
};


///////////////////////////////////////////////////////////////////////////////

struct CallParams
{
  CallParams(MyH323EndPoint & ep, PSyncPoint & end)
    : endpoint(ep), threadEnded(end) { }

  MyH323EndPoint & endpoint;
  PSyncPoint & threadEnded;

  unsigned repeat;
  PTimeInterval tmax_est;
  PTimeInterval tmin_call;
  PTimeInterval tmax_call;
  PTimeInterval tmin_wait;
  PTimeInterval tmax_wait;
};


///////////////////////////////////////////////////////////////////////////////

class CallThread : public PThread
{
  PCLASSINFO(CallThread, PThread);
  public:
    CallThread(
      unsigned index,
      const PString & destination,
      const CallParams & params
    );
    void Main();
    void Stop();

  protected:
    PString          destination;
    unsigned         index;
    CallParams       params;
    PSyncPoint       exit;
};

PLIST(CallThreadList, CallThread);


///////////////////////////////////////////////////////////////////////////////

class CallGen323 : public PProcess 
{
  PCLASSINFO(CallGen323, PProcess)

  public:
    CallGen323();
    void Main();

    PSyncPoint threadEnded;

  protected:
    PDECLARE_NOTIFIER(PThread, CallGen323, Cancel);
    PConsoleChannel console;
    CallThreadList threadList;
};


///////////////////////////////////////////////////////////////////////////////
