Logo Search packages:      
Sourcecode: bayonne version File versions  Download package

ringing.cpp

// Copyright (C) 2000 Open Source Telecom Corporation.
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "driver.h"

#ifdef      CCXX_NAMESPACES
using namespace std;
namespace ost {
#endif

#ifdef      VPB_V12PCI

bool VPBTrunk::ringIntercom(TrunkEvent *event)
{
      Trunk *trunk;
      VPBTrunk *vpb;
      const char *pid;

      switch(event->id)
      {
      case TRUNK_STOP_RINGING:
            ringStation(event);
            trunk = vpbivr.getTrunkPort(event->parm.tid);
            if(trunk == data.answer.intercom)
            {
                  if(thread)
                        vpb_play_terminate(handle);
                  handler = &VPBTrunk::idleHandler;
            }
            return true;
      case TRUNK_EXIT_STATE:
            if(thread)
                  stopServices();
            return true;
      case TRUNK_STOP_STATE:
            if(thread)
                  vpb_play_terminate(handle);
            return false;
      case TRUNK_TIMER_EXPIRED:
            flags.sent = true;
            vpb = (VPBTrunk *)data.answer.intercom;
            if(vpb->flags.cid)
            {
                  thread = new VPBSend(this, handle);
                  thread->start();
            }
            return true;
      case TRUNK_ENTER_STATE:
            setTimer(1100);
      case TRUNK_MAKE_BUSY:
      case TRUNK_MAKE_IDLE:
            return ringStation(event);
      case TRUNK_STATION_OFFHOOK:
            if(thread)
                  vpb_play_terminate(handle);
            setSymbol(SYM_TRANSFER, 16);
            setSymbol(SYM_INTERCOM, 16);
            pid = data.answer.intercom->getSymbol(SYM_GID);
            setConst(SYM_PARENT, pid);
            pid = strchr(pid, '-');
            if(pid)
                  setSymbol(SYM_INTERCOM, pid);       
            if(data.answer.transfer)
                  setSymbol(SYM_TRANSFER, data.answer.transfer);
            return ringStation(event);
      case TRUNK_START_RINGING:
            return false;
      }
      return true;
}

bool VPBTrunk::ringStation(TrunkEvent *event)
{
      unsigned pid, count;
      VPBTrunk *vpb;

      switch(event->id)
      {
        case TRUNK_EXIT_STATE:
                if(thread)
                        stopServices();
                return true;
        case TRUNK_STOP_STATE:
                if(thread)
                        vpb_play_terminate(handle);
                return false;
      case TRUNK_TIMER_EXPIRED:
            count = vpbivr.getTrunkCount();
            pid = 0;
            data.answer.intercom = NULL;
            while(pid < count)
            {
                  if(ringIndex[pid])
                  {
                        vpb = (VPBTrunk *)vpbivr.getTrunkPort(pid);
                        if(!vpb)
                              continue;
                        if(!vpb->flags.cid)
                              continue;
                        break;
                  }
                  ++pid;
            }
            data.answer.intercom = vpbivr.getTrunkPort(pid);
            if(!data.answer.intercom)
                  return true;

            flags.sent = true;
            thread = new VPBSend(this, handle);
            thread->start();
            return true;
      case TRUNK_ENTER_STATE:
            enterState("ring");
            status[id] = '!';
            if(rings < 2)
                  vpb_ring_station_sync(handle, VPB_RING_STATION_ON);
            if(!flags.sent)
                  setTimer(1100);
            return true;
      case TRUNK_STOP_RINGING:
            if(!isStation)
                  return false;
            if(!ringIndex[event->parm.tid])
                  return false;
            ringIndex[event->parm.tid] = false;
            --rings;
            if(rings)
                  return true;
            if(thread)
                  vpb_play_terminate(handle);
            vpb_ring_station_sync(handle, VPB_RING_STATION_OFF);
            handler = &VPBTrunk::idleHandler;
            return true;
      case TRUNK_MAKE_IDLE:
      case TRUNK_MAKE_BUSY:
            if(thread)
                  vpb_play_terminate(handle);
            rings = 0;
            for(pid = 0; pid < (unsigned)vpbivr.getTrunkCount(); ++pid)
                  ringIndex[pid] = false;
            vpb_ring_station_sync(handle, VPB_RING_STATION_OFF);
            return false;
      case TRUNK_START_RINGING:
            return false;
      case TRUNK_START_INTERCOM:
            return idleHandler(event);
      case TRUNK_STATION_OFFHOOK:
            vpb_ring_station_sync(handle, VPB_RING_STATION_OFF);
            idleHandler(event);
            if(thread)
                  vpb_play_terminate(handle);
//          if(idleHandler(event))
//                vpb_ring_station_sync(handle, VPB_RING_STATION_OFF);
      }
      return true;
}

#endif
            
bool VPBTrunk::ringHandler(TrunkEvent *event)
{
      char script[256];
      char *args[2];
      char **start = NULL;
      TrunkGroup *grp = NULL;

      switch(event->id)
      {
      case TRUNK_ENTER_STATE:
            enterState("ring");
            status[id] = '!';
            flags.dsp = DSP_MODE_CALLERID;
            return true;
      case TRUNK_SERVICE_SUCCESS:
            slog(Slog::levelInfo) << "cid sampling success" << endl;
            return true;
      case TRUNK_SERVICE_FAILURE:
            slog(Slog::levelInfo) << "cid sampling failed" << endl;
            return true;
      case TRUNK_START_SCRIPT:
            return false;
      case TRUNK_RING_START:
            flags.dsp = DSP_MODE_INACTIVE;
            return idleHandler(event);
      case TRUNK_RINGING_ON:
            ++rings;
            endTimer();
            return true;
      case TRUNK_EXIT_STATE:
            if(thread)
                  stopServices();
            return true;
      case TRUNK_RINGING_OFF:
            if(rings > 1)
                  flags.dsp = DSP_MODE_INACTIVE;

            // DR 24/7/01 - start sampling CID
            if (rings == 1 && group->getAnswer() > 1) 
            {
                  slog(Slog::levelInfo)<<"start sampling CID" << endl;
                  thread = new VPBCid(this, handle);
                  thread->start();
            }

            // DS shutdown on second ring...
            if (rings >= 2 && thread) 
                  stopServices();

            if(rings < group->getAnswer())
            {
                  setTimer(group->getRingTime() * 1000);
                  return true;
            }
            sprintf(script, "ring%d", event->parm.ring.digit);
            if(!grp)
                  grp = group;
            start = getInitial(args);
            if(attach(*start))
            {
                  answered = false;
                  setList(++start);
                  handler = &VPBTrunk::stepHandler;
                  time(&exittimer);
                  exittimer += 6;
                  return true;
            }
            rings = 0;
            slog(Slog::levelError) << name << ": cannot answer call" << endl; 
            return true;
      case TRUNK_LINE_WINK:
            if(!flags.offhook)
                  return true;
      case TRUNK_STOP_DISCONNECT:
      case TRUNK_CPA_DIALTONE:
      case TRUNK_TIMER_EXPIRED:
            flags.dsp = DSP_MODE_INACTIVE;
            handler = &VPBTrunk::idleHandler;
            return true;
      }
      return false;
}

VPBSend::VPBSend(VPBTrunk *t, int h) :
Service(t, keythreads.priAudio())
{
      handle = h;
      reset = false;
      trk = t;
}

VPBSend::~VPBSend()
{
      vpb_play_terminate(handle);
      terminate();
}

void VPBSend::run(void)
{
      VPBTrunk *vpb = (VPBTrunk *)trk->data.answer.intercom;
      setCancel(cancelImmediate);

      vpb_play_buf_start(handle, VPB_LINEAR);
      vpb_play_buf_sync(handle, (char *)vpb->cidbuf, vpb->cidlen * 2);
      vpb_play_buf_finish(handle);

      setCancel(cancelDeferred);
      trk->exitThread();
      Thread::sleep(~0);
}

VPBCid::VPBCid(VPBTrunk *t, int h) :
Service(t, keythreads.priAudio())
{
      handle = h;
      reset = false;
      trk = t;
}

VPBCid::~VPBCid()
{
      vpb_record_terminate(handle);
      terminate();
}

void VPBCid::run(void)
{
      setCancel(cancelImmediate);
      memset(trk->cidbuf, 0, sizeof(trk->cidbuf));
      vpb_record_buf_start(handle, VPB_LINEAR);
      vpb_record_buf_sync(handle, (char *)trk->cidbuf, sizeof(trk->cidbuf));
      vpb_record_buf_finish(handle);
      strcpy(trk->cidnbr, "pstn:");
      if(VPB_OK == vpb_cid_decode(trk->cidnbr + 5, trk->cidbuf, CID_BUF_SZ))
      {
            setCancel(cancelDeferred);
            trk->setConst(SYM_CLID, trk->cidnbr + 5);
            trk->setConst(SYM_CALLER, trk->cidnbr);
            trk->flags.cid = true;
            trk->cidlen = CID_BUF_SZ / 2;
      }
      setCancel(cancelDeferred);
      trk->exitThread();
      Thread::sleep(~0);
}

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index