"Fossies" - the Fresh Open Source Software Archive

Member "bayonne-1.2.16/drivers/vpb/record.cpp" (22 Dec 2002, 6533 Bytes) of package /linux/misc/old/bayonne-1.2.16.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "record.cpp" see the Fossies "Dox" file reference documentation.

    1 // Copyright (C) 2000 Open Source Telecom Corporation.
    2 //
    3 // This program is free software; you can redistribute it and/or modify
    4 // it under the terms of the GNU General Public License as published by
    5 // the Free Software Foundation; either version 2 of the License, or
    6 // (at your option) any later version.
    7 //
    8 // This program is distributed in the hope that it will be useful,
    9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11 // GNU General Public License for more details.
   12 //
   13 // You should have received a copy of the GNU General Public License
   14 // along with this program; if not, write to the Free Software
   15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   16 
   17 #include "driver.h"
   18 
   19 #ifdef  CCXX_NAMESPACES
   20 using namespace std;
   21 namespace ost {
   22 #endif
   23 
   24 VPBRecord::VPBRecord(VPBTrunk *trunk, int h) :
   25 AudioFile(), Service((Trunk *)trunk, keythreads.priAudio())
   26 {
   27     handle = h;
   28     reset = false;
   29     vpbtr = trunk; // DR
   30 }
   31 
   32 VPBRecord::~VPBRecord()
   33 {
   34     char buffer[12];
   35     struct stat ino;
   36     int trim;
   37 
   38     // DR - make sure Run() thread has finised before we delete object
   39     if(reset)
   40     {
   41         vpb_record_terminate(handle);
   42         yield();
   43     }
   44     terminate();
   45 
   46     sprintf(buffer, "%ld", getPosition());
   47     trunk->setSymbol(SYM_OFFSET, buffer);
   48 
   49     if(data->record.minsize)
   50     {
   51         if(getPosition() < data->record.minsize)
   52         {
   53             trunk->setSymbol(SYM_RECORDED, "0");
   54             remove(data->record.name);
   55             AudioFile::close();
   56             return;         
   57         }
   58     }
   59 
   60     trim = toBytes(getEncoding(), data->record.trim);
   61     stat(data->record.name, &ino);
   62     if(ino.st_size <= trim || data->record.frames)
   63     {
   64         trunk->setSymbol(SYM_RECORDED, "0");
   65         remove(data->record.name);
   66     }
   67     else
   68     {
   69         sprintf(buffer, "%ld", 
   70             getPosition() - data->record.trim);
   71         trunk->setSymbol(SYM_RECORDED, buffer);
   72         truncate(data->record.name, ino.st_size - trim);
   73         chown(data->record.name, keyserver.getUid(), keyserver.getGid());
   74         if(data->record.save)
   75             rename(data->record.name, data->record.save);
   76     }
   77 
   78     AudioFile::close();
   79 
   80 }
   81 
   82 void VPBRecord::initial(void)
   83 {
   84     int codec = VPB_MULAW;
   85     char buffer[32];
   86     Audio::Info info;
   87     const char *ext;
   88     const char *fmt = data->record.encoding;
   89 
   90     trunk->getName(buffer);
   91     info.format = raw;
   92     info.encoding = mulawAudio;
   93     info.order = 0;
   94     info.annotation = (char *)data->record.annotation;
   95     info.rate = 8000;
   96 
   97     ext = strrchr(data->record.name, '/');
   98     if(!ext)
   99         ext = data->record.name;
  100     ext = strrchr(ext, '.');
  101 
  102     if(!ext)
  103     {
  104         ext = data->record.extension;
  105         strcat(data->record.name, ext);
  106     }
  107 
  108     if(!fmt)
  109         fmt = "raw";
  110 
  111     if(!stricmp(ext, ".al"))
  112         info.encoding = alawAudio;
  113     else if(!stricmp(ext, ".au"))
  114     {
  115         info.format = sun;
  116         info.order = __BIG_ENDIAN;
  117     }
  118     else if(!stricmp(ext, ".wav"))
  119     {
  120         info.format = riff;
  121         info.order = __LITTLE_ENDIAN;
  122     }
  123 
  124     if(!stricmp(fmt, "adpcm") || !stricmp(fmt, "g721"))
  125         info.encoding = g721ADPCM;
  126     else if(!stricmp(fmt, "g723"))
  127         info.encoding = g723_3bit;
  128     else if(!stricmp(fmt, "pcm"))
  129         info.encoding = pcm16Mono;
  130 
  131     if(data->record.offset != (unsigned long)-1)
  132     {
  133         open(data->record.name);
  134         setPosition(data->record.offset);
  135     }
  136     else if(data->record.append)
  137         open(data->record.name);
  138     else
  139         create(data->record.name, &info);   
  140 
  141     if(!isOpen())
  142     {
  143         slog(Slog::levelError) << data->record.name << ": cannot open" << endl;
  144         Service::failure();
  145     }
  146     if(data->record.append)
  147         setPosition();
  148 
  149     switch(getEncoding())
  150     {
  151     case g721ADPCM:
  152     case okiADPCM:
  153         codec = VPB_OKIADPCM;
  154         bufsize = 80;
  155         samples = 160;
  156         break;
  157     case g723_3bit:
  158         codec = VPB_OKIADPCM24;
  159         bufsize = 60;
  160         samples = 160;
  161         break;
  162     case mulawAudio:
  163         codec = VPB_MULAW;
  164         bufsize = 160;
  165         samples = 160;
  166         break;
  167     case alawAudio:
  168         codec = VPB_ALAW;
  169         bufsize = 160;
  170         samples = 160;
  171         break;
  172     case pcm16Mono:
  173         codec = VPB_LINEAR;
  174         bufsize = 320;
  175         samples = 160;
  176         break;
  177     default:
  178         slog(Slog::levelError) << buffer << ": unsupported codec required" << endl;
  179         Service::failure();
  180     }
  181 
  182     reset = true;
  183     vpb_record_buf_start(handle, codec);
  184 }
  185 
  186 void VPBRecord::run(void)
  187 {
  188     char name[33];
  189     char buffer[bufsize];
  190     Audio::Error status = Audio::errSuccess;
  191     unsigned frames = 0;
  192     float gain;
  193 
  194     if(data->record.gain != 0.0)
  195     {
  196         vpb_record_get_gain(handle, &gain);
  197         gain += data->record.gain;
  198         if(gain < -12.0)
  199             gain = -12.0;
  200 
  201         if(gain > 12.0)
  202             gain = 12.0;
  203 
  204         vpb_record_set_gain(handle, gain);
  205     }
  206     
  207     trunk->getName(name);
  208 
  209     if(data->record.info)
  210         return success();
  211 
  212     setCancel(cancelDeferred);
  213     while(status == Audio::errSuccess)
  214     {   
  215         if(data->record.frames && (int)frames++ >= data->record.frames)
  216         {
  217             frames = 0;
  218             setPosition(0);
  219         }
  220         if(vpb_record_buf_sync(handle, buffer, bufsize) != VPB_OK)
  221             status = errReadIncomplete;
  222         else
  223             status = putSamples(buffer, samples);
  224         Thread::yield();
  225     }
  226     vpb_record_buf_finish(handle);
  227     reset = false;
  228     if(status == errWriteFailure)
  229         slog(Slog::levelError) << name << ": failed record" << endl;
  230     success();
  231 }
  232 
  233 bool VPBTrunk::recordHandler(TrunkEvent *event)
  234 {
  235     unsigned short mask;
  236 
  237     switch(event->id)
  238     {
  239     case TRUNK_EXIT_STATE:
  240         if(!thread)
  241             return true;
  242         stopServices();
  243         vpb_record_set_gain(handle, inpgain);
  244         handler = &VPBTrunk::stepHandler;
  245         return true;
  246     case TRUNK_STOP_STATE:
  247         endTimer();
  248         stopped = true;
  249         if(thread)
  250         {
  251             vpb_record_terminate(handle);
  252             return true;
  253         }
  254         vpb_record_set_gain(handle, inpgain);
  255         handler = &VPBTrunk::stepHandler;
  256         return true;
  257     case TRUNK_DTMF_KEYUP:
  258         mask = (1 << event->parm.dtmf.digit);
  259         if(!(mask & data.record.term)) {
  260             return false;
  261         }
  262         if(thread)
  263         {
  264             stopped = true;
  265             trunkSignal(TRUNK_SIGNAL_STEP);
  266             vpb_record_terminate(handle);
  267             return true;
  268         }
  269         return true;
  270     case TRUNK_SERVICE_SUCCESS:
  271         if(!stopped)
  272             trunkSignal(TRUNK_SIGNAL_STEP);
  273         exitThread();
  274         return true;
  275     case TRUNK_SERVICE_FAILURE:
  276         if(!stopped)
  277         {
  278             setSymbol(SYM_ERROR, "record-failed");
  279             trunkSignal(TRUNK_SIGNAL_ERROR);
  280         }
  281         exitThread();
  282         return true;
  283     case TRUNK_ENTER_STATE:
  284         stopped = false;
  285         enterState("record");
  286         flags.dsp = DSP_MODE_VOICE;
  287         status[id] = 'r';
  288         if(!flags.offhook)
  289         {
  290             flags.offhook = true;
  291             vpb_sethook_async(handle, VPB_OFFHOOK);
  292             setTimer(getPickupTimer());
  293             return true;
  294         }
  295     case TRUNK_TIMER_EXPIRED:
  296         if(thread)  // default timeout handler
  297             return false;
  298 
  299         if(data.record.term)
  300             setDTMFDetect(true);
  301         else
  302             setDTMFDetect();
  303         thread = new VPBRecord(this, handle);
  304         thread->start();
  305         setTimer(data.record.timeout);
  306         return true;
  307     }
  308     return false;
  309 }
  310 
  311 #ifdef  CCXX_NAMESPACES
  312 };
  313 #endif