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

record.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"
#include <sys/ioctl.h>

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

PhonedevRecord::PhonedevRecord(PhonedevTrunk *trunk) :
Service((Trunk *)trunk, keythreads.priAudio()), AudioFile()
{
      stopped = false;
      reset = false;
      driver = trunk->getDriver();
      dev = trunk->getDevice();
}

PhonedevRecord::~PhonedevRecord()
{
      char buffer[12];
      struct stat ino;
      int trim;

      terminate();

      sprintf(buffer, "%ld", getPosition());
      trunk->setSymbol(SYM_OFFSET, buffer);

      if(data->record.minsize)
      {
            if(getPosition() < data->record.minsize)
            {
                  trunk->setSymbol(SYM_RECORDED, "0");
                  remove(data->record.name);
                  AudioFile::close();
                  if(reset)
                  {
                        ioctl(dev, PHONE_REC_STOP);
                        dspReset();
                  }
                  return;
            }
      }

      trim = toBytes(getEncoding(), data->record.trim);
      stat(data->record.name, &ino);
      if(ino.st_size <= trim || data->record.frames)
      {
            trunk->setSymbol(SYM_RECORDED, "0");
            remove(data->record.name);
      }
      else
      {
            sprintf(buffer, "%ld", 
                  getPosition() - data->record.trim);
            trunk->setSymbol(SYM_RECORDED, buffer);
            truncate(data->record.name, ino.st_size - trim);
            chown(data->record.name, keyserver.getUid(), keyserver.getGid());
            if(data->record.save)
                  rename(data->record.name, data->record.save);
      }

      AudioFile::close();
      if(reset)
      {
            ioctl(dev, PHONE_REC_STOP); 
            dspReset();
      }
}

void PhonedevRecord::initial(void)
{
      int codec, framing, len, count = 0;
      char buffer[32];
      Audio::Info info;
      const char *ext;
      int ctrl;

      trunk->getName(buffer);
      info.format = raw;
      info.encoding = mulawAudio;
      info.order = 0;
      info.annotation = (char *)data->record.annotation;
      info.rate = 8000;

      ext = strrchr(data->record.name, '/');
      if(!ext)
            ext = data->record.name;

      ext = strrchr(ext, '.');
      
      if(!ext)
      {
            ext = data->record.extension;
            strcat(data->record.name, ext);
      }

      if(!stricmp(ext, ".al"))
            info.encoding = alawAudio;
      else if(!stricmp(ext, ".au"))
      {
            info.format = sun;
            info.order = __BIG_ENDIAN;
      }
      else if(!stricmp(ext, ".wav"))
      {
            info.format = riff;
            info.order = __LITTLE_ENDIAN;
      }

#ifdef      POSIX_PHONEDEV
      ctrl = data->record.volume * 10;
      ioctl(dev, PHONE_REC_VOLUME, &ctrl);
#else
      ioctl(dev, PHONE_REC_VOLUME, data->record.volume * 10);
#endif
      if(data->record.offset != (unsigned long)-1)
      {
            open(data->record.name);
            setPosition(data->record.offset);
      }
      else if(data->record.append)
            open(data->record.name);
      else
            create(data->record.name, &info);   
      if(!isOpen())
      {
            slog(Slog::levelError) << data->record.name << ": cannot open" << endl;
            Service::failure();
      }
      if(data->record.append)
            setPosition();

      switch(getEncoding())
      {
      case mulawAudio:
            codec = ULAW;
            framing = 20;
            samples = 24000;
            break;
      case alawAudio:
            codec = ALAW;
            samples = 24000;
            len = 80;
      default:
            slog(Slog::levelError) << buffer << ": unsupported codec required" << endl;
            Service:failure();
      }

      reset = true;
#ifdef      POSIX_PHONEDEV
      ctrl = phivr.getAudioBuffers();
      ioctl(dev, PHONE_REC_DEPTH, &ctrl);
#else
      ioctl(dev, PHONE_REC_DEPTH, phivr.getAudioBuffers());
#endif

      switch(driver)
      {
#ifdef      IXJ_PHONEDEV
      case ixj_driver:
            if(framing == 20)
                  framing = 30;
            break;
#endif
      }

#ifdef      POSIX_PHONEDEV
      for(;;)
      {
            ctrl = framing;
            ioctl(dev, PHONE_FRAME, &ctrl);
            if(framing == ctrl)
                  break;
            if(++count > 4)
                  break;
            Thread::sleep(20);
      }
#else
      while(framing != ioctl(dev, PHONE_FRAME, framing) && count++ < 5)
            Thread::sleep(20);
#endif

      if(count > 4)
      {
            slog(Slog::levelError) << buffer << ": cannot set framing" << endl;
            Service::failure();
      }

#ifdef      POSIX_PHONEDEV
      if(ioctl(dev, PHONE_REC_CODEC, &codec))
#else
      if(ioctl(dev, PHONE_REC_CODEC, codec))
#endif
      {
            slog(Slog::levelError) << buffer << ": cannot set codec" << endl;
            Service::failure();
      }
      samples = (samples * framing) / 3000;
      bufsize = toBytes(getEncoding(), samples);
}

void PhonedevRecord::run(void)
{
      char name[33];
      char buffer[bufsize];
      Error status = Audio::errSuccess;
      int len = 0;
      int frames = 0;

      trunk->getName(name);
      if(ioctl(dev, PHONE_REC_START))
      {
            slog(Slog::levelError) << name << ": failed channel record" << endl;
            Service::failure();
      }

      if(data->record.info)
            Service::success();

      while(status == errSuccess && !stopped)
      {     
            if(data->record.frames && frames++ >= data->record.frames)
            {
                  frames = 0;
                  setPosition(0l);
            }
            len = ::read(dev, buffer, bufsize);
            if(len < bufsize)
                  status = errReadIncomplete;
            else
                  status = putSamples(buffer, samples);
      }
      if(status == errWriteFailure)
            slog(Slog::levelError) << name << ": failed record" << endl;
      ioctl(dev, PHONE_REC_STOP);
      reset = false;
      Service::success();
}

bool PhonedevTrunk::recordHandler(TrunkEvent *event)
{
      unsigned short mask;

      switch(event->id)
      {
      case TRUNK_DTMF_KEYUP:
            mask = (1 << event->parm.dtmf.digit);
            if(!(mask & data.record.term))
                  return false;
      case TRUNK_SERVICE_SUCCESS:
            trunkSignal(TRUNK_SIGNAL_STEP);
            handler = &PhonedevTrunk::stepHandler;
            return true;
      case TRUNK_SERVICE_FAILURE:
            setSymbol(SYM_ERROR, "record-failed");
            trunkSignal(TRUNK_SIGNAL_ERROR);
            handler = &PhonedevTrunk::stepHandler;
            return true;
      case TRUNK_ENTER_STATE:
            enterState("record");
            flags.dsp = DSP_MODE_VOICE;
            status[id] = 'r';
            if(!flags.offhook)
                  setHookState(true);
            if(data.record.term)
                  setDTMFDetect(true);
            else
                  setDTMFDetect();
            thread = new PhonedevRecord(this);
            thread->start();
            setTimer(data.record.timeout);
            return true;
      }
      return false;
}

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index