X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Ffg_io.cxx;h=cd66cf0c6447a7b689067f5446cc57a286c4f13e;hb=6d158e886ca230c8a3cea8197229129a8b0660da;hp=b987fe6a71a424c34ee0c91b24d91857bff07caa;hpb=f3d4f741f097e1a9e1545389b95413d8b78f3b0f;p=flightgear.git diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index b987fe6a7..cd66cf0c6 100644 --- a/src/Main/fg_io.cxx +++ b/src/Main/fg_io.cxx @@ -2,7 +2,7 @@ // // Written by Curtis Olson, started November 1999. // -// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -16,16 +16,20 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#include // atoi() +#include // atoi() -#include STL_STRING +#include +#include #include #include @@ -38,44 +42,49 @@ #include #include -#include +#include #include +#include +#include +#include #include #include #ifdef FG_JPEG_SERVER # include #endif #include -#include +#include #include #include #include +#include #include #include #include #include #include #include +#include + +#ifdef FG_HAVE_HLA +#include +#endif #include "globals.hxx" #include "fg_io.hxx" -SG_USING_STD(string); +using std::atoi; +using std::string; FGIO::FGIO() { } -#include STL_ALGORITHM -SG_USING_STD(for_each); - -static void delete_ptr( FGProtocol* p ) { delete p; } FGIO::~FGIO() { - shutdown_all(); - for_each( io_channels.begin(), io_channels.end(), delete_ptr ); + } @@ -85,87 +94,170 @@ FGIO::parse_port_config( const string& config ) { SG_LOG( SG_IO, SG_INFO, "Parse I/O channel request: " << config ); - vector tokens = simgear::strutils::split( config, "," ); + string_list tokens = simgear::strutils::split( config, "," ); if (tokens.empty()) { - SG_LOG( SG_IO, SG_ALERT, - "Port configuration error: empty config string" ); - return 0; + SG_LOG( SG_IO, SG_ALERT, + "Port configuration error: empty config string" ); + return NULL; } string protocol = tokens[0]; SG_LOG( SG_IO, SG_INFO, " protocol = " << protocol ); - FGProtocol *io = 0; + FGProtocol *io = NULL; try { - if ( protocol == "atc610x" ) { - FGATC610x *atc610x = new FGATC610x; - atc610x->set_hz( 30 ); - return atc610x; - } else if ( protocol == "atlas" ) { - FGAtlas *atlas = new FGAtlas; - io = atlas; - } else if ( protocol == "opengc" ) { - // char wait; - // printf("Parsed opengc\n"); cin >> wait; - FGOpenGC *opengc = new FGOpenGC; - io = opengc; - } else if ( protocol == "garmin" ) { - FGGarmin *garmin = new FGGarmin; - io = garmin; - } else if ( protocol == "httpd" ) { - // determine port - string port = tokens[1]; - return new FGHttpd( atoi(port.c_str()) ); + if ( protocol == "atcsim" ) { + FGATCMain *atcsim = new FGATCMain; + atcsim->set_hz( 30 ); + if ( tokens.size() != 6 ) { + SG_LOG( SG_IO, SG_ALERT, "Usage: --atcsim=[no-]pedals," + << "input0_config,input1_config," + << "output0_config,output1_config,file.nas" ); + delete atcsim; + return NULL; + } + if ( tokens[1] == "no-pedals" ) { + fgSetBool( "/input/atcsim/ignore-pedal-controls", true ); + } else { + fgSetBool( "/input/atcsim/ignore-pedal-controls", false ); + } + atcsim->set_path_names(tokens[2], tokens[3], tokens[4], tokens[5]); + return atcsim; + } else if ( protocol == "atlas" ) { + FGAtlas *atlas = new FGAtlas; + io = atlas; + } else if ( protocol == "opengc" ) { + FGOpenGC *opengc = new FGOpenGC; + io = opengc; + } else if ( protocol == "AV400" ) { + FGAV400 *av400 = new FGAV400; + io = av400; + } else if ( protocol == "AV400Sim" ) { + FGAV400Sim *av400sim = new FGAV400Sim; + io = av400sim; + } else if ( protocol == "AV400WSimA" ) { + FGAV400WSimA *av400wsima = new FGAV400WSimA; + io = av400wsima; + } else if ( protocol == "AV400WSimB" ) { + FGAV400WSimB *av400wsimb = new FGAV400WSimB; + io = av400wsimb; + } else if ( protocol == "garmin" ) { + FGGarmin *garmin = new FGGarmin; + io = garmin; + } else if ( protocol == "httpd" ) { + // determine port + string port = tokens[1]; + return new FGHttpd( atoi(port.c_str()) ); #ifdef FG_JPEG_SERVER - } else if ( protocol == "jpg-httpd" ) { - // determine port - string port = tokens[1]; - return new FGJpegHttpd( atoi(port.c_str()) ); + } else if ( protocol == "jpg-httpd" ) { + // determine port + string port = tokens[1]; + return new FGJpegHttpd( atoi(port.c_str()) ); +#endif + } else if ( protocol == "joyclient" ) { + FGJoyClient *joyclient = new FGJoyClient; + io = joyclient; + } else if ( protocol == "jsclient" ) { + FGJsClient *jsclient = new FGJsClient; + io = jsclient; + } else if ( protocol == "native" ) { + FGNative *native = new FGNative; + io = native; + } else if ( protocol == "native-ctrls" ) { + FGNativeCtrls *native_ctrls = new FGNativeCtrls; + io = native_ctrls; + } else if ( protocol == "native-fdm" ) { + FGNativeFDM *native_fdm = new FGNativeFDM; + io = native_fdm; + } else if ( protocol == "native-gui" ) { + FGNativeGUI *net_gui = new FGNativeGUI; + io = net_gui; + } else if ( protocol == "nmea" ) { + FGNMEA *nmea = new FGNMEA; + io = nmea; + } else if ( protocol == "props" || protocol == "telnet" ) { + io = new FGProps( tokens ); + return io; + } else if ( protocol == "pve" ) { + FGPVE *pve = new FGPVE; + io = pve; + } else if ( protocol == "ray" ) { + FGRAY *ray = new FGRAY; + io = ray; + } else if ( protocol == "rul" ) { + FGRUL *rul = new FGRUL; + io = rul; + } else if ( protocol == "generic" ) { + FGGeneric *generic = new FGGeneric( tokens ); + if (!generic->getInitOk()) + { + // failed to initialize (i.e. invalid configuration) + delete generic; + return NULL; + } + io = generic; + } else if ( protocol == "multiplay" ) { + if ( tokens.size() != 5 ) { + SG_LOG( SG_IO, SG_ALERT, "Ignoring invalid --multiplay option " + "(4 arguments expected: --multiplay=dir,hz,hostname,port)" ); + return NULL; + } + string dir = tokens[1]; + int rate = atoi(tokens[2].c_str()); + string host = tokens[3]; + + short port = atoi(tokens[4].c_str()); + + // multiplay used to be handled by an FGProtocol, but no longer. This code + // retains compatibility with existing command-line syntax + fgSetInt("/sim/multiplay/tx-rate-hz", rate); + if (dir == "in") { + fgSetInt("/sim/multiplay/rxport", port); + fgSetString("/sim/multiplay/rxhost", host.c_str()); + } else if (dir == "out") { + fgSetInt("/sim/multiplay/txport", port); + fgSetString("/sim/multiplay/txhost", host.c_str()); + } + + return NULL; + } +#ifdef FG_HAVE_HLA + else if ( protocol == "hla" ) { + return new FGHLA(tokens); + } + else if ( protocol == "hla-local" ) { + // This is just about to bring up some defaults + if (tokens.size() != 2) { + SG_LOG( SG_IO, SG_ALERT, "Ignoring invalid --hla-local option " + "(one argument expected: --hla-local=" ); + return NULL; + } + tokens.insert(tokens.begin(), ""); + tokens.insert(tokens.begin(), "60"); + tokens.insert(tokens.begin(), "bi"); + tokens.push_back("fg-local.xml"); + return new FGHLA(tokens); + } #endif - } else if ( protocol == "joyclient" ) { - FGJoyClient *joyclient = new FGJoyClient; - io = joyclient; - } else if ( protocol == "native" ) { - FGNative *native = new FGNative; - io = native; - } else if ( protocol == "native_ctrls" ) { - FGNativeCtrls *native_ctrls = new FGNativeCtrls; - io = native_ctrls; - } else if ( protocol == "native_fdm" ) { - FGNativeFDM *native_fdm = new FGNativeFDM; - io = native_fdm; - } else if ( protocol == "mini_fdm" ) { - FGMiniFDM *mini_fdm = new FGMiniFDM; - io = mini_fdm; - } else if ( protocol == "nmea" ) { - FGNMEA *nmea = new FGNMEA; - io = nmea; - } else if ( protocol == "props" || protocol == "telnet" ) { - io = new FGProps( tokens ); - return io; - } else if ( protocol == "pve" ) { - FGPVE *pve = new FGPVE; - io = pve; - } else if ( protocol == "ray" ) { - FGRAY *ray = new FGRAY; - io = ray; - } else if ( protocol == "rul" ) { - FGRUL *rul = new FGRUL; - io = rul; - } else { - return NULL; - } + else { + return NULL; + } } catch (FGProtocolConfigError& err) { - SG_LOG( SG_IO, SG_ALERT, "Port configuration error: " << err.what() ); - delete io; - return 0; + SG_LOG( SG_IO, SG_ALERT, "Port configuration error: " << err.what() ); + delete io; + return NULL; } + if (tokens.size() < 3) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of network arguments."); + delete io; + return NULL; + } string medium = tokens[1]; SG_LOG( SG_IO, SG_INFO, " medium = " << medium ); @@ -179,33 +271,72 @@ FGIO::parse_port_config( const string& config ) SG_LOG( SG_IO, SG_INFO, " hertz = " << hertz ); if ( medium == "serial" ) { - // device name - string device = tokens[4]; - SG_LOG( SG_IO, SG_INFO, " device = " << device ); - - // baud - string baud = tokens[5]; - SG_LOG( SG_IO, SG_INFO, " baud = " << baud ); - - SGSerial *ch = new SGSerial( device, baud ); - io->set_io_channel( ch ); + if ( tokens.size() < 5) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for serial communications."); + delete io; + return NULL; + } + // device name + string device = tokens[4]; + SG_LOG( SG_IO, SG_INFO, " device = " << device ); + + // baud + string baud = tokens[5]; + SG_LOG( SG_IO, SG_INFO, " baud = " << baud ); + + + SGSerial *ch = new SGSerial( device, baud ); + io->set_io_channel( ch ); + + if ( protocol == "AV400WSimB" ) { + if ( tokens.size() < 7 ) { + SG_LOG( SG_IO, SG_ALERT, "Missing second hz for AV400WSimB."); + delete io; + return NULL; + } + FGAV400WSimB *fgavb = static_cast(io); + string hz2_str = tokens[6]; + double hz2 = atof(hz2_str.c_str()); + fgavb->set_hz2(hz2); + } } else if ( medium == "file" ) { - // file name - string file = tokens[4]; - SG_LOG( SG_IO, SG_INFO, " file name = " << file ); - - SGFile *ch = new SGFile( file ); - io->set_io_channel( ch ); + // file name + if ( tokens.size() < 4) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for file I/O."); + delete io; + return NULL; + } + + string file = tokens[4]; + SG_LOG( SG_IO, SG_INFO, " file name = " << file ); + int repeat = 1; + if (tokens.size() >= 7 && tokens[6] == "repeat") { + if (tokens.size() >= 8) { + repeat = atoi(tokens[7].c_str()); + FGGeneric* generic = dynamic_cast(io); + if (generic) + generic->setExitOnError(true); + } else { + repeat = -1; + } + } + SGFile *ch = new SGFile( file, repeat ); + io->set_io_channel( ch ); } else if ( medium == "socket" ) { - string hostname = tokens[4]; - string port = tokens[5]; - string style = tokens[6]; - - SG_LOG( SG_IO, SG_INFO, " hostname = " << hostname ); - SG_LOG( SG_IO, SG_INFO, " port = " << port ); - SG_LOG( SG_IO, SG_INFO, " style = " << style ); - - io->set_io_channel( new SGSocket( hostname, port, style ) ); + if ( tokens.size() < 6) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for socket communications."); + delete io; + return NULL; + } + string hostname = tokens[4]; + string port = tokens[5]; + string style = tokens[6]; + + SG_LOG( SG_IO, SG_INFO, " hostname = " << hostname ); + SG_LOG( SG_IO, SG_INFO, " port = " << port ); + SG_LOG( SG_IO, SG_INFO, " style = " << style ); + + io->set_io_channel( new SGSocket( hostname, port, style ) ); } return io; @@ -217,87 +348,93 @@ FGIO::parse_port_config( const string& config ) void FGIO::init() { - // SG_LOG( SG_IO, SG_INFO, "I/O Channel initialization, " << + // SG_LOG( SG_IO, SG_INFO, "I/O Channel initialization, " << // globals->get_channel_options_list()->size() << " requests." ); - FGProtocol *p; + _realDeltaTime = fgGetNode("/sim/time/delta-realtime-sec"); // we could almost do this in a single step except pushing a valid // port onto the port list copies the structure and destroys the // original, which closes the port and frees up the fd ... doh!!! - // parse the configuration strings and store the results in the - // appropriate FGIOChannel structures - typedef vector container; - container::iterator i = globals->get_channel_options_list()->begin(); - container::iterator end = globals->get_channel_options_list()->end(); - for (; i != end; ++i ) + string_list::iterator i = globals->get_channel_options_list()->begin(); + string_list::iterator end = globals->get_channel_options_list()->end(); + for (; i != end; ++i ) { + add_channel( *i ); + } // of channel options iteration +} + +// add another I/O channel +void FGIO::add_channel(const string& config) +{ + // parse the configuration string and store the results in the + // appropriate FGIOChannel structure + FGProtocol *p = parse_port_config( config ); + if (!p) { - p = parse_port_config( *i ); - if ( p != NULL ) { - p->open(); - io_channels.push_back( p ); - if ( !p->is_enabled() ) { - SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." ); - exit(-1); - } - } else { - SG_LOG( SG_IO, SG_INFO, "I/O Channel parse failed." ); - } + return; + } + + p->open(); + if ( !p->is_enabled() ) { + SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." ); + delete p; + return; } -} + io_channels.push_back( p ); +} -// process any serial port work void -FGIO::update( double delta_time_sec ) +FGIO::reinit() { - // cout << "processing I/O channels" << endl; +} - // SGTimeStamp current_time; - // current_time.stamp(); - // static SGTimeStamp start_time = current_time; - // double elapsed_time = (current_time - start_time) / 1000000.0; - // cout << " Elapsed time = " << elapsed_time << endl; +// process any IO channel work +void +FGIO::update( double /* delta_time_sec */ ) +{ + // use wall-clock, not simulation, delta time, so that network + // protocols update when the simulation is paused + // see http://code.google.com/p/flightgear-bugs/issues/detail?id=125 + double delta_time_sec = _realDeltaTime->getDoubleValue(); - typedef vector< FGProtocol* > container; - container::iterator i = io_channels.begin(); - container::iterator end = io_channels.end(); + ProtocolVec::iterator i = io_channels.begin(); + ProtocolVec::iterator end = io_channels.end(); for (; i != end; ++i ) { - FGProtocol* p = *i; - - if ( p->is_enabled() ) { - p->dec_count_down( delta_time_sec ); - double dt = 1 / p->get_hz(); - while ( p->get_count_down() < 0.33 * dt ) { - p->process(); - p->inc_count_down( dt ); - p->inc_count(); - } - // double ave = elapsed_time / p->get_count(); - // cout << " ave rate = " << ave << endl; - } - } + FGProtocol* p = *i; + if (!p->is_enabled()) { + continue; + } + + p->dec_count_down( delta_time_sec ); + double dt = 1 / p->get_hz(); + if ( p->get_count_down() < 0.33 * dt ) { + p->process(); + p->inc_count(); + while ( p->get_count_down() < 0.33 * dt ) { + p->inc_count_down( dt ); + } + } // of channel processing + } // of io_channels iteration } - void -FGIO::shutdown_all() { - FGProtocol *p; - - // cout << "processing I/O channels" << endl; - - typedef vector< FGProtocol* > container; - container::iterator i = io_channels.begin(); - container::iterator end = io_channels.end(); +FGIO::shutdown() +{ + ProtocolVec::iterator i = io_channels.begin(); + ProtocolVec::iterator end = io_channels.end(); for (; i != end; ++i ) { - p = *i; + FGProtocol *p = *i; + if ( p->is_enabled() ) { + p->close(); + } - if ( p->is_enabled() ) { - p->close(); - } + delete p; } + + io_channels.clear(); } void @@ -309,4 +446,3 @@ void FGIO::unbind() { } -