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

📄 soundcarddevice.cxx

📁 SIP(Session Initiation Protocol)是由IETF定义
💻 CXX
📖 第 1 页 / 共 3 页
字号:
    {        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 SoundCardDevice::hardwareMain()//***************************************************************************// SoundCardDevice::process//// description:  process any events detected on the hardware as well as//               simulated device events triggered by keyboard input.//               report these events back to the session via the fifo queue.//***************************************************************************intSoundCardDevice::process( fd_set* fd ){    if (!fd)    {        return 0;    }    deviceMutex.lock();    // check for events coming from the keyboard    // initialize the event we will send    Sptr<UaDeviceEvent> event = new UaDeviceEvent( sessionQ );    assert( event != 0 );    event->type = DeviceEventUndefined;#ifndef WIN32    char keystroke = '\0';    if( read( stdinFD, &keystroke, 1 ) < 1 )    {        // didn't get any keystrokes        deviceMutex.unlock();        return 0;    }#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.Event.KeyEvent.uChar.AsciiChar == 23 /* 0x17 */             || ir.Event.KeyEvent.uChar.AsciiChar == '\n'            || ir.Event.KeyEvent.uChar.AsciiChar == 0x0a            || ir.Event.KeyEvent.uChar.AsciiChar == 0)         {            deviceMutex.unlock();            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;            playDialTone = true;            event->type = DeviceEventHookUp;            break;        case 'z':  // onhook            if ( hookStateOffhook )            {                hookStateOffhook = false;                event->type = DeviceEventHookDown;            }            break;        case 'f':  // flash            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;            break;        case '4':            event->type = DeviceEventDtmf4;            break;        case '5':            event->type = DeviceEventDtmf5;            break;        case '6':            event->type = DeviceEventDtmf6;            break;        case '7':            event->type = DeviceEventDtmf7;            break;        case '8':            event->type = DeviceEventDtmf8;            break;        case '9':            event->type = DeviceEventDtmf9;            break;        case 'u':            if( hookStateOffhook )            {                cout << "\nEnter URL: ";                cout.flush();                myEntryState = EntryStateEnterUrl;            }            else            {                cpLog( LOG_ERR, "Enter 'a' first" );            }            break;        case '\n':  // ignore            break;        default:  // no events            cpLog( LOG_ERR, "Unknown keyboard input" );            break;        }    }    // send the event    if( event->type != DeviceEventUndefined )    {        assert( sessionQ != 0 );        event->callId = callId;#ifndef WIN32        sessionQ->add( event );#else        Sptr <SipProxyEvent> proxyEvent;        proxyEvent.dynamicCast( event );        sessionQ->add( proxyEvent );#endif    }        deviceMutex.unlock();    return 0;} // end SoundCardDevice::process()//***************************************************************************// SoundCardDevice::processRTP// description:  main processing loop for RTP//***************************************************************************voidSoundCardDevice::processRTP (){    if( audioStack == 0 )    {        vusleep( 1000 );        return;    }    deviceMutex.lock();    //AND:BUGFIX:?    if (audioStack == 0)     {        deviceMutex.unlock();        vusleep( 1000 );        return;    }    bool bNothingDo = true;    RtpSessionState sessionState = audioStack->getSessionState();    if ( sessionState == rtp_session_undefined )     {        deviceMutex.unlock();        vusleep( 1000 );        return;    }    // receive audio    if( sessionState == rtp_session_recvonly ||        sessionState == rtp_session_sendrecv )    {        inRtpPkt = audioStack->receive();        if( inRtpPkt )        {            if( inRtpPkt->getPayloadType() != rtpPayloadPCMU ||                inRtpPkt->getPayloadUsage() != NETWORK_RTP_RATE )            {                cpLog(LOG_ERR,"Received from RTP stack incorrect payload type");            }            writeToSoundCard( (unsigned char*) inRtpPkt->getPayloadLoc(),                              inRtpPkt->getPayloadUsage() );            bNothingDo = false;            // need to delete since RTP stack doesn't do it any more            delete inRtpPkt;             inRtpPkt = NULL;        }    }    // transmit audio    if( sessionState == rtp_session_sendonly ||        sessionState == rtp_session_sendrecv )    {        int cc;        if( audioStack->getRtcpTran() )        {            if( sendRingback )            {                cc = getRingbackTone( dataBuffer, RESID_RTP_RATE );#ifdef WIN32                Sleep(15);#endif            }            else             {                cc = readFromSoundCard( dataBuffer, RESID_RTP_RATE );            }            if ((cc > 0) && audioStack)             {                audioStack->transmitRaw( (char*)dataBuffer, cc );                bNothingDo = false;            }            else            {                cpLog(LOG_DEBUG, "failed to read data from sound card");            }        }    }#ifdef WIN32    if (bNothingDo)     { //AND: Prevent processor from 100% load        Sleep(2);    }#endif    // process RTCP    //if( audioStack && sessionState != rtp_session_inactive )    //{    //    audioStack->processRTCP();    //}    deviceMutex.unlock();    return;}intSoundCardDevice::addToFdSet( fd_set* fd ){    if( ( audioActive || audioHalfActive ) && audioStack )    {        RtpSessionState sessionState = audioStack->getSessionState();        if( sessionState == rtp_session_recvonly ||            sessionState == rtp_session_sendrecv )        {            FD_SET( ( audioStack->getRtpRecv() )->getSocketFD(), fd );//            FD_SET( ( audioStack->getRtcpRecv() )->getSocketFD(), fd );        }    }    FD_SET( myFD, fd );    return 0;} // end SoundCardDevice::addToFdSet()//***************************************************************************// SoundCardDevice::getRtpPort()//// description:  creates a new rtp session and reserves a rtp port//***************************************************************************intSoundCardDevice::getRtpPort(){    deviceMutex.lock();    //this is an arbitrarily defined number    const int MAX_RTP_PORT = UaConfiguration::instance()->getMaxRtpPort();    const int MIN_RTP_PORT = UaConfiguration::instance()->getMinRtpPort();    int port = 0;    int minPort = MIN_RTP_PORT;    // create a rtp session if there is no existing session alread    // this Rtp session will be idle    if( audioStack == 0 )    {        audioStack = new RtpSession(0);    }    while( 1 )    {        // reserve a rtp port        port = audioStack->reserveRtpPort(minPort, MAX_RTP_PORT);        minPort = (port > minPort) ? port : minPort;        // attempt to reserve a rtcp port on port number higher than        // the rtp port        if ( port != 0 && audioStack->reserveRtcpPort(port + 1, 0) != 0 )        {            break;        }        // if not successful allocating rtcp port, increment the minimum rtp        // port and try again.  If minPort reaches MAX_RTP_PORT, return 0        // to indicate port allocation failed.        minPort += 2;        if ( minPort > MAX_RTP_PORT )        {            port = 0;            break;        }    }    deviceMutex.unlock();    return port;}//***************************************************************************// SoundCardDevice::releaseRtpPort()//// description: destroy the rtp session and release the rtp port//***************************************************************************voidSoundCardDevice::releaseRtpPort(){    deviceMutex.lock();    // destroy the rtp session if one exists    if ( audioStack != 0 )    {        //AND:BUGFIX: swap 2x2 bottom 4 lines        // (or releaseRtcpPort() try use _rtp_ stack when his already        // destroy releaseRtpPort) may be Unix to be able use class        // after his ~destroy, but WIN32 close thread :)        int port = audioStack->releaseRtcpPort();        cpLog( LOG_DEBUG, "rtcp port %d released", port );        port = audioStack->releaseRtpPort();        cpLog( LOG_DEBUG, "rtp port %d released", port );        delete audioStack;        audioStack = 0;    }    deviceMutex.unlock();}//***************************************************************************// SoundCardDevice::audioStart//// description:  creates a new rtp session and also allocates memory for//               incoming and outgoing rtp packet.  ioctl calls to initialize//               the quicknet card.//***************************************************************************intSoundCardDevice::audioStart( const HardwareAudioRequest& request ){    deviceMutex.lock();    cerr << "%%% Establishing soundcard 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 << " ms" << endl;    // create new audioStack for this audio session    // 0 is rtpPayloadPCUM    // last paramter, -1, disables jitter buffer    if( audioStack == 0 )    {        int remoteRtcpPort = (request.remotePort > 0) ? request.remotePort + 1 : 0;        int localRtcpPort = (request.localPort > 0) ? request.localPort + 1 : 0;        cerr << "%%%   Remote rtcp port : " << remoteRtcpPort << "\n";        cerr << "%%%   Local rtcp port  : " << localRtcpPort << "\n\n";        const char* remoteHost = 0;        if ( request.remotePort != 0 )            remoteHost = request.remoteHost;        audioStack = new RtpSession( remoteHost, request.remotePort,                                     request.localPort, remoteRtcpPort,                                     localRtcpPort, rtpPayloadPCMU,                                     rtpPayloadPCMU, 0 );    }    else    {        cerr << "%%% Turn half duplex into full duplex" << endl;        //need to determine what mode RtpSession is in        RtpSessionState sessionState = audioStack->getSessionState();        switch ( sessionState )        {        case rtp_session_sendonly:  //turn on the receive            cerr << "%%% Turn on receive" << endl;            cerr << "%%%   local port " << request.localPort << endl;            if ( request.localPort != 0 )            {                audioStack->setSessionState( rtp_session_sendrecv );                audioStack->setReceiver( request.localPort, request.localPort + 1, 0, rtpPayloadPCMU, rtpPayloadPCMU, 0);            }            break;        case rtp_session_recvonly:  //turn on the send            cerr << "%%% Turn on send" << endl;            cerr << "%%%   remote host " << request.remoteHost << endl;            cerr << "%%%   remote port " << request.remotePort << endl;            if ( request.remotePort != 0 )            {                audioStack->setSessionState(rtp_session_sendrecv);                audioStack->setTransmiter(request.remoteHost, request.remotePort, request.remotePort + 1, rtpPayloadPCMU, rtpPayloadPCMU);

⌨️ 快捷键说明

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