📄 tpjackhardware.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 ,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 TpjackHardware_cxx_Version = "$Id: TpjackHardware.cxx,v 1.18 2001/01/10 20:51:26 liuhong Exp $";/* stdlib */#include <iostream.h>#include <stdio.h>#include <unistd.h>#include <sys/ioctl.h>#include <signal.h>/* #include <signum.h> *//* sockets */#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <fcntl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>/* error handling */#include <errno.h>#include "ixjuser.h"#include "TpjackHardware.h"#define ULAW_PAYLOAD 240// Interface for Quicknet's Internet Phone Jack hardware using their// drivers.TpjackHardware::TpjackHardware (char* device) : audioActive(false), hasPlayed(false){ // set to raw mode myFD = open(device, O_RDWR); if (myFD < 0) { cerr << "cannot open " << device << "\n"; exit(1); } ioctl(myFD, IXJCTL_REC_STOP); ioctl(myFD, IXJCTL_PLAY_STOP); ioctl(myFD, IXJCTL_AEC_STOP); close(myFD); myFD = open(device, O_RDWR); if (myFD < 0) { cerr << "cannot open " << device << "\n"; exit(1); } if (ioctl(myFD, IXJCTL_HOOKSTATE)) { hookSwitchOffHook = true; } else { hookSwitchOffHook = false; }}TpjackHardware::~TpjackHardware (void){ close(myFD);}int TpjackHardware::process (fd_set* fd){ int retval = 0; if (ioctl(myFD, IXJCTL_HOOKSTATE)) { // user is offhook if (hookSwitchOffHook == false) { // change from onhook to offhook hookSwitchOffHook = true; outgoingEvents.push(EventOffHook); retval++; } else { // check for DTMF digit if (ioctl(myFD, IXJCTL_DTMF_READY)) { // new digit switch (ioctl(myFD, IXJCTL_GET_DTMF)) { case 1: { outgoingEvents.push(EventDigit1); retval++; } break; case 2: { outgoingEvents.push(EventDigit2); retval++; } break; case 3: { outgoingEvents.push(EventDigit3); retval++; } break; case 4: { outgoingEvents.push(EventDigit4); retval++; } break; case 5: { outgoingEvents.push(EventDigit5); retval++; } break; case 6: { outgoingEvents.push(EventDigit6); retval++; } break; case 7: { outgoingEvents.push(EventDigit7); retval++; } break; case 8: { outgoingEvents.push(EventDigit8); retval++; } break; case 9: { outgoingEvents.push(EventDigit9); retval++; } break; case 0x0A: { outgoingEvents.push(EventDigitStar); retval++; } break; case 0x0B: { outgoingEvents.push(EventDigit0); retval++; } break; case 0x0C: { outgoingEvents.push(EventDigitHash); retval++; } break; default: { cerr << "unrecognized DTMF digit\n"; } break; } // end switch } } } else { // user is onhook if (hookSwitchOffHook == true) { // change from offhook to onhook outgoingEvents.push(EventOnHook); hookSwitchOffHook = false; retval++; } } if (audioActive) { // sending and receiving audio packets /* outgoing packet */ if (FD_ISSET(myFD, fd)) { int cardByteCount = read(myFD, outBufferPkt, 240); if (!hasPlayed) { cerr << "begin audio\n"; hasPlayed = true; } if (cardByteCount > 0) { audioStack->transmitRaw (outBufferPkt, cardByteCount); } } struct timeval tv; /* incoming packet */ if (FD_ISSET((audioStack->getRtpRecv())->getSocketFD(), fd)) { if ((inRtpPkt = audioStack->receive()) > 0) { fd_set writeOkSet; FD_ZERO(&writeOkSet); FD_SET(myFD, &writeOkSet); tv.tv_sec = 0; tv.tv_usec = 0; if (select(128, NULL, &writeOkSet, NULL, &tv) <= 0) { cerr << "error in select: " << errno << endl; } else if (hasPlayed) { if (FD_ISSET(myFD, &writeOkSet)) { write(myFD, inRtpPkt->getPayloadLoc(), 240); // inRtpPkt->getPayloadUsage()); // need to delete it since RTP doesn't delete it any more. delete inRtpPkt; inRtpPkt = NULL; } else { cerr << "can't write -- not ready\n"; } } } } /* outgoing control packet */#if 0 audioStack->processRTCP();#endif /* incoming control packet */ if (FD_ISSET((audioStack->getRtcpRecv())->getSocketFD(), fd)) audioStack->receiveRTCP(); } return retval;}int TpjackHardware::addToFdSet (fd_set* fd){ if (audioActive) { FD_SET((audioStack->getRtpRecv())->getSocketFD(), fd); FD_SET((audioStack->getRtcpRecv())->getSocketFD(), fd); FD_SET(myFD, fd); } return 0;}HardwareEvent TpjackHardware::getEvent (){ HardwareEvent ev; if (!outgoingEvents.empty()) { ev = outgoingEvents.front(); outgoingEvents.pop(); } else { ev = EventNULL; } return ev;}int TpjackHardware::sendSignal (HardwareSignal signal){ int retval = 0; switch (signal) { case SignalRingStart: cerr << "started ringing...\n"; ioctl(myFD, IXJCTL_RING); break; case SignalRingStop: cerr << "stopped ringing...\n"; // no call to explicitly stop ringing is available at this time //ioctl(myFD, IXJCTL_RING_STOP); break; case SignalLocalRingbackStart: cerr << "started local ringback...\n"; ioctl(myFD, IXJCTL_RINGBACK); break; case SignalLocalRingbackStop: cerr << "stopped local ringback...\n"; ioctl(myFD, IXJCTL_CPT_STOP); break; case SignalBusyStart: cerr << "started busy...\n"; ioctl(myFD, IXJCTL_BUSY); break; case SignalBusyStop: cerr << "stopped busy...\n"; ioctl(myFD, IXJCTL_CPT_STOP); break; case SignalAudioStop: cerr << "stopped audio...\n"; ioctl(myFD, IXJCTL_REC_STOP); ioctl(myFD, IXJCTL_PLAY_STOP); ioctl(myFD, IXJCTL_AEC_STOP); close(myFD); // myFD = open("/dev/ixj0", O_RDWR); myFD = open("/dev/phone0", O_RDWR); if (myFD < 0) { // cerr << "cannot open /dev/ixj0 \n"; cerr << "cannot open /dev/phone0 \n"; exit(1); } audioStack->transmitRTCPBYE(); close((audioStack->getRtpRecv())->getSocketFD()); close((audioStack->getRtcpRecv())->getSocketFD()); audioActive = false; hasPlayed = false; delete audioStack; audioStack = NULL; break; default: cerr << "requested signal not supported by hardware\n"; retval = -1; // signal not supported by hardware break; } return retval;}int TpjackHardware::audioStart (int inPort, const char* outHost, int outPort){ cerr << "started audio...\n"; audioStack = new RtpSession(outHost, outPort, inPort, outPort + 1, inPort + 1, rtpPayloadPCMU, rtpPayloadPCMU, 5 ); audioStack->setApiFormat( rtpPayloadPCMU, 240 ); audioStack->setNetworkFormat( rtpPayloadPCMU, 160 ); inRtpPkt = NULL; ioctl(myFD, IXJCTL_PLAY_CODEC, ULAW); ioctl(myFD, IXJCTL_REC_CODEC, ULAW); ioctl(myFD, IXJCTL_PLAY_START); ioctl(myFD, IXJCTL_REC_START); ioctl(myFD, IXJCTL_AEC_START, 0); audioActive = true; hasPlayed = false; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -