make sure that the ::process method gets called
[fg:hoorays-flightgear.git] / src / Scripting / NasalFGProtocol.cxx
1 // Expose FGProtocol module to Nasal to enable I/O protocols to be implemented in Nasal space, e.g.
2 // to support REST/AJAX, JSON or HTTP WebSockets: https://code.google.com/p/flightgear-bugs/issues/detail?id=396 
3 //
4 // Copyright (C) 2013  The FlightGear community
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "NasalFGProtocol.hxx"
25 #include <Main/globals.hxx>
26 #include <Main/util.hxx>
27 #include <Main/fg_io.hxx>
28
29 // supported SGIOChannels
30 #include <simgear/io/iochannel.hxx>
31 #include <simgear/io/sg_file.hxx>
32 #include <simgear/io/sg_serial.hxx>
33 #include <simgear/io/sg_socket.hxx>
34 #include <simgear/io/sg_socket_udp.hxx>
35
36 #include <simgear/nasal/cppbind/from_nasal.hxx>
37 #include <simgear/nasal/cppbind/to_nasal.hxx>
38 #include <simgear/nasal/cppbind/NasalHash.hxx>
39 #include <simgear/nasal/cppbind/Ghost.hxx>
40
41
42 typedef boost::shared_ptr<simgear::NetChat> NasalNetChat_ptr;
43 typedef nasal::Ghost< NasalNetChat_ptr > NasalNetChat;
44
45 typedef boost::shared_ptr<simgear::NetChannel> NasalNetChannel_ptr;
46 typedef nasal::Ghost< NasalNetChannel_ptr > NasalNetChannel;
47
48
49
50 class NasalProtocolWrapper;
51
52 typedef boost::shared_ptr<NasalProtocolWrapper> NasalProtocolWrapper_ptr;
53 typedef nasal::Ghost< NasalProtocolWrapper_ptr > NasalProtocol;
54
55 class NasalProtocolWrapper : public FGProtocol {
56 public:
57  NasalProtocolWrapper(const nasal::CallContext& ctx);
58  void register_handler();
59  bool open();
60  bool process();
61  bool close();
62  bool gen_message();
63  bool parse_message();
64  void set_direction();
65  
66 protected:
67 private:
68 };
69
70 //FIXME: move this out of the constructor, this was just for demonstration purposes
71 NasalProtocolWrapper::NasalProtocolWrapper(const nasal::CallContext& ctx) {
72    //TODO: see parse_port_config() in Main/fg_io.cxx
73   std::string medium = ctx.requireArg<std::string>(0);  
74   std::string direction = ctx.requireArg<std::string>(1);  
75   std::string rate_hz = ctx.requireArg<std::string>(2);  
76
77  FGProtocol::set_direction( direction ); 
78  FGProtocol::set_hz( atof(rate_hz.c_str()) );
79
80  if(medium=="socket") {
81         // look for other arguments:
82         std::string host = ctx.requireArg<std::string>(3);
83         std::string port = ctx.requireArg<std::string>(4); 
84         std::string style = ctx.requireArg<std::string>(5); 
85
86         // http://docs.freeflightsim.org/simgear/classSGSocket.html
87         set_io_channel( new SGSocket( host, port, style ) );
88  }
89  else 
90   SG_LOG(SG_IO, SG_ALERT, "NasalProtocolWrapper: Unsupported medium: "<< medium << std::endl);
91 }
92
93
94
95 void 
96 NasalProtocolWrapper::register_handler() {
97   static_cast<FGIO*> (globals->get_subsystem( "io" )) ->add_channel( this );
98 }
99
100 bool
101 NasalProtocolWrapper::open() {
102 SG_LOG(SG_GENERAL, SG_ALERT, "::open" << std::endl);
103 FGProtocol::open();
104 return true;
105 }
106
107 bool
108 NasalProtocolWrapper::process() {
109 SG_LOG(SG_GENERAL, SG_ALERT, "::process" << std::endl);
110 return true;
111 }
112
113 bool
114 NasalProtocolWrapper::close() {
115 SG_LOG(SG_GENERAL, SG_ALERT, "::close" << std::endl);
116 FGProtocol::close();
117 return true;
118 }
119
120 bool
121 NasalProtocolWrapper::gen_message() {
122 SG_LOG(SG_GENERAL, SG_ALERT, "::gen_message" << std::endl);
123 return true;
124 }
125
126 bool
127 NasalProtocolWrapper::parse_message() {
128 SG_LOG(SG_GENERAL, SG_ALERT, "::parse_message" << std::endl);
129 return true;
130 }
131
132 void
133 NasalProtocolWrapper::set_direction() {
134 SG_LOG(SG_GENERAL, SG_ALERT, "::set_direction" << std::endl);
135
136 }
137
138
139
140 naRef to_nasal_helper(naContext c, NasalProtocolWrapper *obj)
141   { 
142     NasalProtocolWrapper_ptr ptr(obj); 
143     return NasalProtocol::create(c, ptr ); 
144   }
145  
146
147 NasalProtocolWrapper*
148 from_nasal_helper(naContext c, naRef ref, const NasalProtocolWrapper*)
149   { 
150       return (NasalProtocolWrapper*) naGhost_ptr(ref);
151   }
152
153 naRef to_nasal_helper(naContext c, simgear::NetChat *obj)
154   { 
155     NasalNetChat_ptr ptr(obj); 
156     return NasalNetChat::create(c, ptr ); 
157   }
158  
159
160 simgear::NetChat*
161 from_nasal_helper(naContext c, naRef ref, const simgear::NetChat*)
162   { 
163       return (simgear::NetChat*) naGhost_ptr(ref);
164   }
165
166 naRef to_nasal_helper(naContext c, simgear::NetChannel *obj)
167   { 
168     NasalNetChannel_ptr ptr(obj); 
169     return NasalNetChannel::create(c, ptr ); 
170   }
171  
172
173 simgear::NetChannel*
174 from_nasal_helper(naContext c, naRef ref, const simgear::NetChannel*)
175   { 
176       return (simgear::NetChannel*) naGhost_ptr(ref);
177   }
178
179
180 static naRef f_new_protocol(const nasal::CallContext& ctx)
181 {
182  NasalProtocolWrapper* proto = NULL;
183  try {
184    proto = new NasalProtocolWrapper(ctx);
185   }
186   catch(...) {
187    return naNil();
188   }
189
190   return ctx.to_nasal( proto );
191 }
192
193 //------------------------------------------------------------------------------
194 naRef initNasalFGProtocol(naRef globals, naContext c)
195 {
196 // This is where you want to expose all required methods from FGProtocol/NetChat/NetChannel
197
198   // http://docs.freeflightsim.org/simgear/classsimgear_1_1NetChat.html 
199   NasalNetChat::init("io.netchat")
200         .method("setTerminator", &simgear::NetChat::setTerminator)
201         .method("getTerminator", &simgear::NetChat::getTerminator);
202
203   // http://docs.freeflightsim.org/simgear/classsimgear_1_1NetChannel.html
204   NasalNetChannel::init("io.netchannel")
205         .method("close", &simgear::NetChannel::close);
206
207   NasalProtocol::init("io.protocol")
208         .method("register", &NasalProtocolWrapper::register_handler) 
209         .method("open", &NasalProtocolWrapper::open) 
210         .method("close", &NasalProtocolWrapper::close) 
211         .method("gen_message", &NasalProtocolWrapper::gen_message) 
212         .method("parse_message", &NasalProtocolWrapper::parse_message) 
213         .method("set_direction", &NasalProtocolWrapper::set_direction);
214
215   nasal::Hash globals_module(globals, c);
216   nasal::Hash protocol = globals_module.createHash("protocol");
217   protocol.set("new", &f_new_protocol); 
218
219   return naNil();
220 }