From 2fe7cbcb761487bc7409b93b372da6f8ab3c581e Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 13 Dec 2009 18:14:52 +0000 Subject: [PATCH] Export routes over network Implement the reverse field in TrainSpeedPacket Derive the TrainPanel in remote from Expander for a more compact train list Set default size for the remote controller window Catch exceptions caused by packets sent by a client --- source/engineer/trainpanel.cpp | 6 ++ source/engineer/trainpanel.h | 1 + source/libmarklin/layout.cpp | 8 +++ source/libmarklin/layout.h | 1 + source/libmarklin/trafficmanager.h | 1 + source/network/client.cpp | 10 +++ source/network/client.h | 8 ++- source/network/packets.h | 16 +++++ source/network/protocol.cpp | 4 ++ source/network/server.cpp | 105 ++++++++++++++++++++++++----- source/network/server.h | 7 +- source/network/train.cpp | 17 +++++ source/network/train.h | 5 ++ source/remote/remote.cpp | 15 ++++- source/remote/remote.h | 3 + source/remote/trainpanel.cpp | 61 ++++++++++++++++- source/remote/trainpanel.h | 23 ++++++- 17 files changed, 265 insertions(+), 26 deletions(-) diff --git a/source/engineer/trainpanel.cpp b/source/engineer/trainpanel.cpp index d462b51..250b283 100644 --- a/source/engineer/trainpanel.cpp +++ b/source/engineer/trainpanel.cpp @@ -50,6 +50,7 @@ TrainPanel::TrainPanel(Engineer &e, const GLtk::Resources &r, Train &t): tgl_forward->set_geometry(GLtk::Geometry(geom.w-30, geom.h-59, 20, 27)); tgl_forward->set_value(!train.get_locomotive().get_reverse()); tgl_forward->signal_toggled.connect(sigc::mem_fun(this, &TrainPanel::forward_toggled)); + train.get_locomotive().signal_reverse_changed.connect(sigc::mem_fun(this, &TrainPanel::train_reverse_changed)); add(*(lbl_route=new GLtk::Label(res, "Free run"))); lbl_route->set_style("digital"); @@ -107,6 +108,11 @@ void TrainPanel::train_speed_changed(unsigned speed) sld_speed->set_value(speed); } +void TrainPanel::train_reverse_changed(bool reverse) +{ + tgl_forward->set_value(!reverse); +} + void TrainPanel::loco_function_changed(unsigned func, bool value) { map::iterator i = tgl_funcs.find(func); diff --git a/source/engineer/trainpanel.h b/source/engineer/trainpanel.h index aae71f9..a76d907 100644 --- a/source/engineer/trainpanel.h +++ b/source/engineer/trainpanel.h @@ -36,6 +36,7 @@ public: private: void speed_slider_changed(double); void train_speed_changed(unsigned); + void train_reverse_changed(bool); void loco_function_changed(unsigned, bool); void train_route_changed(const Marklin::Route *); void train_status_changed(const std::string &); diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp index 121e19e..67d646b 100644 --- a/source/libmarklin/layout.cpp +++ b/source/libmarklin/layout.cpp @@ -45,6 +45,14 @@ void Layout::add_route(Route &r) signal_route_added.emit(r); } +Route &Layout::get_route(const string &name) const +{ + for(set::const_iterator i=routes.begin(); i!=routes.end(); ++i) + if((*i)->get_name()==name) + return **i; + throw KeyError("Unknown route", name); +} + void Layout::remove_route(Route &r) { if(routes.erase(&r)) diff --git a/source/libmarklin/layout.h b/source/libmarklin/layout.h index 2a1817f..8573a54 100644 --- a/source/libmarklin/layout.h +++ b/source/libmarklin/layout.h @@ -53,6 +53,7 @@ public: void remove_track(Track &); void add_route(Route &); const std::set &get_routes() const { return routes; } + Route &get_route(const std::string &) const; void remove_route(Route &); void save(const std::string &); private: diff --git a/source/libmarklin/trafficmanager.h b/source/libmarklin/trafficmanager.h index b01860a..d4ea2b3 100644 --- a/source/libmarklin/trafficmanager.h +++ b/source/libmarklin/trafficmanager.h @@ -43,6 +43,7 @@ public: ~TrafficManager(); Control &get_control() const { return control; } + Layout &get_layout() const { return layout; } const std::list &get_blocks() const { return blocks; } Block &get_block_by_track(const Track &) const; const std::list &get_trains() const { return trains; } diff --git a/source/network/client.cpp b/source/network/client.cpp index 4eb4b25..8e31cfe 100644 --- a/source/network/client.cpp +++ b/source/network/client.cpp @@ -73,4 +73,14 @@ void Client::receive(const TrainStatusPacket &pkt) get_train(pkt.address).process_packet(pkt); } +void Client::receive(const RouteInfoPacket &pkt) +{ + routes.push_back(pkt.name); +} + +void Client::receive(const TrainRoutePacket &pkt) +{ + get_train(pkt.address).process_packet(pkt); +} + } // namespace Marklin diff --git a/source/network/client.h b/source/network/client.h index ce8dcb6..3a9cbc0 100644 --- a/source/network/client.h +++ b/source/network/client.h @@ -20,7 +20,9 @@ namespace Marklin { class Client: public Msp::Net::PacketReceiver, Msp::Net::PacketReceiver, Msp::Net::PacketReceiver, - Msp::Net::PacketReceiver + Msp::Net::PacketReceiver, + Msp::Net::PacketReceiver, + Msp::Net::PacketReceiver { public: sigc::signal signal_train_added; @@ -31,6 +33,7 @@ private: Msp::Net::StreamSocket *socket; Msp::Net::Communicator *comm; Msp::IO::EventDispatcher *event_disp; + std::list routes; std::map trains; public: @@ -45,6 +48,7 @@ public: { if(comm) comm->send(pkt); } const Catalogue &get_catalogue() const { return catalogue; } + const std::list &get_routes() const { return routes; } NetTrain &get_train(unsigned); private: @@ -52,6 +56,8 @@ private: virtual void receive(const TrainSpeedPacket &); virtual void receive(const TrainFunctionPacket &); virtual void receive(const TrainStatusPacket &); + virtual void receive(const RouteInfoPacket &); + virtual void receive(const TrainRoutePacket &); }; } // namespace Marklin diff --git a/source/network/packets.h b/source/network/packets.h index d6efafc..31fd56d 100644 --- a/source/network/packets.h +++ b/source/network/packets.h @@ -38,6 +38,22 @@ struct TrainStatusPacket std::string status; }; +struct RouteInfoPacket +{ + std::string name; +}; + +struct TrainRoutePacket +{ + unsigned address; + std::string route; +}; + +struct ErrorPacket +{ + std::string message; +}; + } // namespace Marklin #endif diff --git a/source/network/protocol.cpp b/source/network/protocol.cpp index 5801d37..f8e13be 100644 --- a/source/network/protocol.cpp +++ b/source/network/protocol.cpp @@ -20,6 +20,10 @@ Protocol::Protocol() (&TrainFunctionPacket::functions); add() (&TrainStatusPacket::address) (&TrainStatusPacket::status); + add() (&RouteInfoPacket::name); + add() (&TrainRoutePacket::address) + (&TrainRoutePacket::route); + add() (&ErrorPacket::message); } } // namespace Marklin diff --git a/source/network/server.cpp b/source/network/server.cpp index 17142f8..cd52b48 100644 --- a/source/network/server.cpp +++ b/source/network/server.cpp @@ -7,8 +7,10 @@ Distributed under the GPL #include #include "libmarklin/control.h" +#include "libmarklin/layout.h" #include "libmarklin/locomotive.h" #include "libmarklin/locotype.h" +#include "libmarklin/route.h" #include "server.h" using namespace std; @@ -23,12 +25,7 @@ Server::Server(TrafficManager &tm): { const list &trains = trfc_mgr.get_trains(); for(list::const_iterator i=trains.begin(); i!=trains.end(); ++i) - { - Locomotive &loco = (*i)->get_locomotive(); - (*i)->signal_target_speed_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_speed_changed), sigc::ref(**i))); - loco.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(**i))); - (*i)->signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(**i))); - } + train_added(**i); listen_sock.listen(Net::InetAddr(0, 8315), 4); listen_sock.signal_data_available.connect(sigc::mem_fun(this, &Server::incoming_connection)); @@ -52,7 +49,9 @@ void Server::train_added(Train &train) { Locomotive &loco = train.get_locomotive(); train.signal_target_speed_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_speed_changed), sigc::ref(train))); + loco.signal_reverse_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_reverse_changed), sigc::ref(train))); loco.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train))); + train.signal_route_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_route_changed), sigc::ref(train))); train.signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train))); TrainInfoPacket pkt; @@ -71,6 +70,15 @@ void Server::train_speed_changed(const Train &train, unsigned speed) send(pkt); } +void Server::train_reverse_changed(const Train &train, bool reverse) +{ + TrainSpeedPacket pkt; + pkt.address = train.get_locomotive().get_address(); + pkt.speed = train.get_target_speed(); + pkt.reverse = reverse; + send(pkt); +} + void Server::train_function_changed(const Train &train, unsigned, bool) { TrainFunctionPacket pkt; @@ -79,6 +87,15 @@ void Server::train_function_changed(const Train &train, unsigned, bool) send(pkt); } +void Server::train_route_changed(const Train &train, const Route *route) +{ + TrainRoutePacket pkt; + pkt.address = train.get_locomotive().get_address(); + if(route) + pkt.route = route->get_name(); + send(pkt); +} + void Server::train_status_changed(const Train &train, const string &status) { TrainStatusPacket pkt; @@ -113,6 +130,14 @@ Server::Connection::~Connection() void Server::Connection::handshake_done() { + const set &routes = server.trfc_mgr.get_layout().get_routes(); + for(set::const_iterator i=routes.begin(); i!=routes.end(); ++i) + { + RouteInfoPacket pkt; + pkt.name = (*i)->get_name(); + comm.send(pkt); + } + const list &trains = server.trfc_mgr.get_trains(); for(list::const_iterator i=trains.begin(); i!=trains.end(); ++i) { @@ -144,6 +169,13 @@ void Server::Connection::handshake_done() pkt.status = (*i)->get_status(); comm.send(pkt); } + if((*i)->get_route()) + { + TrainRoutePacket pkt; + pkt.address = loco.get_address(); + pkt.route = (*i)->get_route()->get_name(); + comm.send(pkt); + } } } @@ -155,20 +187,61 @@ void Server::Connection::end_of_file() void Server::Connection::receive(const TrainSpeedPacket &pkt) { - Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address); - Train &train = server.trfc_mgr.get_train_by_locomotive(loco); - if(pkt.reverse!=loco.get_reverse()) - train.set_reverse(pkt.reverse); - else - train.set_speed(pkt.speed); + try + { + Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address); + Train &train = server.trfc_mgr.get_train_by_locomotive(loco); + if(pkt.reverse!=loco.get_reverse()) + train.set_reverse(pkt.reverse); + else + train.set_speed(pkt.speed); + } + catch(const Exception &e) + { + error(e.what()); + } } void Server::Connection::receive(const TrainFunctionPacket &pkt) { - Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address); - for(unsigned i=0; i<9; ++i) - if(((pkt.functions^loco.get_functions())>>i)&1) - loco.set_function(i, (pkt.functions>>i)&1); + try + { + Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address); + for(unsigned i=0; i<9; ++i) + if(((pkt.functions^loco.get_functions())>>i)&1) + loco.set_function(i, (pkt.functions>>i)&1); + } + catch(const Exception &e) + { + error(e.what()); + } +} + +void Server::Connection::receive(const TrainRoutePacket &pkt) +{ + try + { + Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address); + Train &train = server.trfc_mgr.get_train_by_locomotive(loco); + if(pkt.route.empty()) + train.set_route(0); + else + { + Route &route = server.trfc_mgr.get_layout().get_route(pkt.route); + train.set_route(&route); + } + } + catch(const Exception &e) + { + error(e.what()); + } +} + +void Server::Connection::error(const string &msg) +{ + ErrorPacket pkt; + pkt.message = msg; + comm.send(pkt); } } // namespace Marklin diff --git a/source/network/server.h b/source/network/server.h index 6ce965e..7c3dce9 100644 --- a/source/network/server.h +++ b/source/network/server.h @@ -22,7 +22,8 @@ class Server { private: struct Connection: private Msp::Net::PacketReceiver, - private Msp::Net::PacketReceiver + private Msp::Net::PacketReceiver, + private Msp::Net::PacketReceiver { Server &server; Msp::Net::StreamSocket *socket; @@ -36,6 +37,8 @@ private: void end_of_file(); virtual void receive(const TrainSpeedPacket &); virtual void receive(const TrainFunctionPacket &); + virtual void receive(const TrainRoutePacket &); + void error(const std::string &); }; Protocol proto; @@ -52,7 +55,9 @@ private: void train_added(Train &); void train_speed_changed(const Train &, unsigned); + void train_reverse_changed(const Train &, bool); void train_function_changed(const Train &, unsigned, bool); + void train_route_changed(const Train &, const Route *); void train_status_changed(const Train &, const std::string &); template diff --git a/source/network/train.cpp b/source/network/train.cpp index 468b220..025dcf5 100644 --- a/source/network/train.cpp +++ b/source/network/train.cpp @@ -58,6 +58,17 @@ void NetTrain::set_function(unsigned i, bool set) client.send(pkt); } +void NetTrain::set_route(const string &r) +{ + if(r==route) + return; + + TrainRoutePacket pkt; + pkt.address = address; + pkt.route = r; + client.send(pkt); +} + void NetTrain::process_packet(const TrainSpeedPacket &pkt) { if(pkt.speed!=speed) @@ -87,4 +98,10 @@ void NetTrain::process_packet(const TrainStatusPacket &pkt) signal_status_changed.emit(status); } +void NetTrain::process_packet(const TrainRoutePacket &pkt) +{ + route = pkt.route; + signal_route_changed.emit(route); +} + } // namespace Marklin diff --git a/source/network/train.h b/source/network/train.h index 57154a0..0a6a8a8 100644 --- a/source/network/train.h +++ b/source/network/train.h @@ -23,6 +23,7 @@ public: sigc::signal signal_speed_changed; sigc::signal signal_reverse_changed; sigc::signal signal_function_changed; + sigc::signal signal_route_changed; sigc::signal signal_status_changed; private: @@ -33,6 +34,7 @@ private: unsigned speed; bool reverse; unsigned functions; + std::string route; std::string status; public: @@ -47,9 +49,12 @@ public: bool get_reverse() const { return reverse; } void set_function(unsigned, bool); bool get_function(unsigned i) const { return (functions>>i)&1; } + void set_route(const std::string &); + const std::string &get_route() const { return route; } void process_packet(const TrainSpeedPacket &); void process_packet(const TrainFunctionPacket &); + void process_packet(const TrainRoutePacket &); void process_packet(const TrainStatusPacket &); }; diff --git a/source/remote/remote.cpp b/source/remote/remote.cpp index 57080c1..c6afc6d 100644 --- a/source/remote/remote.cpp +++ b/source/remote/remote.cpp @@ -5,6 +5,7 @@ Copyright © 2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ +#include #include #include #include "remote.h" @@ -34,9 +35,12 @@ Remote::Remote(int argc, char **argv): delete addr; window.signal_hide().connect(sigc::bind(sigc::mem_fun(this, &Remote::exit), 0)); + window.set_default_size(300, 200); window.set_border_width(5); + train_box = new Gtk::VBox(false, 5); window.add(*manage(train_box)); + window.show_all(); } @@ -48,6 +52,13 @@ void Remote::tick() void Remote::train_added(Marklin::NetTrain &t) { - TrainPanel *panel = new TrainPanel(t); - train_box->add(*manage(panel)); + TrainPanel *panel = new TrainPanel(client, t); + if(!train_panels.empty()) + { + Gtk::HSeparator *sep = new Gtk::HSeparator; + train_box->pack_start(*manage(sep), false, true); + sep->show(); + } + train_box->pack_start(*manage(panel), false, true); + train_panels.push_back(panel); } diff --git a/source/remote/remote.h b/source/remote/remote.h index 4599a13..a4bfc42 100644 --- a/source/remote/remote.h +++ b/source/remote/remote.h @@ -14,6 +14,8 @@ Distributed under the GPL #include #include "network/client.h" +class TrainPanel; + class Remote: public Msp::Application { private: @@ -23,6 +25,7 @@ private: Gtk::Main gtk; Gtk::Window window; Gtk::Box *train_box; + std::vector train_panels; static Msp::Application::RegApp reg; diff --git a/source/remote/trainpanel.cpp b/source/remote/trainpanel.cpp index e3db1ba..ce46fa1 100644 --- a/source/remote/trainpanel.cpp +++ b/source/remote/trainpanel.cpp @@ -6,17 +6,21 @@ Distributed under the GPL */ #include +#include #include "libmarklin/locotype.h" #include "trainpanel.h" using namespace std; -TrainPanel::TrainPanel(Marklin::NetTrain &t): +TrainPanel::TrainPanel(Marklin::Client &c, Marklin::NetTrain &t): + client(c), train(t) { train.signal_name_changed.connect(sigc::mem_fun(this, &TrainPanel::name_changed)); train.signal_speed_changed.connect(sigc::mem_fun(this, &TrainPanel::speed_changed)); + train.signal_reverse_changed.connect(sigc::mem_fun(this, &TrainPanel::reverse_changed)); train.signal_function_changed.connect(sigc::mem_fun(this, &TrainPanel::function_changed)); + train.signal_route_changed.connect(sigc::mem_fun(this, &TrainPanel::route_changed)); train.signal_status_changed.connect(sigc::mem_fun(this, &TrainPanel::status_changed)); set_label(train.get_name()); @@ -25,13 +29,19 @@ TrainPanel::TrainPanel(Marklin::NetTrain &t): add(*manage(vbox)); vbox->set_border_width(5); - vbox->add(*manage(scl_speed = new Gtk::HScale)); + Gtk::HBox *hbox = new Gtk::HBox(false, 5); + vbox->add(*manage(hbox)); + + hbox->add(*manage(scl_speed = new Gtk::HScale)); scl_speed->set_digits(0); scl_speed->set_range(0, 14); scl_speed->set_increments(1, 1); - scl_speed->set_size_request(280, -1); + scl_speed->set_size_request(210, -1); scl_speed->signal_value_changed().connect(sigc::mem_fun(this, &TrainPanel::ui_speed_changed)); + hbox->add(*manage(chk_reverse = new Gtk::CheckButton("Rev"))); + chk_reverse->signal_toggled().connect(sigc::mem_fun(this, &TrainPanel::ui_reverse_changed)); + Gtk::HBox *func_box = new Gtk::HBox(false, 5); vbox->add(*manage(func_box)); const std::map &funcs = train.get_loco_type().get_functions(); @@ -43,6 +53,18 @@ TrainPanel::TrainPanel(Marklin::NetTrain &t): chk->signal_toggled().connect(sigc::bind(sigc::mem_fun(this, &TrainPanel::ui_function_changed), i->first)); } + Glib::RefPtr route_store = Gtk::ListStore::create(route_columns); + vbox->add(*manage(cmb_route = new Gtk::ComboBox(route_store))); + cmb_route->pack_start(route_columns.name); + route_store->append(); + const list &routes = client.get_routes(); + for(list::const_iterator i=routes.begin(); i!=routes.end(); ++i) + { + Gtk::TreeIter iter = route_store->append(); + (*iter)[route_columns.name] = *i; + } + cmb_route->signal_changed().connect(sigc::mem_fun(this, &TrainPanel::ui_route_changed)); + vbox->add(*manage(lbl_status = new Gtk::Label)); show_all(); @@ -63,6 +85,11 @@ void TrainPanel::speed_changed(unsigned speed) scl_speed->set_value(speed); } +void TrainPanel::reverse_changed(bool rev) +{ + chk_reverse->set_active(rev); +} + void TrainPanel::function_changed(unsigned func, bool set) { std::map::iterator i = chk_funcs.find(func); @@ -70,14 +97,42 @@ void TrainPanel::function_changed(unsigned func, bool set) i->second->set_active(set); } +void TrainPanel::route_changed(const string &route) +{ + Gtk::TreeNodeChildren children = cmb_route->get_model()->children(); + for(Gtk::TreeIter i=children.begin(); i!=children.end(); ++i) + if((*i)[route_columns.name]==route) + { + cmb_route->set_active(i); + break; + } +} + void TrainPanel::ui_speed_changed() { train.set_speed(static_cast(scl_speed->get_value())); } +void TrainPanel::ui_reverse_changed() +{ + train.set_reverse(chk_reverse->get_active()); +} + void TrainPanel::ui_function_changed(unsigned func) { std::map::iterator i = chk_funcs.find(func); if(i!=chk_funcs.end()) train.set_function(func, i->second->get_active()); } + +void TrainPanel::ui_route_changed() +{ + Gtk::TreeIter iter = cmb_route->get_active(); + train.set_route(Glib::ustring((*iter)[route_columns.name])); +} + + +TrainPanel::RouteRecord::RouteRecord() +{ + add(name); +} diff --git a/source/remote/trainpanel.h b/source/remote/trainpanel.h index 2dcd095..b969af4 100644 --- a/source/remote/trainpanel.h +++ b/source/remote/trainpanel.h @@ -9,28 +9,45 @@ Distributed under the GPL #define TRAINPANEL_H_ #include -#include +#include +#include #include #include +#include "network/client.h" #include "network/train.h" -class TrainPanel: public Gtk::Frame +class TrainPanel: public Gtk::Expander { private: + struct RouteRecord: public Gtk::TreeModelColumnRecord + { + Gtk::TreeModelColumn name; + + RouteRecord(); + }; + + Marklin::Client &client; Marklin::NetTrain &train; Gtk::Scale *scl_speed; Gtk::Label *lbl_status; + Gtk::CheckButton *chk_reverse; + RouteRecord route_columns; + Gtk::ComboBox *cmb_route; std::map chk_funcs; public: - TrainPanel(Marklin::NetTrain &); + TrainPanel(Marklin::Client &, Marklin::NetTrain &); private: void name_changed(const std::string &); void status_changed(const std::string &); void speed_changed(unsigned); + void reverse_changed(bool); void function_changed(unsigned, bool); + void route_changed(const std::string &); void ui_speed_changed(); + void ui_reverse_changed(); void ui_function_changed(unsigned); + void ui_route_changed(); }; #endif -- 2.45.2