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

trunk.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

char VPBTrunk::status[16 * 12];
unsigned VPBTrunk::_trkcount = 0;

VPBTrunk::VPBTrunk(int card, int ts, bool sta) :
Trunk((card - 1) * vpbivr.getCardSize() + ts, card)
{
      VPB_DETECT reorder;
      const char *cp;
      char cbuf[65];
      char *tok;
      unsigned pid;
      TrunkEvent event;
      ringIndex = NULL;
      handler = NULL;
      joined = NULL;
      timer = NULL;
      unsigned f1, f2;
      lastring = 0;
      inTimer = isRinging = false;
      isStation = sta;
      _bank = ((card - 1) * (vpbivr.getCardSize() / 4) + ts / 4) + 1;
      _card = card;
      _port = ts;

      if(vpbivr.getExtCount())
      {
            if(isStation)
                  snprintf(name, sizeof(name), "sta(%d,%d)", card, ts);
            else
            {
                  _trk = _trkcount ++;
                  dialgroup[9] = true;
                  snprintf(name, sizeof(name), "trk(%d,%d)", card, ts);
            }
      }
      else
      {
            _trk = _trkcount++;
            snprintf(name, sizeof(name), "vpb(%d,%d)", card, ts);
      }

      if(isStation)
      {
            ringIndex = new bool[vpbivr.getTrunkCount()];
            for(pid = 0; pid < (unsigned)vpbivr.getTrunkCount(); ++pid)
                  ringIndex[pid] = false;
      }

      handle = vpb_open(card, ts + 1);
      vpb_timer_open(&timer, handle, id, 0);
      

#ifdef      VPB_V12PCI
      if(isStation)
      {
            vpb_disable_event(handle, VPB_MRING);
            cp = NULL;
      }
      else
      {
            cp = vpbivr.VPBConfig::getLast("reorder");
      }
#else
      cp = vpbivr.VPBConfig::getLast("reorder");
#endif

      if(cp)
      {
            reorder.stran[0].type = reorder.stran[2].type = VPB_RISING;
            reorder.stran[1].type = VPB_FALLING;
            reorder.stran[0].tfire = reorder.stran[1].tfire =  reorder.stran[2].tfire = 0;
            reorder.stran[0].tmin = reorder.stran[0].tmax = 0;
            reorder.stran[1].tmin = reorder.stran[2].tmin = 220;
            reorder.stran[1].tmax = reorder.stran[2].tmax = 280;

            reorder.nstates = 3;
            reorder.tone_id = VPB_GRUNT + 1;

            strcpy(cbuf, cp);
            cp = strtok_r(cbuf, " \t\r\n,;:", &tok);
            f1 = atoi(cp);
            cp = strtok_r(NULL, " \t\r\n,;:", &tok);
            if(cp)
                  f2 = atoi(cp);
            else
                  f2 = 0;

            reorder.glitch = 40;
            reorder.snr = 10;

            reorder.freq1 = f1;
            reorder.bandwidth1 = 100;
            reorder.minlevel1 = -20;

            if(f2)
            {
                  reorder.ntones = 2;
                  reorder.twist = 10;
                  reorder.freq2 = f2;
                  reorder.bandwidth2 = 100;
                  reorder.minlevel2 = -20;
            }
            else
            {
                  reorder.ntones = 1;
                  reorder.twist = 0;
                  reorder.freq2 = 0;
                  reorder.bandwidth2 = 0;
                  reorder.minlevel2 = 0;
            }
            vpb_settonedet(handle, &reorder);
      }

      vpb_play_get_gain(handle, &outgain);
      vpb_record_get_gain(handle, &inpgain);

      event.id = TRUNK_ENTER_STATE;
      handler = &VPBTrunk::idleHandler;
      postEvent(&event);
}

