//
//  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 CPhone, a cross platform voip gui.
//
//  The Initial Developer of the Original Code is Derek Smithies.
//
//  Copyright (C) 2002 Indranet Technologies Ltd, 
//                                  http://www.indranet-technologies.com
//  All Rights Reserved.
//
//  Contributor(s): _______________


/*
 *
 *  $Log: statisticsSub.cxx,v $
 *  Revision 1.4  2004/04/23 05:09:59  dereksmithies
 *  Fixes so it works with latest openh323 lib, and not lock X display.
 *
 *  Revision 1.3  2003/09/02 03:37:32  dereksmithies
 *  Add statistics, new icons, toolbuttons (icon + name)
 *
 *  Revision 1.2  2003/08/26 04:48:02  dereksmithies
 *  Fixes to get statistics working right, add icons, add ok,cancel,apply buttons
 *
 *  Revision 1.1  2003/08/26 03:31:12  dereksmithies
 *  Initial release of statistics display
 *
 *
 *
 *
 *
 */


#include <ptlib.h>
#include <qapplication.h>
#include <qcheckbox.h> 
#include <qevent.h>
#include <qlabel.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qtimer.h>
 
#ifdef __GNUC__
#pragma implementation "statisticsSub.h"
#endif

#include "mainwindowSub.h"
#include "statisticsSub.h"
#include "gdisplay.h"

#define CUSTOM_EVENT_SETUP (QEvent::User + 1)

//#define new PNEW


Statistics::Statistics()
  : FormStatistics( 0, "Statistics", FALSE, WStyle_NoBorderEx)
{
  move(350,60);

  CPhone::Current().SetWindowId(eStatistics, winId());

  QApplication::postEvent(this, new QCustomEvent(CUSTOM_EVENT_SETUP));

  audioPackets = NULL;
  videoPackets = NULL;

  startTime = PTime();
}

void Statistics::Setup()
{
  checkBoxAudioStats->setChecked(CPhone::GetUi().connectOpts.audioStats);
  checkBoxVideoStats->setChecked(CPhone::GetUi().connectOpts.videoStats);

  audioPackets = new StatisticsPacketList();
  videoPackets = new StatisticsPacketList();
  ((StatisticsPacketList *)audioPackets)->AllowDeleteObjects();
  ((StatisticsPacketList *)videoPackets)->AllowDeleteObjects();

  startTimer(1000);  //Every 1000 milliseconds, get more data.
  inCall = FALSE;
}

/*  
 *  Destroys the object and frees any allocated resources
 */
Statistics::~Statistics()
{
  killTimers();

  if (audioPackets != NULL)
    delete audioPackets;

  if (videoPackets != NULL)
    delete videoPackets;
}


void Statistics::closeEvent(QCloseEvent *e)
{
  CPhone::Current().ForgetExists(eStatistics, winId());

  e->accept();
}

