catalogue(c),
socket(0),
comm(0),
- event_disp(0)
+ event_disp(0),
+ power(false),
+ halt(false)
{ }
Client::~Client()
comm = new Net::Communicator(*socket, proto, *this);
}
+void Client::set_power(bool p)
+{
+ DriverStatePacket pkt;
+ pkt.power = p;
+ pkt.halt = halt;
+ send(pkt);
+}
+
+void Client::set_halt(bool h)
+{
+ DriverStatePacket pkt;
+ pkt.power = power;
+ pkt.halt = h;
+ send(pkt);
+}
+
NetTrain &Client::get_train(unsigned addr) const
{
map<unsigned, NetTrain *>::const_iterator i = trains.find(addr);
return *i->second;
}
+void Client::receive(const DriverStatePacket &pkt)
+{
+ if(pkt.power!=power)
+ {
+ power = pkt.power;
+ signal_power_changed.emit(power);
+ }
+ if(pkt.halt!=halt)
+ {
+ halt = pkt.halt;
+ signal_halt_changed.emit(halt);
+ }
+}
+
+void Client::receive(const EmergencyPacket &pkt)
+{
+ signal_emergency.emit(pkt.message);
+}
+
void Client::receive(const TrainInfoPacket &pkt)
{
NetTrain *train = new NetTrain(*this, pkt);
namespace R2C2 {
-class Client: public Msp::Net::PacketReceiver<TrainInfoPacket>,
+class Client: Msp::Net::PacketReceiver<DriverStatePacket>,
+ Msp::Net::PacketReceiver<EmergencyPacket>,
+ Msp::Net::PacketReceiver<TrainInfoPacket>,
Msp::Net::PacketReceiver<TrainFunctionPacket>,
Msp::Net::PacketReceiver<TrainControlPacket>,
Msp::Net::PacketReceiver<TrainStatusPacket>,
Msp::Net::PacketReceiver<ErrorPacket>
{
public:
+ sigc::signal<void, bool> signal_power_changed;
+ sigc::signal<void, bool> signal_halt_changed;
+ sigc::signal<void, const std::string &> signal_emergency;
sigc::signal<void, NetTrain &> signal_train_added;
sigc::signal<void, const std::string &> signal_error;
Msp::Net::StreamSocket *socket;
Msp::Net::Communicator *comm;
Msp::IO::EventDispatcher *event_disp;
+ bool power;
+ bool halt;
std::list<std::string> routes;
std::map<unsigned, NetTrain *> trains;
const Catalogue &get_catalogue() const { return catalogue; }
const std::list<std::string> &get_routes() const { return routes; }
+ void set_power(bool);
+ void set_halt(bool);
NetTrain &get_train(unsigned) const;
const std::map<unsigned, NetTrain *> &get_trains() const { return trains; }
private:
+ virtual void receive(const DriverStatePacket &);
+ virtual void receive(const EmergencyPacket &);
virtual void receive(const TrainInfoPacket &);
virtual void receive(const TrainControlPacket &);
virtual void receive(const TrainFunctionPacket &);
namespace R2C2 {
+struct DriverStatePacket
+{
+ char power;
+ char halt;
+};
+
+struct EmergencyPacket
+{
+ std::string message;
+};
+
struct TrainInfoPacket
{
unsigned address;
Protocol::Protocol()
{
+ add<DriverStatePacket>() (&DriverStatePacket::power)
+ (&DriverStatePacket::halt);
+ add<EmergencyPacket>() (&EmergencyPacket::message);
add<TrainInfoPacket>() (&TrainInfoPacket::address)
(&TrainInfoPacket::loco_type) (&TrainInfoPacket::name);
add<TrainControlPacket>() (&TrainControlPacket::address)
*/
#include <msp/net/inet.h>
+#include "libr2c2/driver.h"
#include "libr2c2/route.h"
#include "libr2c2/train.h"
#include "libr2c2/vehicletype.h"
listen_sock(Net::INET),
event_disp(0)
{
+ layout.get_driver().signal_power.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
+ layout.get_driver().signal_halt.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
+ layout.signal_emergency.connect(sigc::mem_fun(this, &Server::emergency));
+
layout.signal_train_added.connect(sigc::mem_fun(this, &Server::train_added));
const map<unsigned, Train *> &trains = layout.get_trains();
connections.push_back(new Connection(*this, sock));
}
+void Server::driver_state_changed()
+{
+ DriverStatePacket pkt;
+ pkt.power = layout.get_driver().get_power();
+ pkt.halt = layout.get_driver().is_halted();
+ send(pkt);
+}
+
+void Server::emergency(const string &msg)
+{
+ EmergencyPacket pkt;
+ pkt.message = msg;
+ send(pkt);
+}
+
void Server::train_added(Train &train)
{
train.signal_control_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_control_changed), sigc::ref(train)));
void Server::Connection::handshake_done()
{
- const set<Route *> &routes = server.layout.get_routes();
- for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
{
- RouteInfoPacket pkt;
- pkt.name = (*i)->get_name();
+ DriverStatePacket pkt;
+ pkt.power = server.layout.get_driver().get_power();
+ pkt.halt = server.layout.get_driver().is_halted();
comm.send(pkt);
}
+ const set<Route *> &routes = server.layout.get_routes();
+ for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
+ if(!(*i)->is_temporary())
+ {
+ RouteInfoPacket pkt;
+ pkt.name = (*i)->get_name();
+ comm.send(pkt);
+ }
+
const map<unsigned, Train *> &trains = server.layout.get_trains();
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
stale = true;
}
+void Server::Connection::receive(const DriverStatePacket &pkt)
+{
+ Driver &driver = server.layout.get_driver();
+ if(pkt.power!=driver.get_power())
+ driver.set_power(pkt.power);
+ if(pkt.halt!=driver.is_halted())
+ driver.halt(pkt.halt);
+}
+
void Server::Connection::receive(const TrainControlPacket &pkt)
{
try
class Server
{
private:
- struct Connection: private Msp::Net::PacketReceiver<TrainControlPacket>,
- private Msp::Net::PacketReceiver<TrainFunctionPacket>,
- private Msp::Net::PacketReceiver<TrainRoutePacket>
+ struct Connection: Msp::Net::PacketReceiver<DriverStatePacket>,
+ Msp::Net::PacketReceiver<TrainControlPacket>,
+ Msp::Net::PacketReceiver<TrainFunctionPacket>,
+ Msp::Net::PacketReceiver<TrainRoutePacket>
{
Server &server;
Msp::Net::StreamSocket *socket;
void handshake_done();
void end_of_file();
+ virtual void receive(const DriverStatePacket &);
virtual void receive(const TrainControlPacket &);
virtual void receive(const TrainFunctionPacket &);
virtual void receive(const TrainRoutePacket &);
private:
void incoming_connection();
+ void driver_state_changed();
+ void emergency(const std::string &);
void train_added(Train &);
void train_control_changed(const Train &, const std::string &, float);
void train_function_changed(const Train &, unsigned, bool);
#include <gtkmm/separator.h>
#include <msp/net/resolve.h>
#include <msp/time/units.h>
+#include "mainpanel.h"
#include "remote.h"
#include "trainpanel.h"
window.add(*manage(scroll));
scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
- train_box = new Gtk::VBox(false, 5);
- scroll->add(*manage(train_box));
+ panel_box = new Gtk::VBox(false, 5);
+ scroll->add(*manage(panel_box));
+
+ main_panel = new MainPanel(*this, client);
+ panel_box->pack_start(*manage(main_panel), false, true);
window.show_all();
}
void Remote::train_added(R2C2::NetTrain &t)
{
+ Gtk::HSeparator *sep = new Gtk::HSeparator;
+ panel_box->pack_start(*manage(sep), false, true);
+ sep->show();
+
TrainPanel *panel = new TrainPanel(*this, 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);
+ panel_box->pack_start(*manage(panel), false, true);
train_panels.push_back(panel);
}
#include <msp/core/application.h>
#include "network/client.h"
+class MainPanel;
class TrainPanel;
class Remote: public Msp::Application
R2C2::Client client;
Gtk::Main gtk;
Gtk::Window window;
- Gtk::Box *train_box;
+ Gtk::Box *panel_box;
+ MainPanel *main_panel;
std::vector<TrainPanel *> train_panels;
static Msp::Application::RegApp<Remote> reg;