VPBTrunk::~VPBTrunk()
{
      handler = NULL;
      endTimer();

#ifdef      VPB_V12PCI
      if(isStation && rings)
            vpb_ring_station_sync(handle, VPB_RING_STATION_OFF);
#endif            

      if(timer)
            vpb_timer_close(timer);
      if(ringIndex)
            delete[] ringIndex;
      vpb_sethook_sync(handle, VPB_ONHOOK);
      vpb_close(handle);
      slog(Slog::levelInfo) << name << ": device stopped" << endl;
}

void VPBTrunk::clearRinging(void)
{
      unsigned pid, max = vpbivr.getTrunkCount();
      TrunkEvent event;
      VPBTrunk *trunk;

      if(!isRinging)
            return;

      isRinging = false;

      if(ringIndex)
      {
            if(ringIndex[id])
            {
                  --rings;
                  ringIndex[id] = false;
            }
      }

      for(pid = 0; pid < max; ++pid)
      {
            trunk = (VPBTrunk *)vpbivr.getTrunkPort(pid);
            if(!trunk)
                  continue;

            if(trunk == this)
                  continue;

            if(!trunk->isStation)
                  continue;

            if(!trunk->ringIndex[id])
                  continue;

            event.id = TRUNK_STOP_RINGING;
            event.parm.tid = id;
            trunk->postEvent(&event);           
      }
}

unsigned long VPBTrunk::getCapabilities(void)
{
      if(isStation)
            return TRUNK_CAP_VOICE | TRUNK_CAP_DIAL | TRUNK_CAP_STATION;
      
      return TRUNK_CAP_VOICE | TRUNK_CAP_DIAL;
}

void VPBTrunk::exitThread(void)
{
        VPB_EVENT e;

        e.handle = handle;
        e.data = 0;
        e.type = VPB_DIALEND;           // user defined
        vpb_put_event(&e);
}

unsigned VPBTrunk::getPickupTimer(void)
{
      unsigned min = vpbivr.getHookTimer();
      unsigned pu = group->getPickup();
      if(pu < min)
            return min;

      return pu;
}

void VPBTrunk::getName(char *buffer)
{
      strcpy(buffer, name);
}

void VPBTrunk::exit(void)
{
      if(!flags.onexit)
            if(redirect("::exit"))
            {
                  autoloop(false);
                  flags.onexit = true;
                  return;
            }

      handler = &VPBTrunk::hangupHandler;
}

void VPBTrunk::setTimer(timeout_t timeout)
{

      if(inTimer)
            vpb_timer_stop(timer);

      vpb_timer_change_period(timer, timeout);
        vpb_timer_start(timer);
      inTimer = true;
}

void VPBTrunk::endTimer(void)
{
      if(inTimer)
            vpb_timer_stop(timer);

      inTimer = false;
}

void VPBTrunk::disjoin(trunkevent_t reason)
{
        TrunkEvent event;

        if(!joined)
                return;

        if(bridge < 1 || bridge > 2)
                slog(Slog::levelWarning) << name << ": disjoin called with invalid bridge resource " << bridge << endl;

      vpbivr.freeBridge(_card, bridge);
        vpb_bridge(handle, joined->handle, VPB_BRIDGE_OFF, bridge);
        bridge = 0;
        joined->bridge = 0;
        joined->joined = NULL;
      event.id = TRUNK_PART_TRUNKS;
      event.parm.reason = reason;
      joined->postEvent(&event);
        joined = NULL;
}

void VPBTrunk::setOffhook(void)
{
      timeout_t timer;
      if(!flags.offhook)
      {
            if(!answered)
                  exittimer = 0;
            answered = true;
            vpb_sethook_async(handle, VPB_OFFHOOK);
            timer = vpbivr.getHookTimer();
      }
      flags.offhook = true;
}

bool VPBTrunk::postEvent(TrunkEvent *event)
{
      bool rtn = true;
      trunkhandler_t prior;
      char *tag;
      char *dtargs[2];

      enterMutex();
      switch(event->id)
      {
      case TRUNK_TIMER_SYNC:
            if(!synctimer)
                  rtn = false;
            synctimer = 0;
            break;
      case TRUNK_TIMER_EXIT:
            if(!exittimer)
                  rtn = false;
            exittimer = 0;
            break;
      case TRUNK_TIMER_EXPIRED:
            if(!inTimer)
                  rtn = false;
            break;
      case TRUNK_START_INTERCOM:
            if(handler != &VPBTrunk::idleHandler && handler != &VPBTrunk::ringStation)
                  rtn = false;
      case TRUNK_START_RINGING:
      case TRUNK_STOP_RINGING:
            if(!isStation)
                  rtn = false;
            break;
      case TRUNK_STATION_PICKUP:
            if(isActive())
                  break;
            if(handler != &VPBTrunk::idleHandler || isStation)
            {
                  rtn = false;
                  break;
            }
//          dtargs[1] = NULL;
//          dtargs[0] = (char *)group->getLast("dialing");
//          event->parm.argv = dtargs;
            break;
      case TRUNK_STATION_ANSWER:
            if(handler != &VPBTrunk::toneHandler)
                  rtn = false;
            break;
      case TRUNK_DTMF_KEYUP:
            if(flags.offhook)
                  time(&idletime);
            if(!flags.dtmf)
                  rtn = false;
            break;
      }     
      if(!rtn)
      {
            leaveMutex();
            return false;
      }

      if(!handler)
      {
            slog(Slog::levelWarning) << name;
            slog() << ": no handler active; event=" << event->id << endl;
            leaveMutex();
            return false;
      }

retry:
      debug->debugEvent(this, event);
      prior = handler;
      rtn = (this->*handler)(event);
      if(rtn)
      {
            if(handler != prior)
            {
                  if(prior == &VPBTrunk::idleHandler)
                        setIdle(false);
                  event->id = TRUNK_ENTER_STATE;
                  goto retry;
            }
            leaveMutex();
            return true;
      }

      // default handler

      rtn = true;
      switch(event->id)
      {
      case TRUNK_RINGING_ON:
            if(flags.offhook)
            {
                  if(trunkSignal(TRUNK_SIGNAL_RING))
                  {
                        event->id = TRUNK_STOP_STATE;
                        goto retry;
                  }
                  else
                        event->id = TRUNK_STOP_DISCONNECT;
            }
            else if(!answered && exittimer)
            {
                  time(&exittimer);
                  exittimer += 6;               
            }
            ++rings;
            break;
      case TRUNK_ENTER_STATE:
            if(flags.offhook)
                  setDTMFDetect();
            else
                  setDTMFDetect(false);
            endTimer();
            break;
      case TRUNK_CPA_REORDER:
            if(vpbivr.getExtCount() > 0)
                  break;
            event->parm.tone.name = "reorder";
            if(trunkSignal(TRUNK_SIGNAL_TONE))
            {
                  setSymbol(SYM_TONE, "reorder");
                  event->id = TRUNK_STOP_STATE;
            }
            else
                  event->id = TRUNK_STOP_STATE;
            goto retry;
      case TRUNK_LINE_WINK:
            if(!flags.offhook)
                  break;
      case TRUNK_CPA_DIALTONE:
            if(isStation)
                  break;
      case TRUNK_STOP_DISCONNECT:
      case TRUNK_STATION_ONHOOK:
            if(flags.onexit)
                  break;
            if(trunkSignal(TRUNK_SIGNAL_HANGUP))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_SEND_MESSAGE:
            if(recvEvent(event))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_STATION_FLASH:
            if(trunkSignal(TRUNK_SIGNAL_FLASH))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
        case TRUNK_TIMER_SYNC:
                if(trunkSignal(TRUNK_SIGNAL_TIME))
                {
                        event->id = TRUNK_STOP_STATE;
                        goto retry;
                }
                break;
        case TRUNK_TIMER_EXIT:
            if(!answered)
            {
                  answered = true;
                  event->id = TRUNK_STOP_DISCONNECT;
                  goto retry;
            }
                if(trunkSignal(TRUNK_SIGNAL_TIME))
                        event->id = TRUNK_STOP_STATE;
                else
                        event->id = TRUNK_STOP_DISCONNECT;
                goto retry;
      case TRUNK_TIMER_EXPIRED:
            if(!trunkSignal(TRUNK_SIGNAL_TIMEOUT))
                  trunkSignal(TRUNK_SIGNAL_STEP);
            event->id = TRUNK_STOP_STATE;
            goto retry;
            break;
      case TRUNK_TONE_START:
            setSymbol(SYM_TONE, event->parm.tone.name);
            if(trunkSignal(TRUNK_SIGNAL_TONE))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_CHILD_EXIT:
            if(!isActive())
                  break;
            if(trunkSignal(TRUNK_SIGNAL_CHILD))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_STATION_PICKUP:
            if(!isActive())
                  break;
            if(trunkSignal(TRUNK_SIGNAL_PICKUP))
            {
                  tag = event->parm.trunk->getSymbol(SYM_GID);
                  if(!tag)
                        tag = "";
                  else
                        tag = strchr(tag, '-');
                  setSymbol(SYM_RECALL, tag);
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            rtn = false;
            break;
      case TRUNK_DTMF_KEYUP:
            if(digits < MAX_DIGITS)
                  dtmf.bin.data[digits++] = digit[event->parm.dtmf.digit];
            dtmf.bin.data[digits] = 0;
            if(trunkSignal((trunksignal_t)(event->parm.dtmf.digit + TRUNK_SIGNAL_0)))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_EXIT_SHELL:
            tgi.pid = 0;
            break;
      case TRUNK_STOP_STATE:
            endTimer();
            handler = &VPBTrunk::stepHandler;
            break;
      case TRUNK_EXIT_STATE:
            break;
      case TRUNK_MAKE_STANDBY:
      case TRUNK_MAKE_BUSY:
            handler = &VPBTrunk::busyHandler;
            break;
      case TRUNK_START_RINGING:
            if(!isStation)
            {
                  rtn = false;
                  break;
            }
            if(!ringIndex[event->parm.tid])
            {
                  ++rings;
                  ringIndex[event->parm.tid] = true;
            }           
            break;
      case TRUNK_STOP_RINGING:
            if(!isStation)
            {
                  rtn = false;
                  break;
            }
            if(ringIndex[event->parm.tid])
            {
                  --rings;
                  ringIndex[event->parm.tid] = false;
            }
            break;
      case TRUNK_MAKE_IDLE:
            handler = &VPBTrunk::idleHandler;
            break;
      default:
            rtn = false;
      }
      if(handler != prior)
      {
            event->id = TRUNK_ENTER_STATE;
            goto retry;
      }
      leaveMutex();
      return rtn;
}

unsigned long VPBTrunk::getIdleTime(void)
{
      time_t now;

      time(&now);
      if(handler == &VPBTrunk::idleHandler)
            return now - idletime;

      return 0;
}

bool VPBTrunk::scrJoin(void)
{
      const char *mem = getMember();
      char *port = "";
      Trunk *trunk;

      data.join.hangup = false;
      data.join.wakeup = 0;

      if(!mem)
            mem = "";

      if(!stricmp(mem, "pickup"))
      {
            data.join.hangup = false;
            port = getSymbol(SYM_PICKUP);
      }
      else if(!stricmp(mem, "trunk"))
      {
            data.join.hangup = false;
            port = getSymbol(SYM_TRUNK);
      }
      else if(!stricmp(mem, "intercom"))
      {
            data.join.hangup = false;
            port = getSymbol(SYM_INTERCOM);
      }
      else if(!stricmp(mem, "transfer"))
      {
            data.join.hangup = false;
            port = getSymbol(SYM_TRANSFER);
      }
      else if(!stricmp(mem, "hangup"))
            data.join.hangup = true;
      else if(!stricmp(mem, "parent"))
            port = getSymbol(SYM_PARENT);
      else
            port = getValue(getKeyword("id"));
        
      trunk = vpbivr.getTrunkId(port);

        if(!trunk) 
      {
                error("join-no-port");
                return true;
        }

      mem = getKeyword("count");
      if(mem)
            data.join.count = atoi(mem);
      else
            data.join.count = 0;

      mem = getKeyword("waitTime");
      if(mem)
            data.join.count = getSecTimeout(mem) / keythreads.getResetDelay() + 1;

      mem = getKeyword("maxTime");
      if(mem)
            data.join.wakeup = getSecTimeout(mem);

      data.join.seq = trunk->getSequence();
        data.join.trunk = data.join.waiting = trunk;
        trunkStep(TRUNK_STEP_JOIN);
        return false;
}

bool VPBTrunk::scrWait(void)
{
      const char *mem = getMember();

      if(mem)
      {
            data.join.waiting = NULL;
            data.join.hangup = false;
            if(!stricmp(mem, "intercom"))
                  data.join.waiting = vpbivr.getTrunkId(getSymbol(SYM_INTERCOM));
            else if(!stricmp(mem, "pickup") || !stricmp(mem, "hold"))
                  data.join.waiting = vpbivr.getTrunkId(getSymbol(SYM_PICKUP));
            else if(!stricmp(mem, "trunk"))
                  data.join.waiting = vpbivr.getTrkNumber(getSymbol(SYM_TRUNK));
            else if(!stricmp(mem, "parent"))
                  data.join.waiting = vpbivr.getTrunkId(getSymbol(SYM_PARENT));
            else if(!stricmp(mem, "transfer"))
                  data.join.waiting = vpbivr.getTrunkId(getSymbol(SYM_PARENT));

            else if(!stricmp(mem, "recall"))
                  data.join.waiting = vpbivr.getTrunkId(getSymbol(SYM_RECALL));
            else if(!stricmp(mem, "hangup"))
                  data.join.hangup = true;

      }
      else
      {
            data.join.waiting = NULL;
            data.join.hangup = false;
      }
      data.join.count = 0;
        data.join.trunk = NULL;
      if(getKeyword("maxTime"))
              data.join.wakeup = getTimeout("maxTime");
      else
            data.join.wakeup = getTimeout("waitTime");
        trunkStep(TRUNK_STEP_JOIN);
        return false;
}

bool VPBTrunk::scrDial(void)
{
      const char *mem = getMember();
      VPBTrunk *trunk, *ttrk = NULL;
      TrunkEvent event;
      bool rtn;
      const char *pid;
      const char *ringback = getKeyword("ringback");
      const char *count = getKeyword("count");
      const char *transfer = getKeyword("transfer");
      const char *origin = getKeyword("origin");
      const char *name = getKeyword("name");
      char pbuf[5];

      if(!origin && isStation)
            origin = extNumber;
      else
            origin = getSymbol(SYM_CLID);
      
      if(!isStation)
            return Trunk::scrDial();

      if(transfer)
            if(!*transfer)
                  transfer = NULL;

      if(transfer)
      {
            if(*transfer != '-')
            {
                  pid = strchr(transfer, '-');
                  if(pid)
                        transfer = pid;
            }
            ttrk = (VPBTrunk *)vpbivr.getTrunkId(transfer);
            if(!ttrk)
                  transfer = NULL;
            else
                  ttrk->isRinging = true;
      }

      if(!mem)
            mem = "";

      if(!ringback)
            ringback = getKeyword("ringtone");

      if(!ringback)
            ringback = "ringback";

      if(!count)
            count = "-1";

      data.tone.freq1 = data.tone.freq2 = 0;
      data.tone.ampl1 = data.tone.ampl2 = 0;
      data.tone.wakeup = data.tone.duration = 4000;
      data.tone.loops = atoi(count);
      data.tone.tone = getphTone(ringback);
      if(!data.tone.tone)
            data.tone.tone = getphTone("ringback");

      if(!strnicmp(mem, "int", 3))
      {
            while(NULL != (mem = getValue(NULL)))
            {
                  trunk = (VPBTrunk *)vpbivr.getExtNumber(mem);
                  if(!trunk)
                  {
                        if(!trunkSignal(TRUNK_SIGNAL_INVALID))
                              error("dial-invalid-extension");
                        return true;
                  }
                  if(trunk == this)
                        continue;
                  event.id = TRUNK_START_INTERCOM;
                  event.parm.intercom.tid = id;
                  event.parm.intercom.transfer = transfer;
                  rtn = trunk->postEvent(&event);
                  if(ttrk)
                  {
                        event.id = TRUNK_START_RINGING;
                        event.parm.tid = ttrk->id;
                        trunk->postEvent(&event);

                  }
                  if(rtn)
                  {
                        isRinging = true;
                        pid = trunk->getSymbol(SYM_GID);
                        if(pid)
                              pid = strchr(pid, '-');
                        else
                        {
                              snprintf(pbuf, sizeof(pbuf), "%d", trunk->id);
                              pid = pbuf;
                        }
                        setSymbol(SYM_INTERCOM, pid);
                        data.tone.recall = false;
                        data.tone.dialing = trunk;
                        trunkStep(TRUNK_STEP_TONE);
                        return false;     
                  }
            }     
            if(!trunkSignal(TRUNK_SIGNAL_BUSY))
                  error("dial-busy");
            return true;      
      }
      return Trunk::scrDial();
}


bool VPBTrunk::scrAnswer(void)
{
      VPBTrunk *trunk = NULL;
      TrunkEvent event;
      const char *mem = getMember();
      unsigned pid;

      if(!isStation)
            return Trunk::scrAnswer();

      if(!mem)
            mem = "";

      if(!stricmp(mem, "intercom"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_INTERCOM));
      else if(!stricmp(mem, "pickup"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_PICKUP));
      else if(!stricmp(mem, "trunk"))
            trunk = (VPBTrunk *)vpbivr.getTrkNumber(getSymbol(SYM_TRUNK));
      else if(!stricmp(mem, "parent"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_PARENT));
      else
            return Trunk::scrAnswer();

      if(!trunk || trunk == this)
      {
            if(!trunkSignal(TRUNK_SIGNAL_FAIL))
                  error("answer-nocall");
            return true;
      }
      pid = trunk->id;
      if(isStation)
      {
            if(ringIndex[pid])
            {
                  ringIndex[pid] = false;
                  --rings;
            }
      }
      mem = trunk->getSymbol(SYM_GID);
      if(!mem)
            mem = "";
      else
            mem = strchr(mem, '-');
      setSymbol(SYM_PICKUP, mem);
      event.id = TRUNK_STATION_ANSWER;
      event.parm.trunk = this;
      if(trunk->postEvent(&event))
            return scrGoto();
      if(!trunkSignal(TRUNK_SIGNAL_BUSY))
            error("answer-busy");
      return true;
}

bool VPBTrunk::scrPickup(void)
{
      VPBTrunk *trunk = NULL;
      TrunkEvent event;
      const char *mem = getMember();
      unsigned pid = 0, max = vpbivr.getTrunkCount();
      char trk[5];
      unsigned dig;
      bool dgrp = false;

      if(!mem)
            mem = "incoming";

      if(!stricmp(mem, "hold"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_PICKUP));
      else if(!stricmp(mem, "transfer"))
      {
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_TRANSFER));
            setSymbol(SYM_TRANSFER, "");
      }
      else if(!stricmp(mem, "trunk"))
            trunk = (VPBTrunk *)vpbivr.getTrkNumber(getSymbol(SYM_TRUNK));
      else if(!stricmp(mem, "parent"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_PARENT));
      else if(!stricmp(mem, "recall"))
            trunk = (VPBTrunk *)vpbivr.getTrunkId(getSymbol(SYM_RECALL));
      else if(!stricmp(mem, "outgoing") || isdigit(*mem))
      {
            if(isdigit(*mem))
            {
                  dgrp = true;
                  dig = *mem - '0';
            }
            pid = vpbivr.getTrkCount();
            while(pid--)
            {
                  snprintf(trk, sizeof(trk), "%d", pid);
                  trunk = (VPBTrunk *)vpbivr.getTrkNumber(trk);
                  if(!trunk)
                        continue;                     
            
                  if(dgrp)
                        if(!trunk->dialgroup[dig])
                              continue;
            
                  mem = trunk->getSymbol(SYM_GID);
                  if(!mem)
                  {
                        snprintf(trk, sizeof(trk), "%d", trunk->id);
                        mem = trk;
                  }

                  event.id = TRUNK_STATION_PICKUP;
                  event.parm.trunk = this;
                  if(trunk->postEvent(&event))
                  {
                        setSymbol(SYM_TRUNK, mem);
                        setSymbol(SYM_PICKUP, mem);
                        if(!trunkSignal(TRUNK_SIGNAL_ANSWER))
                              return scrGoto();
                        else
                              return true;
                  }                       
            }     
            if(!trunkSignal(TRUNK_SIGNAL_FAIL))
                  error("pickup-failed");
            return true;
      }
      else if(!stricmp(mem, "intercom") && isStation)
      {
            for(pid = 0; pid < max; ++pid)
            {
                  trunk = (VPBTrunk *)vpbivr.getTrunkPort(pid);
                  if(!trunk)
                        continue;
                  if(trunk == this)
                        continue;
                  if(!ringIndex[pid])
                        continue;
                  if(!trunk->isStation)
                        continue;
                  break;
            }
      }     
      else if(isStation)
      {
            for(pid = 0; pid < max; ++pid)
            {
                  trunk = (VPBTrunk *)vpbivr.getTrunkPort(pid);
                  if(!trunk)
                        continue;
                  if(trunk == this)
                        continue;
                  if(!ringIndex[pid])
                        continue;
                  if(trunk->isStation)
                        continue;
                  break;
            }
      }
            
      if(!trunk || pid >= max)
      {
            error("pickup-nocall");
            return true;
      }
      pid = trunk->id;
      if(isStation)
      {
            if(ringIndex[pid])
            {
                  ringIndex[pid] = false;
                  --rings;
            }
      }
      mem = trunk->getSymbol(SYM_GID);
      if(!mem)
      {
            snprintf(trk, sizeof(trk), "%d", trunk->id);
            mem = trk;
      }
      else
            mem = strchr(mem, '-');
      setSymbol(SYM_PICKUP, mem);
      event.id = TRUNK_STATION_PICKUP;
      event.parm.trunk = this;
      if(trunk->postEvent(&event))
            return scrGoto();
      if(!trunkSignal(TRUNK_SIGNAL_FAIL))
            error("pickup-failed");
      return true;
}
            
bool VPBTrunk::scrRing(void)
{
      TrunkGroup *grp = NULL;
      TrunkEvent event;
      VPBTrunk *trunk, *ring = NULL;
      unsigned pid = 0, sid, count = 0;
      unsigned max = vpbivr.getTrunkCount();
      trunkevent_t evtype = TRUNK_START_RINGING;
      char extbuf[256];
      char *tok = NULL;
      const char *src = getKeyword("source");
      const char *mem = getMember();
      unsigned i;
      bool found;

      if(!mem)
            mem = "start";

      if(src)
      {
            trunk = (VPBTrunk *)vpbivr.getTrunkId(src);
            if(!trunk)
            {
                  error("ring-source-invalid");
                  return true;
            }
            trunk->isRinging = true;
            sid = trunk->id;
      }
      else
            sid = id;

      src = getKeyword("group");
      if(src)
            grp = getGroup(src);

      if(!stricmp(mem, "clear"))
      {
            pid = 0;
            count = vpbivr.getTrunkCount();
            evtype = TRUNK_STOP_RINGING;
      }
      else if(!strnicmp(mem, "att", 3))
      {
            grp = getGroup(mem);
            if(grp)
            {
                  pid = 0;
                  count = vpbivr.getTrunkCount();
            }
            else
            {
                  trunk = (VPBTrunk *)vpbivr.getExtNumber("0");
                  if(trunk)
                  {
                        count = 1;
                        pid = trunk->id;
                  }
                  else
                  {
                        count = 0;
                        pid = max;
                  }
            }
      }
      else if(!stricmp(mem, "trunk") || !strnicmp(mem, "dial", 4))
      {
            ring = this;
            pid = 0;
            count = vpbivr.getTrunkCount();
      }
      else if(!stricmp(mem, "all"))
      {
            pid = 0;
            count = vpbivr.getTrunkCount();
      }
      else if(!stricmp(mem, "card"))
      {
            count = vpbivr.getCardSize();
            mem = getValue(NULL);
            if(mem)
                  pid = (atoi(mem) - 1) * count;
            else
                  pid = (_card - 1) * count;
      }
      else if(!stricmp(mem, "bank"))
      {
            count = 4;
            mem = getValue(NULL);
            if(mem)
                  pid = (atoi(mem) - 1) * 4;
            else
                  pid = (_bank - 1) * 4;
      }
      else if(!stricmp(mem, "immediate") || !stricmp(mem, "delayed"))
      {
            if(grp)
                  mem = grp->getLast(mem);
            else
                  mem = group->getLast(mem);
            if(!mem)
                  mem = "";
            strcpy(extbuf, mem);
            mem = strtok_r(extbuf, ",;:", &tok);
            while(mem)
            {
                  trunk = (VPBTrunk *)vpbivr.getExtNumber(mem);
                  mem = strtok_r(NULL, ",;:", &tok);
                  if(!trunk)
                        continue;
                  if(trunk == this)
                        continue;
                  if(!trunk->isStation)
                        continue;
                  if(trunk->ringIndex[id])
                        continue;
                  event.id = evtype;
                  event.parm.tid = sid;
                  trunk->postEvent(&event);                 
            }     
      }
      else if(!stricmp(mem, "transfer"))
      {
                while(NULL != (mem = getValue(NULL)))
                {
                        trunk = (VPBTrunk *)vpbivr.getExtNumber(mem);
                        if(!trunk)
                                continue;
                  if(trunk == this)
                        continue;

                  trunk->enterMutex();
                  event.id = TRUNK_START_INTERCOM;
                  event.parm.intercom.tid = id;
                  event.parm.intercom.transfer = getKeyword("source");
                  trunk->postEvent(&event);
                  event.id = TRUNK_STOP_RINGING;
                  event.parm.tid = id;
                  trunk->postEvent(&event);
                  trunk->leaveMutex();
            }
      }
      else if(!stricmp(mem, "start") || !stricmp(mem, "stop"))
      {
            if(!stricmp(mem, "stop"))
                  evtype = TRUNK_STOP_RINGING;
            while(NULL != (mem = getValue(NULL)))
            {
                  trunk = (VPBTrunk *)vpbivr.getExtNumber(mem);
                  if(!trunk)
                        continue;
                  if(trunk == this)
                        continue;

                  if(grp)
                        if(trunk->group != grp)
                              continue;

                  if(!trunk->isStation)
                        continue;
                  if(trunk->ringIndex[id])
                        continue;
                  event.id = evtype;
                  event.parm.tid = sid;
                  trunk->postEvent(&event);
            }
      }
      while(count-- && pid < max)
      {
            trunk = (VPBTrunk *)vpbivr.getTrunkPort(pid++);
            if(!trunk)
                  continue;

            if(trunk == this)
                  continue;

            if(grp)
                  if(trunk->group != grp)
                        continue;

            if(!trunk->isStation)
                  continue;

            if(ring)
            {
                  found = false;
                  for(i = 0; i < 10; ++i)
                  {
                        if(ring->dialgroup[i] && trunk->dialgroup[i])
                        {
                              found = true;
                              break;
                        }
                  }     
            }
            else
                  found = true;

            if(!found)
                  continue;

            if(evtype == TRUNK_START_RINGING)
            {
                  if(trunk->ringIndex[id])
                        continue;
            }
            else
            {
                  if(!trunk->ringIndex[id])
                        continue;
            }
            event.id = evtype;
            event.parm.tid = sid;
            trunk->postEvent(&event);
      }
      if(evtype == TRUNK_START_RINGING)
            isRinging = true;
      advance();
      return true;
}     

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index