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

join.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
namespace ost {
using namespace std;
#endif

VPBJoin::VPBJoin(VPBTrunk *source, VPBTrunk *target) :
Service((Trunk *)source, keythreads.priAudio())
{
      this->source = source;
      this->target = target;
      reset = false;
      shandle = source->handle;
      thandle = target->handle;
}

VPBJoin::~VPBJoin()
{
      terminate();
}

void VPBJoin::initial(void)
{
      // FIXME Check to see if target trunk is already busy here
      reset = true; // JRS: Is this necessary here before we join them?

      //    vpb_echo_canc_disable();
/*
      vpb_play_set_hw_gain(shandle, 11.0);
      vpb_play_set_hw_gain(thandle, 11.0);
      vpb_record_set_hw_gain(shandle, 0.0);
      vpb_record_set_hw_gain(thandle, 0.0);
*/
      vpb_play_set_gain(shandle, 11.0);
      vpb_play_set_gain(thandle, 11.0);

      vpb_set_codec_reg(shandle, 0x32, 197);
      vpb_set_codec_reg(thandle, 0x32, 197);
      
      //    vpb_disable_event(shandle, VPB_MTONEDETECT);
      //    vpb_disable_event(thandle, VPB_MTONEDETECT);

      vpb_record_buf_start(shandle, VPB_LINEAR);
      vpb_play_buf_start(shandle, VPB_LINEAR);
      vpb_record_buf_start(thandle, VPB_LINEAR);
      vpb_play_buf_start(thandle, VPB_LINEAR);
}

void VPBJoin::run(void)
{
      VPBTrunk *trk = (VPBTrunk *)trunk;
      int bufsize = 160;
      short srcbuf[bufsize];
      short tgtbuf[bufsize];
      while(!trk->stopped)
      {     
            if(VPB_OK != vpb_record_buf_sync(shandle, (char*)srcbuf,  sizeof(short)*bufsize))
                  break;
            if(VPB_OK != vpb_record_buf_sync(thandle, (char*)tgtbuf, sizeof(short)*bufsize))
                  break;
            vpb_play_buf_sync(shandle, (char*)tgtbuf, sizeof(short)*bufsize);
            vpb_play_buf_sync(thandle, (char*)srcbuf, sizeof(short)*bufsize);
      }
      vpb_record_buf_finish(shandle);
      vpb_record_buf_finish(thandle);
      vpb_play_buf_finish(shandle);
      vpb_play_buf_finish(thandle);
      reset = false;
      success();
}

bool VPBTrunk::joinHandler(TrunkEvent *event)
{
      int rc;
      TrunkEvent jevent;
      char *msg;

      slog(Slog::levelInfo) << name << ": joinHandler got event " << event->id << endl;

      switch(event->id)
      {
      case TRUNK_DTMF_KEYUP:
            data.join.reason = TRUNK_STATION_FLASH;
            break;
      case TRUNK_TIMER_EXIT:
            data.join.reason = TRUNK_TIMER_EXPIRED;
            break;
      case TRUNK_CPA_DIALTONE:
      case TRUNK_STOP_DISCONNECT:
            if(joined)
                  if(joined->isStation && !isStation)
                        return true; 
      case TRUNK_MAKE_BUSY:
      case TRUNK_MAKE_IDLE:
      case TRUNK_CALL_DISCONNECT:
            data.join.reason = TRUNK_STOP_DISCONNECT;
            break;
      case TRUNK_SEND_MESSAGE:
      case TRUNK_TIMER_EXPIRED:
      case TRUNK_STATION_FLASH:
            data.join.reason = event->id;
      }     

      switch(event->id)
      {
      case TRUNK_EXIT_STATE:
            if(!thread)
                  return true;
            endTimer();
            stopServices();
            disjoin(data.join.reason);
            handler = &VPBTrunk::stepHandler;
            return true;
      case TRUNK_STATION_FLASH:
            if(!joined)
                  return true;
            return false;
      case TRUNK_PART_TRUNKS:
            if(data.join.hangup)
            {
                  if(!trunkSignal(TRUNK_SIGNAL_CANCEL))
                        trunkSignal(TRUNK_SIGNAL_HANGUP);
            }
            else 
            {
                  switch(event->parm.reason)
                  {
                  case TRUNK_TIMER_EXPIRED:
                        setSymbol(SYM_ERROR, "time-parted");
                        break;
                  case TRUNK_STATION_FLASH:
                        setSymbol(SYM_ERROR, "user-parted");
                        break;
                  case TRUNK_SEND_MESSAGE:
                        setSymbol(SYM_ERROR, "send-parted");
                        break;
                  default:
                        setSymbol(SYM_ERROR, "join-parted");
      
                  }
                  if(!trunkSignal(TRUNK_SIGNAL_CANCEL))
                        trunkSignal(TRUNK_SIGNAL_ERROR);
            }
      case TRUNK_STOP_STATE:
            if(thread)
            {
                  stopped = true;
                  vpb_record_terminate(handle);
                  return true;
            }
            data.join.count = 0;
            endTimer();
            handler = &VPBTrunk::stepHandler;
            disjoin(data.join.reason);
            flags.reset = true;
            return true;
      case TRUNK_SERVICE_SUCCESS:
            data.join.count = 0;
            if(!stopped)
                  trunkSignal(TRUNK_SIGNAL_STEP);
            exitThread();
            return true;
      case TRUNK_SERVICE_FAILURE:
            data.join.count = 0;
            if(!stopped)
            {
                  setSymbol(SYM_ERROR, "join-failed");
                  trunkSignal(TRUNK_SIGNAL_ERROR);
            }
            exitThread();
            return true;
      case TRUNK_JOIN_TRUNKS:
            if(joined) 
            {
                  slog(Slog::levelWarning) << name << ":  Trying to join an already joined port" << endl;
                  return false;
            }
      
            if(data.join.waiting)
            {
                  if(data.join.waiting != event->parm.trunk)
                        return false;
            }
                  
            data.join.count = 0;
            endTimer();
            // For software joins
            // joined = new VPBSWJoin(this, (VPBTrunk *) data.join.trunk);
            bridge = vpbivr.getBridge(_card);
            if(!bridge) {
                  slog(Slog::levelWarning) << name << ":  Could not find free bridge resource" << endl;
                  return false;
            }
            joined = (VPBTrunk *)event->parm.trunk;
            joined->joined = this;
            joined->bridge = bridge;

            msg = joined->getSymbol(SYM_GID);
            setSymbol(SYM_JOINID, strchr(msg, '-'));
            

/*          vpb_play_set_hw_gain(handle, 9.5);
            vpb_play_set_hw_gain(joined->handle, 9.5);
            vpb_record_set_hw_gain(handle, 0.0);
            vpb_record_set_hw_gain(joined->handle, 0.0);
*/          
            slog(Slog::levelInfo) << name << ": Joining handles " << handle << " and " << joined->handle << " on resource " << bridge << endl;
            rc = vpb_bridge(handle, joined->handle, VPB_BRIDGE_ON, bridge);
            if(rc == VPB_OK) 
            {
                  enterState("join");
                  status[id] = 'j';
                  return true;
            }
            else
                  slog(Slog::levelWarning) << name << ":  vpb_bridge failed: " << strerror(rc) << endl;

            if(!trunkSignal(TRUNK_SIGNAL_ERROR))
                  trunkSignal(TRUNK_SIGNAL_STEP);
            handler = &VPBTrunk::stepHandler;
            setSymbol(SYM_ERROR, "join-failed");
            return false;
      case TRUNK_TIMER_EXPIRED:
            if(!data.join.count)
                  return false;
            --data.join.count;
            if(data.join.trunk->getSequence() != data.join.seq)
                  goto failed;
      case TRUNK_ENTER_STATE:
            setDTMFDetect();
            endTimer();
            stopped = false;
            data.join.reason = TRUNK_STOP_DISCONNECT;

            if(!flags.offhook)
                  setOffhook();

            if(data.join.trunk) 
            {
                  jevent.id = TRUNK_JOIN_TRUNKS;
                  jevent.parm.trunk = this;
                  data.join.trunk->postEvent(&jevent);
                  if(!joined && data.join.count)
                  {
                        enterState("sync");
                        status[id] = 's';
                        setTimer(vpbivr.syncTimer);
                        return true;
                  }
                  if(!joined)
                  {
failed:
                        if(!trunkSignal(TRUNK_SIGNAL_ERROR))
                              trunkSignal(TRUNK_SIGNAL_STEP);
                        setSymbol(SYM_ERROR, "join-failed");
                        handler = &VPBTrunk::stepHandler;
                        return true;
                  }
                  if(data.join.wakeup)
                        setTimer(data.join.wakeup);
            }
            else 
            {
                  enterState("wait");
                  Trunk::setDTMFDetect();
                  status[id] = 'w';
                  if(data.join.wakeup)
                        setTimer(data.join.wakeup);
            }
            data.join.count = 0;
            return true;
      case TRUNK_SIGNAL_NOTIFY:
            // FIXME this is inconsistent with other drivers, but
            // necessary to tell the joined port to hang up.  You
            // usually need to do that because the hangup dialtone
            // doesn't make it through the bridge for some reason
            // so the joined port doesn't hang up when you want it
            // to.

            //          if(joined)
            //                return false;
            if(event->parm.error)
                  setSymbol(SYM_ERROR, event->parm.error);
            if(!trunkSignal(TRUNK_SIGNAL_SIGNAL))
                  trunkSignal(TRUNK_SIGNAL_HANGUP);
            handler = &VPBTrunk::stepHandler;
            return true;
      }
      return false;
}

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index