void Statistics::timerEvent(QTimerEvent *)
{
  frameAudioStats->setHidden(!CPhone::GetUi().connectOpts.audioStats);
  frameVideoStats->setHidden(!CPhone::GetUi().connectOpts.videoStats);

  StatisticsPacketList *audio = (StatisticsPacketList *)audioPackets;
  StatisticsPacketList *video = (StatisticsPacketList *)videoPackets;

  H323Connection * connection = CPhone::GetUi().GetCurrentConnectionWithLock();

  StatisticsPacket *aStats = new StatisticsPacket(connection, RTP_Session::DefaultAudioSessionID);
  StatisticsPacket *vStats = new StatisticsPacket(connection, RTP_Session::DefaultVideoSessionID);

  audio->AppendElem(aStats);
  video->AppendElem(vStats);

  PString aName, vName, timeString;
  H323Channel *channel = NULL;
  if (connection != NULL) {
    channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, FALSE);
    if (channel != NULL)
      aName = channel->GetCapability().GetFormatName();
    channel = connection->FindChannel(RTP_Session::DefaultVideoSessionID, FALSE);
    if (channel != NULL)
      vName = channel->GetCapability().GetFormatName();

    if (!inCall) {
      startTime = PTime();
      timeString = startTime.AsString("hh:mm:ss dd MMM");
      textLabelStartTime->setText(timeString.GetPointer());
      inCall = TRUE;
    }
    if (inCall) {
      PTimeInterval pt = PTime() - startTime;
      timeString = "Duration: " + pt.AsString(1, PTimeInterval::NormalFormat, 0) + " secs";
      textLabelCallDuration->setText(timeString.GetPointer());
    }
    connection->Unlock();
  } else {
    textLabelCallDuration->clear();
    textLabelStartTime->clear();
    inCall = FALSE;
  }

  graphDisplayAudio->SetDisplayData(audio);
  graphDisplayVideo->SetDisplayData(video);

  textLabelAudioCodec->setText(aName.GetPointer());
  textLabelVideoCodec->setText(vName.GetPointer());

  textLabelAudioMaxStats->setText(graphDisplayAudio->GetRateString()); 
  textLabelAudioCurrent->setText(graphDisplayAudio->GetDualRateString());
  textLabelVideoMaxStats->setText(graphDisplayVideo->GetRateString()); 
  textLabelVideoCurrent->setText(graphDisplayVideo->GetDualRateString());
}


void Statistics::customEvent( QCustomEvent *e)
{
  if (e->type()  == CUSTOM_EVENT_DIE) 
   close(TRUE);

 if (e->type()  == CUSTOM_EVENT_SETUP) 
    Setup();
}

void Statistics::ApplySlot()
{
  CPhone::GetUi().connectOpts.audioStats = checkBoxAudioStats->isChecked();
  CPhone::GetUi().connectOpts.videoStats = checkBoxVideoStats->isChecked();
}

void Statistics::CancelSlot()
{
  close(TRUE);  
}

void Statistics::OkSlot()
{
  ApplySlot();
  close(TRUE);
}



StatisticsPacket::StatisticsPacket(H323Connection *connection, unsigned sessionId)
{
  thisTime = PTime();
  rateSent = 0;
  rateReceived = 0;

  RTP_Session * session = NULL;

  if (connection != NULL)
    session = connection->GetSession(sessionId);

   if (session == NULL) {
     packetsSent = 0;
     packetsReceived = 0;
     octetsSent = 0;
     octetsReceived = 0;
     return;
   }
    
  packetsSent = session->GetPacketsSent();
  packetsReceived = session->GetPacketsReceived();

  octetsSent = session->GetOctetsSent();
  octetsReceived = session->GetOctetsReceived();
}

void StatisticsPacket::operator-=(PObject *src)
{
  StatisticsPacket *sp = (StatisticsPacket *)src;

  PInt64 elapsedMilliseconds = (thisTime - sp->thisTime).GetMilliSeconds();
  double divisor = (8 * 1.024) / elapsedMilliseconds;

  rateSent = (octetsSent - sp->GetOctets(true)) * divisor;
  rateReceived = (octetsReceived - sp->GetOctets(false)) * divisor;

  if (rateSent < 0)
    rateSent = 0;
  
  if (rateReceived < 0)
    rateReceived = 0;
}

unsigned StatisticsPacket::GetPacket(bool isSend)
{
  if (isSend)
    return packetsSent;
  else
    return packetsReceived;
}

unsigned StatisticsPacket::GetOctets(bool isSend)
{
  if (isSend)
    return octetsSent;
  else
    return octetsReceived;
}

double   StatisticsPacket::GetRate  (bool isSend)
{
  if (isSend)
    return rateSent;
  else
    return rateReceived;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
StatisticsPacketList:: ~StatisticsPacketList()
{

}


StatisticsPacket *StatisticsPacketList::GetEntry(PINDEX i)
{
  return (StatisticsPacket *)GetAt(i);
}

void StatisticsPacketList::AppendElem(StatisticsPacket *pack)
{
  if (GetSize() > 0) {
    *pack -= GetAt(0);
    RemoveAt(0);
  }

  Append(pack);
}


    


syntax highlighted by Code2HTML, v. 0.9.1