📄 dupcarddevice.cxx
字号:
deviceMutex.unlock(); mySoundCard.reopen(); return 0;} // end DupCardDevice::audioStart()//***************************************************************************// DupCardDevice::audioStop//// description: tears down audio. cleans up by delete objects created when// audioStart was called... audioStack, rtp packets.//***************************************************************************intDupCardDevice::audioStop(){ if( !audioActive ) { return 1; } cerr << "%%% Stopping audio" << endl; // mark audio as deactivated. audioActive = false; audioHalfActive = false; vusleep( 200 ); deviceMutex.lock(); //AND: or thread must die !!! // should lock here, but seg faults application when unlocking below - kle // close RTP session if( audioStack ) { RtpSessionState sessionState = audioStack->getSessionState(); if( sessionState == rtp_session_sendonly || sessionState == rtp_session_sendrecv ) { audioStack->transmitRTCPBYE(); } }#if 0 if( inRtpPkt ) { delete inRtpPkt; inRtpPkt = 0; }#endif if( audioStack ) { delete audioStack; audioStack = 0; } deviceMutex.unlock(); mySoundCard.reopen(); return 0;} // end DupCardDevice::audioStop()//***************************************************************************// DupCardDevice::audioSuspend//// description: suspend the RTP transmit and receive, and also stop the////***************************************************************************intDupCardDevice::audioSuspend (){ deviceMutex.lock(); cerr << "%%% Suspending audio" << endl; cerr << "Setting all RTP / RTCP ports to 0" << endl; if ( audioStack != 0 ) { //set rtp session to inactive audioStack->setSessionState( rtp_session_inactive ); audioStack->setReceiver( 0, 0, 0, rtpPayloadPCMU, rtpPayloadPCMU, 0 ); audioStack->setTransmiter( 0, 0, 0, rtpPayloadPCMU, rtpPayloadPCMU ); } deviceMutex.unlock(); mySoundCard.reopen(); return 0;} // end DupCardDevice::audioSuspend()//***************************************************************************// DupCardDevice::audioResume//// description: resume the rtp session using the new sdp information// enable the quicknet card audio//***************************************************************************intDupCardDevice::audioResume( const HardwareAudioRequest& request ){ deviceMutex.lock(); if ( audioStack == 0 ) { cpLog( LOG_ERR, "Try to resume an existing audio channel" ); cpLog( LOG_ERR, "No existing audio channel" ); deviceMutex.unlock(); return 0; } cerr << "Resuming audio" << endl; cerr << "Listening on port: " << request.localPort << endl; cerr << "Sending to host: " << request.remoteHost << endl; cerr << "Sending to port: " << request.remotePort << endl; cerr << "RTP packet size: " << request.rtpPacketSize << endl; //resuming audio channel //int remoteRtcpPort = (request.remotePort > 0) ? request.remotePort + 1 : 0; //int localRtcpPort = (request.localPort > 0) ? request.localPort + 1 : 0; const char* remoteHost = 0; if( request.remotePort != 0 ) remoteHost = request.remoteHost; if( request.localPort != 0 && request.remotePort != 0 ) { //full duplex audio audioStack->setSessionState(rtp_session_sendrecv); audioStack->setReceiver(request.localPort, request.localPort + 1, 0, rtpPayloadPCMU, rtpPayloadPCMU, 0); audioStack->setTransmiter(request.remoteHost, request.remotePort, request.remotePort + 1, rtpPayloadPCMU, rtpPayloadPCMU); } else if ( request.localPort != 0 ) { //receive only audioStack->setSessionState(rtp_session_sendrecv); audioStack->setReceiver(request.localPort, request.localPort + 1, 0, rtpPayloadPCMU, rtpPayloadPCMU, 0); } else if ( request.remotePort != 0 ) { //transmit only audioStack->setSessionState( rtp_session_sendrecv ); audioStack->setTransmiter( request.remoteHost, request.remotePort, request.remotePort + 1, rtpPayloadPCMU, rtpPayloadPCMU ); } audioStack->setApiFormat( rtpPayloadPCMU, request.rtpPacketSize*8 ); audioStack->setNetworkFormat( rtpPayloadPCMU, request.rtpPacketSize*8 ); if( request.sendRingback ) startSendRingback(); else stopSendRingback(); deviceMutex.unlock(); mySoundCard.reopen(); return 0;} // end DupCardDevice::audioResume()//***************************************************************************// DupCardDevice::provideTone//// description: provide the tone for the soundcard by playing// a sound file of that particular tone.//***************************************************************************voidDupCardDevice::provideTone( const ToneEmulation tone ){ // open ULAW encoded sound file int toneFD; switch( tone ) { case DialToneEmulation: cpLog( LOG_DEBUG, "*** Provide dial tone emulation ***" ); toneFD = open( "Tone/dialtone", O_RDONLY ); break; case RingbackToneEmulation: cpLog( LOG_DEBUG, "*** Provide ringback tone emulation ***" ); toneFD = open( "Tone/ringback", O_RDONLY ); break; default: cpLog( LOG_ERR, "Unsupported tone requested" ); toneFD = -1; break; } if( toneFD < 0 ) { cpLog( LOG_ERR, "Cannot open tone file" ); return; } // play until file ends or hardware event mySoundCard.reopen(); bool provideToneLoop = true; while( provideToneLoop ) { int cc = read( toneFD, dataBuffer, NETWORK_RTP_RATE ); if( cc != NETWORK_RTP_RATE ) { // end of file reached provideToneLoop = false; } deviceMutex.lock(); // play tone sample mySoundCard.write( dataBuffer, NETWORK_RTP_RATE );#ifndef WIN32 // watch for a key press on stdinFD fd_set readFdSet; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO( &readFdSet ); FD_SET(stdinFD, &readFdSet ); select( stdinFD+1, &readFdSet, 0, 0, &tv ); if( FD_ISSET( stdinFD, &readFdSet ) ) { // something in the keyboard buffer provideToneLoop = false; }#else HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); INPUT_RECORD inputRecord; DWORD nRecords; if (PeekConsoleInput( hStdin, &inputRecord, 1, &nRecords) && nRecords) { if (inputRecord.Event.KeyEvent.bKeyDown) { // something in the keyboard buffer provideToneLoop = false; } }#endif if( myQ->size() > 0 ) { // need to stop tone and process endpoint msg provideToneLoop = false; } deviceMutex.unlock(); } mySoundCard.reopen(); close( toneFD );} // end provideTone()intDupCardDevice::getRingbackTone( unsigned char *ringData, const int samples ){ // open tone file if first time if( ringbackFd == -1 ) { cpLog( LOG_DEBUG, "Opening remote ringback tone file" ); if( ( ringbackFd = open( "Tone/ringback", O_RDONLY ) ) == -1 ) { cpLog( LOG_ERR, "Fail to open Tone/ringback" ); return 0; } } // read from tone file int cc = read( ringbackFd, (char*)ringData, samples ); if( cc != samples ) { //AND:may be need close file for reopen at next read() ? close(ringbackFd); ringbackFd = -1; // end of file reached return cc; } return cc;}//***************************************************************************// DupCardDevice::onhookOrFlash//// THIS FEATURE IS TURNED OFF IN THE PHONECARDDEVICE UNTIL QUICKNET// RELEASES THE SMARTCABLE.// description: quicknet does not implement a flash function on their cards.// so, we have to implement our own, by checking the hook state// of the phone. this function will tell us whether the phone// is being flashed or being placed onhook.//***************************************************************************voidDupCardDevice::onhookOrFlash(){ cpLog( LOG_DEBUG, "We know this isn't a flash!" );}voidDupCardDevice::provideDialToneStart(){ cpLog( LOG_DEBUG, "*** Start dial tone ***" ); provideTone( DialToneEmulation );}voidDupCardDevice::provideDialToneStop(){ cpLog( LOG_DEBUG, "*** Stop dial tone ***" ); if( playDialTone == true ) { playDialTone = false; mySoundCard.reopen(); }}voidDupCardDevice::provideRingStart(){ cpLog( LOG_DEBUG, "*** Start Ringing ***" ); cout << "Incoming call..." << endl << endl; //TODO play some ringing sound to speaker? //provideTone( RingbackToneEmulation );}voidDupCardDevice::provideRingStop(){ cpLog( LOG_DEBUG, "*** Stop Ringing ***" ); mySoundCard.reopen();}voidDupCardDevice::provideLocalRingbackStart(){ cpLog( LOG_DEBUG, "*** Start local ringback ***" ); provideTone( RingbackToneEmulation );}voidDupCardDevice::provideLocalRingbackStop(){ cpLog( LOG_DEBUG, "*** Stop local ringback ***" ); mySoundCard.reopen();}voidDupCardDevice::provideBusyToneStart(){ cpLog( LOG_DEBUG, "*** Start busy tone ***" );}voidDupCardDevice::provideBusyToneStop(){ cpLog( LOG_DEBUG, "*** Stop busy tone ***" );}voidDupCardDevice::provideFastBusyToneStart(){ cpLog( LOG_DEBUG, "*** Start fast busy tone ***" );}voidDupCardDevice::provideFastBusyToneStop(){ cpLog( LOG_DEBUG, "*** Stop fast busy tone ***" );}voidDupCardDevice::provideDtmf( DeviceSignalType signal ){ char digit = ' '; if ( signal >= DeviceSignalDigit0 && signal <= DeviceSignalDigit9 ) { digit = '0' + signal - DeviceSignalDigit0; } else if ( signal == DeviceSignalDigitHash ) { digit = '#'; } else if ( signal == DeviceSignalDigitStar ) { digit = '*'; } cpLog( LOG_DEBUG, "*** DTMF %c ***", digit );}voidDupCardDevice::provideCallInfo(string, string, string){}#if 0voidDupCardDevice::killDialTone(){ if( playDialTone == true ) { playDialTone = false; cpLog( LOG_DEBUG, "*** Stopping tone emulation ***" );#ifndef WIN32 //AND:Construction fall on WIN32 deviceMutex.unlock(); mySoundCard.reopen(); deviceMutex.unlock();#endif }}#endifvoidDupCardDevice::provideCallWaitingBeepStart(){ // Not yet implemented cpLog( LOG_DEBUG, "in provideCallWaitingBeepStart() - not completed" );}voidDupCardDevice::provideCallWaitingBeepStop(){ // Not yet implemented cpLog( LOG_DEBUG, "in provideCallWaitingBeepStop() - not completed" );}PlayThread::PlayThread(DupCardDevice* ptr) :myDevice(ptr){}PlayThread::~PlayThread(){}voidPlayThread::thread(){ while(true) { sleep(1); }}/* Local Variables: *//* c-file-style: "stroustrup" *//* indent-tabs-mode: nil *//* c-file-offsets: ((access-label . -) (inclass . ++)) *//* c-basic-offset: 4 *//* End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -