X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNetwork%2Ffgcom.cxx;h=8d1bfc96c8bb332af58b23ac6677891247fb75f3;hb=b0dcb657e77579ecc79798ff365737095f96f9e2;hp=5d9319c2053139b9eaf2d7a94354ec2858200205;hpb=7827e28ff3ab9e2d90634fb119cb3c0b68737678;p=flightgear.git diff --git a/src/Network/fgcom.cxx b/src/Network/fgcom.cxx index 5d9319c20..8d1bfc96c 100644 --- a/src/Network/fgcom.cxx +++ b/src/Network/fgcom.cxx @@ -1,6 +1,6 @@ // fgcom.cxx -- FGCom: Voice communication // -// Written by Clement de l'Hamaide, started Mai 2013. +// Written by Clement de l'Hamaide, started May 2013. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,32 +39,66 @@ #include #include -#include +#include <3rdparty/iaxclient/lib/iaxclient.h> #define NUM_CALLS 4 +#define MAX_GND_RANGE 10.0 +#define MAX_TWR_RANGE 50.0 #define MAX_RANGE 100.0 #define MIN_RANGE 20.0 +#define MIN_GNDTWR_RANGE 0.0 #define DEFAULT_SERVER "fgcom.flightgear.org" #define IAX_DELAY 300 // delay between calls in milliseconds #define TEST_FREQ 910.00 #define NULL_ICAO "ZZZZ" const int special_freq[] = { // Define some freq who need to be used with NULL_ICAO + 910000, 911000, 700000, 123450, 122750, 121500, - 123500, - 121000, - 723340 }; + 123500 }; + +static FGCom* static_instance = NULL; + + + +static int iaxc_callback( iaxc_event e ) +{ + switch( e.type ) + { + case IAXC_EVENT_TEXT: + static_instance->iaxTextEvent(e.ev.text); + break; + default: + return 0; + } + return 1; +} + + + +void FGCom::iaxTextEvent(struct iaxc_ev_text text) +{ + if( (text.type == IAXC_TEXT_TYPE_STATUS || + text.type == IAXC_TEXT_TYPE_IAX) && + _showMessages_node->getBoolValue() ) + { + _text_node->setStringValue(text.message); + } +} + FGCom::FGCom() : - _register(true) + _register(true), + _enabled(false), + _initialized(false), + _listener_active(0) { - _listener_active = 0; } @@ -83,21 +117,23 @@ void FGCom::bind() _enabled_node = node->getChild( "enabled", 0, true ); _micBoost_node = node->getChild( "mic-boost", 0, true ); _micLevel_node = node->getChild( "mic-level", 0, true ); + _silenceThd_node = node->getChild( "silence-threshold", 0, true ); _speakerLevel_node = node->getChild( "speaker-level", 0, true ); _selectedInput_node = node->getChild( "device-input", 0, true ); _selectedOutput_node = node->getChild( "device-output", 0, true ); + _showMessages_node = node->getChild( "show-messages", 0, true ); SGPropertyNode *reg_node = node->getChild("register", 0, true); _register_node = reg_node->getChild( "enabled", 0, true ); _username_node = reg_node->getChild( "username", 0, true ); _password_node = reg_node->getChild( "password", 0, true ); - //_nav0_node = fgGetNode("/instrumentation/nav[0]/frequencies/selected-mhz", true); - //_nav1_node = fgGetNode("/instrumentation/nav[1]/frequencies/selected-mhz", true); _comm0_node = fgGetNode("/instrumentation/comm[0]/frequencies/selected-mhz", true); - //_comm1_node = fgGetNode("/instrumentation/comm[1]/frequencies/selected-mhz", true); + _comm1_node = fgGetNode("/instrumentation/comm[1]/frequencies/selected-mhz", true); _ptt0_node = fgGetNode("/instrumentation/comm[0]/ptt", true); //FIXME: what about /instrumentation/comm[1]/ptt ? _callsign_node = fgGetNode("/sim/multiplay/callsign", true); + _text_node = fgGetNode("/sim/messages/atc", true ); + _version_node = fgGetNode("/sim/version/flightgear", true ); // Set default values if not provided if ( !_enabled_node->hasValue() ) @@ -118,6 +154,9 @@ void FGCom::bind() if ( !_micLevel_node->hasValue() ) _micLevel_node->setFloatValue(1.0); + if ( !_silenceThd_node->hasValue() ) + _silenceThd_node->setFloatValue(-35.0); + if ( !_register_node->hasValue() ) _register_node->setBoolValue(false); @@ -127,16 +166,18 @@ void FGCom::bind() if ( !_password_node->hasValue() ) _password_node->setStringValue("guest"); + if ( !_showMessages_node->hasValue() ) + _showMessages_node->setBoolValue(false); + _selectedOutput_node->addChangeListener(this); _selectedInput_node->addChangeListener(this); _speakerLevel_node->addChangeListener(this); + _silenceThd_node->addChangeListener(this); _micBoost_node->addChangeListener(this); _micLevel_node->addChangeListener(this); _enabled_node->addChangeListener(this); _comm0_node->addChangeListener(this); - //_comm1_node->addChangeListener(this); - //_nav0_node->addChangeListener(this); - //_nav1_node->addChangeListener(this); + _comm1_node->addChangeListener(this); _ptt0_node->addChangeListener(this); _test_node->addChangeListener(this); } @@ -156,16 +197,16 @@ void FGCom::init() _register = _register_node->getBoolValue(); _username = _username_node->getStringValue(); _password = _password_node->getStringValue(); + _selectedComm = 0; _currentComm0 = _comm0_node->getDoubleValue(); - //_currentComm1 = _comm1_node->getDoubleValue(); - //_currentNav0 = _nav0_node->getDoubleValue(); - //_currentNav1 = _nav1_node->getDoubleValue(); + _currentComm1 = _comm1_node->getDoubleValue(); _comm0Changed = false; - //_comm1Changed = false; - //_nav0Changed = false; - //_nav1Changed = false; + _comm1Changed = false; + + _maxRange = MAX_RANGE; + _minRange = MIN_RANGE; } @@ -178,22 +219,36 @@ void FGCom::postinit() //WARNING: this _must_ be executed after sound system is totally initialized ! if( iaxc_initialize(NUM_CALLS) ) { - SG_LOG(SG_IO, SG_ALERT, "FGCom: cannot initialize iaxclient!"); + SG_LOG(SG_IO, SG_ALERT, "FGCom: cannot initialize iaxclient"); _enabled = false; return; } + + assert( static_instance == NULL ); + static_instance = this; + iaxc_set_event_callback( iaxc_callback ); // FIXME: To be implemented in IAX audio driver //iaxc_mic_boost_set( _micBoost_node->getIntValue() ); - iaxc_set_formats( IAXC_FORMAT_GSM, IAXC_FORMAT_GSM ); + std::string app = "FGFS-"; + app += _version_node->getStringValue(); + + iaxc_set_callerid( _callsign_node->getStringValue(), app.c_str() ); + iaxc_set_formats (IAXC_FORMAT_SPEEX, IAXC_FORMAT_ULAW|IAXC_FORMAT_SPEEX); + iaxc_set_speex_settings(1, 5, 0, 1, 0, 3); + iaxc_set_filters(IAXC_FILTER_AGC | IAXC_FILTER_DENOISE); + iaxc_set_silence_threshold(_silenceThd_node->getFloatValue()); iaxc_start_processing_thread (); + + // Now IAXClient is initialized + _initialized = true; if ( _register ) { _regId = iaxc_register( const_cast(_username.c_str()), const_cast(_password.c_str()), const_cast(_server.c_str()) ); if( _regId == -1 ) { - SG_LOG(SG_IO, SG_INFO, "FGCom: cannot register iaxclient!"); + SG_LOG(SG_IO, SG_ALERT, "FGCom: cannot register iaxclient"); return; } } @@ -255,6 +310,10 @@ void FGCom::postinit() _selectedOutput_node->setIntValue(devs[i].devID); } + // Mute the mic and set speaker at start + iaxc_input_level_set( 0.0 ); + iaxc_output_level_set( _speakerLevel_node->getFloatValue() ); + iaxc_millisleep(50); // Do the first call at start @@ -262,11 +321,10 @@ void FGCom::postinit() _currentFreqKhz = 10 * static_cast(freq * 100 + 0.25); std::string num = computePhoneNumber(freq, getAirportCode(freq)); if( !num.empty() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom comm[0] number=" << num ); _callComm0 = iaxc_call(num.c_str()); } if( _callComm0 == -1 ) - SG_LOG( SG_IO, SG_ALERT, "FGCom cannot call selected freq" ); + SG_LOG( SG_IO, SG_DEBUG, "FGCom: cannot call " << num.c_str() ); } @@ -286,8 +344,7 @@ void FGCom::updateCall(bool& changed, int& callNo, double freqMHz) return; } } - - SG_LOG( SG_IO, SG_INFO, "FGCom manage change" ); + changed = false; // FIXME, out-params are confusing if( callNo != -1 ) { @@ -300,11 +357,10 @@ void FGCom::updateCall(bool& changed, int& callNo, double freqMHz) if( !isInRange(freqMHz) ) return; if( !num.empty() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom number=" << num ); - callNo = iaxc_call_ex(num.c_str(), _callsign.c_str(), NULL, 0 /* no video */); + callNo = iaxc_call(num.c_str()); if( callNo == -1 ) - SG_LOG( SG_IO, SG_ALERT, "FGCom cannot call selected freq" ); + SG_LOG( SG_IO, SG_DEBUG, "FGCom: cannot call " << num.c_str() ); } } else { changed = true; @@ -315,27 +371,37 @@ void FGCom::updateCall(bool& changed, int& callNo, double freqMHz) void FGCom::update(double dt) { - if ( !_enabled ) { + if ( !_enabled || !_initialized ) { return; } + // For now we manage FGCom for only one freq because IAXClient // is not able to handle multiple calls at same time. - updateCall(_comm0Changed, _callComm0, _comm0_node->getDoubleValue()); - // updateCall(_comm1Changed, _callComm1, _comm1_node->getDoubleValue()); - // updateCall(_nav0Changed, _callNav0, _nav0_node->getDoubleValue()); - // updateCall(_nav1Changed, _callNav1, _nav1_node->getDoubleValue()); + if( _selectedComm == 0) { + updateCall(_comm0Changed, _callComm0, _comm0_node->getDoubleValue()); + } else { + updateCall(_comm1Changed, _callComm0, _comm1_node->getDoubleValue()); + } } void FGCom::shutdown() { - SG_LOG( SG_IO, SG_INFO, "FGCom shutdown()" ); + if( !_enabled ) { + return; + } + + _initialized = false; _enabled = false; + iaxc_set_event_callback(NULL); iaxc_unregister(_regId); iaxc_stop_processing_thread(); iaxc_shutdown(); + + assert( static_instance == this ); + static_instance = NULL; } @@ -343,8 +409,12 @@ void FGCom::shutdown() void FGCom::valueChanged(SGPropertyNode *prop) { if (prop == _enabled_node) { - SG_LOG( SG_IO, SG_INFO, "FGCom enabled= " << prop->getBoolValue() ); - if( prop->getBoolValue() ) { + bool isEnabled = prop->getBoolValue(); + if (_enabled == isEnabled) { + return; + } + + if( isEnabled ) { init(); postinit(); } else { @@ -354,36 +424,51 @@ void FGCom::valueChanged(SGPropertyNode *prop) } if (prop == _ptt0_node && _enabled) { + if( _ptt0_node->getIntValue() == 2 ) { + if( _selectedComm == 0 ) { + SG_LOG( SG_IO, SG_INFO, "FGCom: change comm source to comm[1]" ); + _comm1Changed = true; + _selectedComm = 1; + } else { + SG_LOG( SG_IO, SG_INFO, "FGCom: change comm source to comm[0]" ); + _comm0Changed = true; + _selectedComm = 0; + } + return; + } if( _ptt0_node->getBoolValue() ) { - iaxc_input_level_set( _micLevel_node->getFloatValue() ); //0.0 = min , 1.0 = max iaxc_output_level_set( 0.0 ); + iaxc_input_level_set( _micLevel_node->getFloatValue() ); //0.0 = min , 1.0 = max } else { - iaxc_input_level_set( 0.0 ); iaxc_output_level_set( _speakerLevel_node->getFloatValue() ); + iaxc_input_level_set( 0.0 ); } } if (prop == _test_node) { - SG_LOG( SG_IO, SG_INFO, "FGCom test= " << prop->getBoolValue() ); testMode( prop->getBoolValue() ); return; } + if (prop == _silenceThd_node && _initialized) { + float silenceThd = prop->getFloatValue(); + SG_CLAMP_RANGE( silenceThd, -60, 0 ); + iaxc_set_silence_threshold( silenceThd ); + return; + } + //FIXME: not implemented in IAX audio driver (audio_openal.c) - if (prop == _micBoost_node && _enabled) { + if (prop == _micBoost_node && _initialized) { int micBoost = prop->getIntValue(); - SG_LOG( SG_IO, SG_INFO, "FGCom mic-boost= " << micBoost ); SG_CLAMP_RANGE( micBoost, 0, 1 ); iaxc_mic_boost_set( micBoost ) ; // 0 = enabled , 1 = disabled return; } //FIXME: not implemented in IAX audio driver (audio_openal.c) - if ((prop == _selectedInput_node || prop == _selectedOutput_node) && _enabled) { + if ((prop == _selectedInput_node || prop == _selectedOutput_node) && _initialized) { int selectedInput = _selectedInput_node->getIntValue(); int selectedOutput = _selectedOutput_node->getIntValue(); - SG_LOG( SG_IO, SG_INFO, "FGCom selected-input= " << selectedInput ); - SG_LOG( SG_IO, SG_INFO, "FGCom selected-output= " << selectedOutput ); iaxc_audio_devices_set(selectedInput, selectedOutput, 0); return; } @@ -395,7 +480,6 @@ void FGCom::valueChanged(SGPropertyNode *prop) if (prop == _speakerLevel_node && _enabled) { float speakerLevel = prop->getFloatValue(); - SG_LOG( SG_IO, SG_INFO, "FGCom speaker-level= " << speakerLevel ); SG_CLAMP_RANGE( speakerLevel, 0.0, 1.0 ); _speakerLevel_node->setFloatValue(speakerLevel); iaxc_output_level_set(speakerLevel); @@ -403,47 +487,27 @@ void FGCom::valueChanged(SGPropertyNode *prop) if (prop == _micLevel_node && _enabled) { float micLevel = prop->getFloatValue(); - SG_LOG( SG_IO, SG_INFO, "FGCom mic-level= " << micLevel ); SG_CLAMP_RANGE( micLevel, 0.0, 1.0 ); _micLevel_node->setFloatValue(micLevel); - iaxc_input_level_set(micLevel); + //iaxc_input_level_set(micLevel); } if (prop == _comm0_node) { if( _currentComm0 != prop->getDoubleValue() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom comm[0]/freq= " << prop->getDoubleValue() ); _currentComm0 = prop->getDoubleValue(); _p.stamp(); _comm0Changed = true; } } -/* + if (prop == _comm1_node) { if( _currentComm1 != prop->getDoubleValue() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom comm[1]/freq= " << prop->getDoubleValue() ); _currentComm1 = prop->getDoubleValue(); _p.stamp(); _comm1Changed = true; } } - if (prop == _nav0_node) { - if( _currentNav0 != prop->getDoubleValue() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom nav[0]/freq= " << prop->getDoubleValue() ); - _currentNav0 = prop->getDoubleValue(); - _nav0Changed = true; - } - } - - if (prop == _nav1_node) { - if( _currentNav1 != prop->getDoubleValue() ) { - SG_LOG( SG_IO, SG_INFO, "FGCom nav[1]/freq= " << prop->getDoubleValue() ); - _currentNav1 = prop->getDoubleValue(); - _nav1Changed = true; - } - } -*/ - _listener_active--; } @@ -451,24 +515,27 @@ void FGCom::valueChanged(SGPropertyNode *prop) void FGCom::testMode(bool testMode) { - if(testMode) { + if(testMode && _initialized) { _enabled = false; - iaxc_dump_call_number(_callComm0); - iaxc_input_level_set( _micLevel_node->getFloatValue() ); + iaxc_dump_all_calls(); + iaxc_input_level_set( 1.0 ); iaxc_output_level_set( _speakerLevel_node->getFloatValue() ); std::string num = computePhoneNumber(TEST_FREQ, NULL_ICAO); if( num.size() > 0 ) { - SG_LOG( SG_IO, SG_INFO, "FGCom test mode =" << num ); iaxc_millisleep(IAX_DELAY); _callComm0 = iaxc_call(num.c_str()); } if( _callComm0 == -1 ) - SG_LOG( SG_IO, SG_ALERT, "FGCom cannot call selected freq (test mode)" ); + SG_LOG( SG_IO, SG_DEBUG, "FGCom: cannot call " << num.c_str() ); } else { - iaxc_dump_call_number(_callComm0); - iaxc_millisleep(IAX_DELAY); - _callComm0 = -1; - _enabled = true; + if( _initialized ) { + iaxc_dump_all_calls(); + iaxc_millisleep(IAX_DELAY); + iaxc_input_level_set( 0.0 ); + iaxc_output_level_set( _speakerLevel_node->getFloatValue() ); + _callComm0 = -1; + _enabled = true; + } } } @@ -485,17 +552,28 @@ std::string FGCom::getAirportCode(const double& freq) for(size_t i=0; itype() == FGPositioned::FREQ_TOWER ) { + _maxRange = MAX_TWR_RANGE; + _minRange = MIN_GNDTWR_RANGE; + } else if( apt->type() == FGPositioned::FREQ_GROUND ) { + _maxRange = MAX_GND_RANGE; + _minRange = MIN_GNDTWR_RANGE; + } else { + _maxRange = MAX_RANGE; + _minRange = MIN_RANGE; } - SG_LOG( SG_IO, SG_INFO, "FGCom getAirportCode: found " << apt->airport()->ident() ); _aptPos = apt->geod(); return apt->airport()->ident(); @@ -503,28 +581,6 @@ std::string FGCom::getAirportCode(const double& freq) -/* - \param freq The requested frequency e.g 112.7 - \return The ICAO code as string e.g ITS -*/ -/* -std::string FGCom::getVorCode(const double& freq) const -{ - SGGeod aircraftPos = globals->get_aircraft_position(); - FGNavList::TypeFilter filter(FGPositioned::VOR); - - FGNavRecord* vor = FGNavList::findByFreq( freq, aircraftPos, &filter); - if( !vor ) { - SG_LOG( SG_IO, SG_INFO, "FGCom getVorCode: not found" ); - return std::string(); - } - SG_LOG( SG_IO, SG_INFO, "FGCom getVorCode: found " << vor->get_ident(); ); - - return vor->get_ident(); -} -*/ - - /* \param freq The requested frequency e.g 120.825 \param iaco The associated ICAO code e.g LFMV @@ -584,8 +640,8 @@ bool FGCom::isInRange(const double &freq) const double delta_elevation_ft = fabs(acftPos.getElevationFt() - _aptPos.getElevationFt()); double rangeNm = 1.23 * sqrt(delta_elevation_ft); - if (rangeNm > MAX_RANGE) rangeNm = MAX_RANGE; - if (rangeNm < MIN_RANGE) rangeNm = MIN_RANGE; + if (rangeNm > _maxRange) rangeNm = _maxRange; + if (rangeNm < _minRange) rangeNm = _minRange; if( distNm > rangeNm ) return 0; return 1; }