X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Ffg_io.cxx;h=36ca64433d3f6dc923acdfcdaa59374ea88856d7;hb=f467ba360902e4395d23b35481c55844a3946b91;hp=4a75a78fb0ba65413981c8a4d0d08cad734f2fcc;hpb=182fd42b4017fa54d680508c092ea1b216398a00;p=flightgear.git diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index 4a75a78fb..36ca64433 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,178 +16,283 @@ // // 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 STL_STRING +#include // atoi() + +#include #include #include #include #include #include +#include #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 #include "globals.hxx" +#include "fg_io.hxx" + +using std::atoi; +using std::string; -SG_USING_STD(string); +FGIO::FGIO() +{ +} -// define the global I/O channel list -io_container global_io_list; +#include +using std::for_each; +static void delete_ptr( FGProtocol* p ) { delete p; } -// configure a port based on the config string -static FGProtocol *parse_port_config( const string& config ) +FGIO::~FGIO() { - string::size_type begin, end; + shutdown_all(); + for_each( io_channels.begin(), io_channels.end(), delete_ptr ); +} - begin = 0; +// configure a port based on the config string +FGProtocol* +FGIO::parse_port_config( const string& config ) +{ SG_LOG( SG_IO, SG_INFO, "Parse I/O channel request: " << config ); - // determine protocol - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy + vector tokens = simgear::strutils::split( config, "," ); + if (tokens.empty()) + { + SG_LOG( SG_IO, SG_ALERT, + "Port configuration error: empty config string" ); + return 0; } - - string protocol = config.substr(begin, end - begin); - begin = end + 1; + + string protocol = tokens[0]; SG_LOG( SG_IO, SG_INFO, " protocol = " << protocol ); - FGProtocol *io; - if ( protocol == "atlas" ) { - FGAtlas *atlas = new FGAtlas; - io = atlas; - } else if ( protocol == "garmin" ) { - FGGarmin *garmin = new FGGarmin; - io = garmin; - } else if ( protocol == "joyclient" ) { - FGJoyClient *joyclient = new FGJoyClient; - io = joyclient; - } else if ( protocol == "native" ) { - FGNative *native = new FGNative; - io = native; - } else if ( protocol == "nmea" ) { - FGNMEA *nmea = new FGNMEA; - io = nmea; - } else if ( protocol == "props" ) { - FGProps *props = new FGProps; - io = props; - } 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; + FGProtocol *io = 0; + + try + { + 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" ) { + // char wait; + // printf("Parsed opengc\n"); cin >> wait; + 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 == "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()) ); +#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" ) { + size_t configToken; + if (tokens[1] == "socket") { + configToken = 7; + } else if (tokens[1] == "file") { + configToken = 5; + } else { + configToken = 6; + } + + if (configToken >= tokens.size()) { + SG_LOG( SG_IO, SG_ALERT, "Not enough tokens passed for the generic protocol."); + return NULL; + } + + FGGeneric *generic = new FGGeneric( tokens ); + 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]; + string rate = tokens[2]; + string host = tokens[3]; + string port = tokens[4]; + return new FGMultiplay(dir, atoi(rate.c_str()), host, atoi(port.c_str())); + } else { + return NULL; + } } - - // determine medium - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy + catch (FGProtocolConfigError& err) + { + SG_LOG( SG_IO, SG_ALERT, "Port configuration error: " << err.what() ); + delete io; + return 0; } - string medium = config.substr(begin, end - begin); - begin = end + 1; + if (tokens.size() < 3) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of network arguments."); + return NULL; + } + string medium = tokens[1]; SG_LOG( SG_IO, SG_INFO, " medium = " << medium ); - // determine direction - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy - } - - string direction = config.substr(begin, end - begin); - begin = end + 1; + string direction = tokens[2]; io->set_direction( direction ); SG_LOG( SG_IO, SG_INFO, " direction = " << direction ); - // determine hertz - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy - } - - string hertz_str = config.substr(begin, end - begin); - begin = end + 1; + string hertz_str = tokens[3]; double hertz = atof( hertz_str.c_str() ); io->set_hz( hertz ); SG_LOG( SG_IO, SG_INFO, " hertz = " << hertz ); if ( medium == "serial" ) { + if ( tokens.size() < 5) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for serial communications."); + return NULL; + } // device name - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string device = config.substr(begin, end - begin); - begin = end + 1; + string device = tokens[4]; SG_LOG( SG_IO, SG_INFO, " device = " << device ); // baud - string baud = config.substr(begin); + string baud = tokens[5]; SG_LOG( SG_IO, SG_INFO, " baud = " << baud ); + SGSerial *ch = new SGSerial( device, baud ); io->set_io_channel( ch ); } else if ( medium == "file" ) { // file name - string file = config.substr(begin); + if ( tokens.size() < 4) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for file I/O."); + return NULL; + } + + string file = tokens[4]; SG_LOG( SG_IO, SG_INFO, " file name = " << file ); - - SGFile *ch = new SGFile( 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" ) { - // hostname - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string hostname = config.substr(begin, end - begin); - begin = end + 1; + if ( tokens.size() < 6) { + SG_LOG( SG_IO, SG_ALERT, "Incompatible number of arguments for socket communications."); + 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 ); - // port string - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string port = config.substr(begin, end - begin); - begin = end + 1; - SG_LOG( SG_IO, SG_INFO, " port string = " << port ); - - // socket style - string style_str = config.substr(begin); - SG_LOG( SG_IO, SG_INFO, " style string = " << style_str ); - - SGSocket *ch = new SGSocket( hostname, port, style_str ); - io->set_io_channel( ch ); + io->set_io_channel( new SGSocket( hostname, port, style ) ); } return io; @@ -196,12 +301,13 @@ static FGProtocol *parse_port_config( const string& config ) // step through the port config streams (from fgOPTIONS) and setup // serial port channels for each -void fgIOInit() { - // SG_LOG( SG_IO, SG_INFO, "I/O Channel initialization, " << +void +FGIO::init() +{ + // SG_LOG( SG_IO, SG_INFO, "I/O Channel initialization, " << // globals->get_channel_options_list()->size() << " requests." ); FGProtocol *p; - string_list *channel_options_list = globals->get_channel_options_list(); // we could almost do this in a single step except pushing a valid // port onto the port list copies the structure and destroys the @@ -209,11 +315,15 @@ void fgIOInit() { // parse the configuration strings and store the results in the // appropriate FGIOChannel structures - for ( int i = 0; i < (int)channel_options_list->size(); ++i ) { - p = parse_port_config( (*channel_options_list)[i] ); + 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 ) + { + p = parse_port_config( *i ); if ( p != NULL ) { p->open(); - global_io_list.push_back( p ); + io_channels.push_back( p ); if ( !p->is_enabled() ) { SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." ); exit(-1); @@ -224,55 +334,68 @@ void fgIOInit() { } } +void +FGIO::reinit() +{ +} -// process any serial port work -void fgIOProcess() { - FGProtocol *p; +// process any IO channel work +void +FGIO::update( double delta_time_sec ) +{ // cout << "processing I/O channels" << endl; + // cout << " Elapsed time = " << delta_time_sec << endl; - static int inited = 0; - int interval; - static SGTimeStamp last; - SGTimeStamp current; - - if ( ! inited ) { - inited = 1; - last.stamp(); - interval = 0; - } else { - current.stamp(); - interval = current - last; - last = current; - } - - for ( int i = 0; i < (int)global_io_list.size(); ++i ) { - // cout << " channel = " << i << endl; - p = global_io_list[i]; + typedef vector< FGProtocol* > container; + container::iterator i = io_channels.begin(); + container::iterator end = io_channels.end(); + for (; i != end; ++i ) { + FGProtocol* p = *i; if ( p->is_enabled() ) { - p->dec_count_down( interval ); - while ( p->get_count_down() < 0 ) { - p->process(); - p->dec_count_down( -1000000.0 / p->get_hz() ); + 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 ); + } + // double ave = elapsed_time / p->get_count(); + // cout << " ave rate = " << ave << endl; } } } } -// shutdown all I/O connections -void fgIOShutdownAll() { +void +FGIO::shutdown_all() { FGProtocol *p; - // cout << "processing I/O channels" << endl; + // cout << "shutting down all I/O channels" << endl; - for ( int i = 0; i < (int)global_io_list.size(); ++i ) { - // cout << " channel = " << i << endl; - p = global_io_list[i]; + typedef vector< FGProtocol* > container; + container::iterator i = io_channels.begin(); + container::iterator end = io_channels.end(); + for (; i != end; ++i ) + { + p = *i; if ( p->is_enabled() ) { p->close(); } } } + +void +FGIO::bind() +{ +} + +void +FGIO::unbind() +{ +} +