⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmcpdevice.cxx

📁 SIP(Session Initiation Protocol)是由IETF定义
💻 CXX
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000-2003 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const VmcpDevice_cxx_Version =     "$Id: VmcpDevice.cxx,v 1.8.2.5 2003/02/27 01:55:27 bko Exp $";#include "global.h"#include <cassert>#include <VTime.hxx>/* error handling */#include <cerrno>#include "Vmcp.h"#include "VmcpDevice.hxx"#include "UaConfiguration.hxx"#include "UaFacade.hxx"#include "DeviceEvent.hxx"#include "cpLog.h"#include "CodecG711U.hxx"#include "MediaController.hxx"#include "UaCommandLine.hxx"                             using namespace Vocal;using namespace Vocal::UA;VmcpDevice::VmcpDevice(int id)    : MediaDevice(WAVE, AUDIO),      hasPlayed(false),      myId(id),      audioActive(false),      hookStateOffhook(false),      serverAvailable(false),      fwdFlag(false),      ss(0){    myVmStack = new Vmcp();    prevRtpPacketTime.tv_usec = 0;    myAudioThread->run();    myCodec = new CodecG711U();    myVmServerThread = new VmcpThread(this);    myVmServerThread->run();}  // end VmcpDevice::VmcpDevice()//***************************************************************************// VmcpDevice::~VmcpDevice// description:  Destructor//***************************************************************************VmcpDevice::~VmcpDevice(void){    cpLog(LOG_DEBUG, "VmcpDevice::~VmcpDevice(void)");    myVmServerThread->shutdown();    myVmServerThread->join();    if(ss)    {        myVmStack->sendClose();        close(ss);       }    delete myVmStack;} // end VmcpDevice::~VmcpDevice()voidVmcpDevice::vmThread (){    // process forever on behalf of VmcpDevice hardware    fd_set readfds;    struct timeval tv;    int retval;    int maxFd = 128;      if(ss <= 0)     {        vusleep(50000);        return;    }    // reset file descriptor    FD_ZERO(&readfds);    addToFdSet(&readfds);    // block on select for asyncronous events, but poll to process    // audio and signal requests from endpoints in message queue    tv.tv_sec = 1;    tv.tv_usec = 0;    if ((retval = select(maxFd, &readfds, 0, 0, &tv)) < 0)    {        cpLog(LOG_ERR, "select() returned with an error" );    }    else    {        if (process(&readfds) < 0)        {            cpLog(LOG_ERR, "hardware encountered an error");        }    }}voidVmcpDevice::processAudio (){    myMutex.lock();    if ( (!audioActive) || (!hookStateOffhook) || hasPlayed )    {        myMutex.unlock();        vusleep(50000);        return ;    }    int wait = networkPktSize - (vm_gettimeofday() - nextTime);     if ( wait > 0 )    {        vusleep(wait*1000);    }     nextTime += networkPktSize;     //Since we wakeup, see if any of the device state has changed    if ( (!audioActive) || (!hookStateOffhook) || hasPlayed )    {        myMutex.unlock();        return ;    }    char buffer[1024];    memset(buffer, 0xFE, networkPktSize*8);    if ( !player.getData(buffer, networkPktSize*8) )    {       if(player.isListEmpty())       {         cpLog(LOG_DEBUG, "Done playing");         myVmStack->playStopped();         hasPlayed = true;       }    }    if(!hasPlayed)    {        processRaw((char*)buffer, networkPktSize*8);    }    myMutex.unlock();}//***************************************************************************// VmcpDevice::process//// description:  process any events from vmserver of type VMCP. //               Like play the file, start recording, stop recording etc.             //***************************************************************************intVmcpDevice::process (fd_set* fd){     Lock lock(myMutex);    if ( (hookStateOffhook == true) && (ss > 0 ))    {        if (FD_ISSET(ss, fd))        {            int Msg;	    Msg=myVmStack->getMsg();            if ( Msg < 1 )              {                reportEvent(DeviceEventHookDown);                hookStateOffhook = false;		close(ss);                ss = -1;                return 0;            }            switch (Msg)            {		case Vmcp::Close:		{                    cpLog(LOG_DEBUG,"VMCP:Close");                    reportEvent(DeviceEventHookDown);                    hookStateOffhook = false;		    close(ss);                    ss = -1;		}		break;		case Vmcp::PlayFile:                    cpLog(LOG_DEBUG,"VMCP:Playing file %s",myVmStack->getPlayFileName().c_str());                    player.add(myVmStack->getPlayFileName());                    break;                case Vmcp::StartPlay:                    cpLog(LOG_DEBUG,"VMCP:Start player");                    if( !player.start() )		    {			myVmStack->playStopped();		    }		    else		    {		        hasPlayed = false;		        nextTime = vm_gettimeofday();		    }                    break;                case Vmcp::RecordFile:                    cpLog(LOG_DEBUG,"VMCP:RecordFile");                    recorder.open(myVmStack->getRecordFileName());                    break;                case Vmcp::StartRecord:                    cpLog(LOG_DEBUG,"VMCP:StartRecord");                    recorder.start();		    nextRecTime = vm_gettimeofday();                    break;                case Vmcp::StopRecord:                    cpLog(LOG_DEBUG,"VMCP:StopRecord");                    recorder.close();                    break;                case Vmcp::StopPlay:                    cpLog(LOG_DEBUG,"VMCP:StopPlayer");                    player.stop();		    if(player.isListEmpty())		    {		        hasPlayed = true;		    }                    break;                     case Vmcp::Ack:                    cpLog(LOG_DEBUG,"VMCP:Ack");	            break;			default:                    cpLog(LOG_DEBUG_STACK,"VMCP:Unknown command");		    break;                           }        }    }    return 0;} // end VmcpDevice::process()intVmcpDevice::addToFdSet (fd_set* fd){    Lock lock(myMutex);    if( hookStateOffhook && (ss > 0 ))    {	// set the VM controller to active        FD_SET(ss,fd);         }    return 0;} // end VmcpDevice::addToFdSet()intVmcpDevice::start(){    Lock lock(myMutex);    if ( audioActive )    {        cpLog(LOG_ERR, "Audio channel is already active. Ignoring");        return 0;    }    MediaDevice::start();    //Connect to the VM server    if( connectToVmServer() < 0)    {        cpLog(LOG_ERR, "failed to connect to the VmServers");        return 0;    };    // allocate RTP packet spaces    networkPktSize = atoi(UaConfiguration::instance().getValue(NetworkRtpRateTag).c_str());    // mark audio as active    cpLog(LOG_DEBUG, "setting audio active");    nextTime = vm_gettimeofday();    nextRecTime = vm_gettimeofday();    audioActive = true;    hasPlayed = false;    return 0;} intVmcpDevice::stop (void){    Lock lock(myMutex);    if (!audioActive)     {         return 1;    }    MediaDevice::stop();    // mark audio as deactivated.    cpLog(LOG_DEBUG, "Audio Stop received.");    audioActive = false;    hookStateOffhook = false;        ///reportEvent(DeviceEventHookDown);    player.stop();    recorder.close();    myVmStack->sendClose(); 	    close(ss);    ss = -1;    cpLog(LOG_DEBUG,"End of session");      hasPlayed = false;    return 0;} voidVmcpDevice::sinkData(char* data, int length, VCodecType type){    Lock lock(myMutex);    cpLog(LOG_DEBUG_STACK, "Sink Data: length %d", length);    if(type == DTMF_TONE)    {        char digit;        memcpy(&digit, data, 1);	switch ( digit )	  {	  case 0:	    digit = '0';	    break;	  case 1:	    digit = '1';	    break;	  case 2:	    digit = '2';	    break;	  case 3:	    digit = '3';	    break;	  case 4:	    digit = '4';	    break;	  case 5:	    digit = '5';	    break;	  case 6:	    digit = '6';	    break;	  case 7:	    digit = '7';	    break;	  case 8:	    digit = '8';	    break;	  case 9:	    digit = '9';	    break;	  case 10:	    digit = '*';	    break;	  case 11:	    digit = '#';	    break;	  default:	    cpLog(LOG_ERR,"Unrecognized DTMF Received");	    return;	  }        cpLog( LOG_DEBUG, "***  DTMF %c  ***", digit );        myVmStack->sendDtmf(digit);        return;    }    //Synchronize writing    if ( (!audioActive) || (!hookStateOffhook) )    {        vusleep(30000);        return ;    }    int wait = networkPktSize - (vm_gettimeofday() - nextRecTime);    if ( wait > 0 )    {        vusleep(wait*1000);    }    nextRecTime += networkPktSize;    if(type != myCodec->getType())    {        //First convert the data from type to myType and then feed        //it to the soundcard        cpLog(LOG_ERR, "Need codec conversion!!!!");        Sptr<CodecAdaptor> cAdp =        MediaController::instance().getMediaCapability().getCodec(type);        ///Convert from codec type to PCM        int decLen = 1024;        char decBuf[1024];        cAdp->decode(data, length, decBuf, decLen);        int encLen = 1024;        char encBuf[1024];        myCodec->encode(decBuf, decLen, encBuf, encLen);        recorder.write( (unsigned char*) encBuf, encLen);    }    else    {        recorder.write( (unsigned char*) data, length);    }}voidVmcpDevice::provideCallInfo(Data sCallerId, Data sCalleeId, Data sForwardReason){    cpLog(LOG_DEBUG, "Call from %s to %s, reason %s", sCallerId.c_str(), sCalleeId.c_str(), sForwardReason.c_str());    CallerId = sCallerId;    CalleeId = sCalleeId;    if ( CalleeId == "" ) CalleeId = "5000";    if ( CallerId == "" ) CallerId = "unknown";    cpLog(LOG_DEBUG,"Sending call info");       if ( sCalleeId == "5000" )    {        cpLog(LOG_DEBUG," Direct call to 5000");        NumberOfForwards = 0;        ForwardReason = "UNK";    }    else if ( sForwardReason == "" || sForwardReason == "Unknown" && !fwdFlag )    {	cpLog(LOG_DEBUG," Forward reason unknown");        NumberOfForwards = 0;        ForwardReason = "UNK";    }    else    {	cpLog(LOG_DEBUG," Forward No Answer");        NumberOfForwards = 1;        ForwardReason = "FNA";    }}voidVmcpDevice::reportEvent(DeviceEventType eventType ){    cpLog( LOG_INFO, "Got device event: %d", eventType );    Sptr < DeviceEvent > event = new DeviceEvent( UaFacade::instance().getEventFifo() );    event->type = eventType;    event->id = myId;    UaFacade::instance().getEventFifo()->add( event );}intVmcpDevice::connectToVmServer(){    int retVal = -1;    if( ss > 0 )    {        cpLog(LOG_ERR, "Already active!!! (%d)", ss);        return 0 ;    }    /* Redundancy : Try to connect to the one of the Vmservers     * configured in the config file.     */    const list<string>& vmServers=UaConfiguration::instance().getVmServers();    if(vmServers.size() == 0)    {        // there are NO VM servers configured.        cpLog(LOG_ALERT, "No VmServers are configured in the config file.");        return (-1);    }    for( list<string>::const_iterator itr = vmServers.begin();                itr != vmServers.end(); itr++)    {   		if(UaCommandLine::instance()->getIntOpt("vmadmin")) {        cpLog(LOG_DEBUG,"Trying to connect to vmadin %s:%d",(*itr).c_str(),9024);        if( myVmStack->connect((*itr).c_str(),9024) )        {           cpLog(LOG_DEBUG,"Server connected");           ss = myVmStack->getFd();           myVmStack->setSessionInfo(CallerId.c_str(),CalleeId.c_str(),"5000",ForwardReason.c_str(),NumberOfForwards);            hookStateOffhook = true;           reportEvent(DeviceEventHookUp);           retVal = 0;           break;        }        else        {            cpLog(LOG_DEBUG,"Server not responding, trying the next one");        }    } else {		cpLog(LOG_DEBUG,"Trying to connect to vmserver %s:%d",(*itr).c_str(),8024);        if( myVmStack->connect((*itr).c_str(),8024) )        {           cpLog(LOG_DEBUG,"Server connected");           ss = myVmStack->getFd();           myVmStack->setSessionInfo(CallerId.c_str(),CalleeId.c_str(),"5000",ForwardReason.c_str(),NumberOfForwards);            hookStateOffhook = true;           reportEvent(DeviceEventHookUp);           retVal = 0;           break;        }        else        {            cpLog(LOG_DEBUG,"Server not responding, trying the next one");        }    }}		    return retVal;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -