All,
As promised, I worked on the generator API a bit last night. Now obdsim is capable of having multiple generators linked in at the same time. Instructions on writing plugins are provided in src/sim/generators/README.generator [repeated below]. The short version is "copy generators/random/ to generators/{whatever}/, and edit to taste".
Code:
How to write a generator for obdsim
Note: By convention, I will refer to the name of your generator-to-be
as {generator}, or {GENERATOR} if you should uppercase it.
1) Start by looking at datasource.h
It contains a struct, "obdsim_generator", containing functions you
must implement.
2) The easiest generator to understand is in /generators/random/
Copy /generators/random/ to generators/{generator}/
2a) Look at the C files
It #includes "datasource.h", then creates the functions required
by datasource.h.
By convention, all the functions are named {generator}_simgen_{function}.
At the end of the file, we create the obdsim_generator struct.
2b) Look at the CMakeInclude.cmake files
Edit this and replace all instances of RANDOM with {GENERATOR},
and random with {generator}
If you need extra libraries for your generator, add them similarly at
the end of GENERATOR_LIBS
3) Open sim/obdsim.c
Your plugin should be added in two places, both near the top of the file:
first, an extern to declare it without #including anything.
second, added to the list of available_generators.
Note that each instance is wrapped with #ifdef OBDSIMGEN_{GENERATOR}
Project-wide conventions: If your generator will add external dependencies,
it should default to Off.
Gary "Chunky Ks" Briggs
<chunky@icculus.org>
Step 3 is obviously the slightly cheesy C workaround. If anyone has a better way of doing it, I'm open to suggestion. The rest of it is pretty easy, a big case of monkey-see-monkey-do. I'm likely to make the CMakeInclude files easier to edit by some simple substitutions, but that won't change anything important.
The output of --help now appears thus:
Code:
Usage: ../bin/obdsim [params]
[-s|--seed=<generator-specific-string>]
[-g|--generator=<name of generator>]
[-o|--launch-logger]
[-v|--version] [-h|--help]
The generators built into this sim:
"Random"
"Logger" (default)
It's also not too late to get in requests for changes to the API. The current version is here:
http://svn.icculus.org/obdgpslogger/....h?view=markup. As I see it, there's two things that might be worth changing:
1) The build system, specifically a better way of working around step 3 in the instructions. In C++, I would use a linked list and some macros so that generators get added during static initialisation. I don't know of a pattern like that that works in C, though.
2) The API itself. It's not too late to get in requests for API changes. I'm currently considering two more functions:
a) one to get a human-friendly description of the seed for end-user help [eg, the one for logger would be "Filename of obdgpslogger logfile"].
b) An idle-type callback. Currently the sim blocks on reading lines from the pty. This was easier to code [a lot!] than a nonblocking version. The problem is that when you want to write a GUI data generator.
There are two ways to write a GUI data generator for this;
1) Spawn a thread in the generator_create function and run the UI from that [generally running UIs out of your non-main thread is a Bad Idea(TM), although it will work fine for some of them, or in most cases...].
2) Add an idle callback in obdsim. Use nonblocking reads from the pty, and whenever obdsim has nothing better to do, it calls that idle callback. This is great for GUIs, since you can just shove a call to
wxYield(),
FL::check(),
QApplication:
rocessEvents(), etc.
Feedback is welcome. In fact, more than welcome, I really need help and advice of developers here :-)
It also occurs to me that an idle callback would be more useful in the case of, say, a dbus plugin which can continue consuming signals while it has nothing better to do.
Gary (-;