Thanks for the heads-up and thanks for your PM - I do absolutely agree, this looks fantastic.
Regarding your code/design questions, I think you have already extended the class beyond what I was envisioning originally.
And it seems you even completed the visualization routine already, which is something that didn't even start yet.
From a code management point, I was hoping to come up with a decoupled design using 3 distinct classes - one for handling the GCA itself, and to helper classes whose constructor would take a handle to the GCA class to retrieve any instance specific state from it directly, e.g. for visualizing the running GCA, but also for setting up the whole thing using the UI that I created.
I haven't yet looked at any of your code, so I don't know if you were already tinkering with integrating the UI, too ?
That is actually something that started doing 1-2 weeks ago, when I began moving everything to an addon/submodule structure - but in the meantime you have made so much progress, that it would be kinda moot to share that code now.
Finally, regarding the threading related questions: I am entirely with Thorsten on that one, the runtime footprint caused by this script should be marginal even under the worst of conditions - thus, there's hardly any point in porting it to some other language/framework or moving it to a separate thread at this point. As a matter of fact, people who don't buy that, can easily benchmark the script using debug.benchmark() - moving the computations to a Nasal worker thread would be easy enough, but would buy us nothing. Thus, I would suggest not to over-engineer things by prematurely optimizing this feature so early.
Even if we should be able to identify a few bottlenecks in the time to come, it should only take a few experienced Nasal coders to optimize the script and make it work well enough for most people - it's not like this is some kind of heavy eye-candy feature after all.
Like Thorsten said already, I wouldn't underestimate the overhead cause by porting/rewriting the script using a different framework and by sync'ing the relevant state using whatever IPC you have in mind.
My guess is that the Canvas based visualization dialog is much heavier in terms of added footprint than the script itself, and it's not like people are suggesting to move Canvas/Nasal to a different thread (yet).
That being said, and totally unrelated to spokenATC and the GCA module, if/when threading should ever become an option, it would make more sense to thread-out individual Nasal scripts, or even associate individual interpreter instances to a single Canvas instance (texture), so that each texture could have its own associated scripting interpreter updating it, using a private property tree.
I once tinkered with such a scheme when I was working on disabling Nasal entirely and making it initialize incrementally afterwards - the point being that such a Nasal interpreter would only have/require a subset of the usual FG/Nasal APIs, so that it would be much more lightweight - which also means you cannot just getprop() or setprop() arbitrary properties, but really need a sane form of IPC - for starters that could be Torsten's mongoose/Phi work.
http://wiki.flightgear.org/Howto:Disable_Nasal_entirelyhttp://wiki.flightgear.org/Initializing_Nasal_earlyIn other words, there is no clean way to run Nasal/Canvas based code in a worker thread unless you are willing to provide each Canvas texture with its own scripting interpreter that runs outside the main loop. And that's a potentially interesting scheme, because such textures -while still GC bound- could be updated at much higher rates. i.e. higher than 60 hz, which would also be of interest to certain aggrressive threading optimizations that OSG can make
For that to work, each Canvas would have to use its own private property tree instance (SGPropertyNode) and only replicate relevant state/events in the global property tree at framerate, whereas things would be internally updated much faster