📄 nullhwdevice.cxx
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 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 NullHwDevice_cxx_Version = "$Id: NullHwDevice.cxx,v 1.32 2002/04/24 01:58:35 bko Exp $";#include "global.h"#include <cassert>/* stdlib */#include <iostream>#include <cstdio>#include <unistd.h>#include <sys/ioctl.h>#include <csignal>#include <termios.h>/* sockets */#include <sys/types.h>#include <sys/socket.h>#include <fcntl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>/* error handling */#include <cerrno>#include "VTime.hxx"#include "VCondition.h"#include "NullHwDevice.hxx"#include "UaDeviceEvent.hxx"#include "UaConfiguration.hxx"#define ULAW_PAYLOAD 240#define ULAW_SAMPLE_RATE 240#define RESID_RTP_RATE 240#define NETWORK_RTP_RATE 160using namespace Vocal;//***************************************************************************// NullHwDevice::NullHwDevice// description: Constructor.//***************************************************************************NullHwDevice::NullHwDevice( char* deviceName, Sptr < Fifo < Sptr < SipProxyEvent > > > inputQ, Sptr < Fifo < Sptr < SipProxyEvent > > > outputQ ) : ResGwDevice( deviceName, inputQ, outputQ ), audioActive( false ), hasPlayed( false ){ // initialize queues sessionQ = outputQ; myQ = inputQ; // store the device name. myDeviceName = deviceName;#ifndef WIN32 stdinFD = fileno( stdin ); tcgetattr( stdinFD, &initialTerm ); struct termios termAttr = initialTerm; termAttr.c_lflag &= ~ICANON; termAttr.c_cc[VMIN] = 1; termAttr.c_cc[VTIME] = 0; if ( tcsetattr( stdinFD, TCSANOW, &termAttr ) != 0 ) { cerr << "Unable to set new terminal mode." << endl; exit( -1 ); }#endif} // end NullHwDevice::NullHwDevice()//***************************************************************************// QuickNetDevice::~QuickNetDevice// description: Destructor//***************************************************************************NullHwDevice::~NullHwDevice(){#ifndef WIN32 close(myFD); tcsetattr( stdinFD, TCSANOW, &initialTerm );#endif} // end NullHwDevice::~NullHwDevice()//***************************************************************************// NullHwDevice::hardwareMain// description: main processing loop of the hardware//***************************************************************************void*NullHwDevice::hardwareMain (void* parms){#if !defined(WIN32) // process forever on behalf of NullHwDevice hardware fd_set readfds; struct timeval tv; int retval; // fd_set isn't implemented quite right! int maxFd = 8; // should be 0 then increment as needed when addToFdSet // reset file descriptor FD_ZERO(&readfds); addToFdSet( &readfds ); tv.tv_sec = 0; tv.tv_usec = 300; if ((retval = select(maxFd, &readfds, 0, 0, &tv)) < 0) { cpLog( LOG_ERR, "select() returned error %d", retval ); } else if (retval > 0) { if (process(&readfds) < 0) { cpLog( LOG_ERR, "hardware encountered an error" ); assert(0); } }#else HANDLE handles [1]; handles[0] = GetStdHandle(STD_INPUT_HANDLE); DWORD dwd = WaitForMultipleObjects(1, handles, false, 300); fd_set* ptr = NULL; if (dwd == WAIT_OBJECT_0) { ptr = (fd_set*)&dwd; } if (process(ptr) < 0) { cerr << "hardware encountered an error\n"; assert(0); }#endif // check for signal requests from the session if ( myQ->size() > 0 ) { processSessionMsg( myQ->getNext() ); }; return 0;} // end NullHwDevice::hardwareMain()//***************************************************************************// NullHwDevice::process//// description: process any events detected on the hardware (dtmf digit// press, onhook & offhook, etc.) and reports the events back// to the session via the fifo queue.//***************************************************************************intNullHwDevice::process (fd_set* fd){ vusleep(0); // needed to stabilize hookstate readings Sptr < UaDeviceEvent > event = new UaDeviceEvent( sessionQ ) ; assert( event != 0 );#if !defined(WIN32) char keystroke = '\0'; read( stdinFD, &keystroke, 1 );#else char keystroke = '\n'; // ignore INPUT_RECORD ir; unsigned long cNumRead; if (fd) { HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); ReadConsoleInput( hStdin, &ir, 1, &cNumRead); if (!ir.Event.KeyEvent.bKeyDown || ir.EventType != KEY_EVENT ) { return 0; } keystroke = ir.Event.KeyEvent.uChar.AsciiChar; }#endif if(myEntryState == EntryStateEnterUrl) { // the user is entering a URL, so do something else switch( keystroke ) { case '\x08': case '\x7F': // Backspace (\b) or Delete (DEL) { if( myTextEntry.length() > 0 ) { // xxx this is lame cout << "\b \b\b \b\b \b"; cout.flush(); myTextEntry.setchar(myTextEntry.length() - 1, ' '); myTextEntry.removeSpaces(); } else { cout << "\b \b\b \b"; cout.flush(); } break; } case '\x0A': // Line Feed (\n) -> done { cpLog( LOG_DEBUG, "URL is %s", myTextEntry.logData() ); event->type = DeviceEventCallUrl; event->text = myTextEntry; myTextEntry = ""; myEntryState = EntryStateTelephoneUI; break; } default: { if( keystroke >= '\x20' && keystroke <= '\x7E' ) { // Append a character between ' ' and '~' myTextEntry.setchar(myTextEntry.length(), keystroke); } else { // Treat everything else as abort // e.g. '\1B': // Esc -> abort myTextEntry = ""; myEntryState = EntryStateTelephoneUI; cout << endl; cpLog( LOG_DEBUG, "Abort URL input" ); // Emulate a 'z' in TelephoneUI hookStateOffhook = false; event->type = DeviceEventHookDown; } break; } } } else { // process keystroke if( keystroke != '\n' ) { cpLog( LOG_DEBUG, "Keystroke read: '%c'(%x)", ( keystroke >= ' ' && keystroke <= '~' ) ? keystroke : '.', keystroke ); } switch( keystroke ) { case 'q': { // shutdown event->type = DeviceEventShutdown; cpLog( LOG_NOTICE , "User requested shutdown" ); } break; case 'a': // offhook { hookStateOffhook = true; event->type = DeviceEventHookUp; } break; case 'z': // onhook { if( hookStateOffhook ) { hookStateOffhook = false; event->type = DeviceEventHookDown; } } break; case 'f': { event->type = DeviceEventFlash; } break; case '*': { event->type = DeviceEventDtmfStar; } break; case '#': { event->type = DeviceEventDtmfHash; } break; case '0': { event->type = DeviceEventDtmf0; } break; case '1': { event->type = DeviceEventDtmf1; } break; case '2': { event->type = DeviceEventDtmf2; } break; case '3': { event->type = DeviceEventDtmf3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -