James wrote:Stuart wrote:This is very cool, and gives me extra incentive to get further on the
G1000 project.
Are you intending to support sending events back natively so that button presses
etc. can be handled, or will that need to use some other mechanism (emessary)?
I will add native event support - that’s why I prompted Richard to add native touch event support as an animation type, and we can make the canvas handle that locally. The idea is the client side is very thin, there’s no Nasal or anything in it, it’s just a renderer and event source, similar to VNC but obviously way more efficient because only property changes are sent.
BTW this should also work for the Canvas-map, but I didn’t test that all yet - images are one of the least developed parts for now so I’m not sure how the tile management would cope but in *principle* it should all just work.
Now that Richard has started hooking up his Emesary IPC framework to the MFD framework, I would like to reiterate my suggestion to consider/discuss wrapping all MFD bindings (those triggering events/notifications) using fgcommands instead of pure Nasal blobs - the point being that sooner or later you may want to actually run multiple instances of the FG1000 - e.g. by showing several instruments in a single dialog or by opening separate dialogs with independent instances.
This kind of thing can become pretty messy once you use Nasal blobs all over the place (been there, seen it) - fgcommands are much cleaner than that, and they have the added advantage that other front-ends can just as easily access/use the FG1000 MFD without having to know anything about Nasal or Emesary - i.e. you are basically encapsulating event handling (Emesary notifications) using fgcommand (do note that if this were generally done, that adopting an IPC mechanism like Emesary would also be much simpler than reviewing/editing tons of Nasal blobs in the <bindings> section of a cockpit/UI dialog).
I am currently having the same discussion with Richard, trying to make the point why using Nasal in the bindings part of the MFD is problematic in the long term - for pretty much the same reasons that James encouraged Richard not to use Emesary for his new Touch Animation.
The point being that external front-ends like Phi, FGQCanvas, tablet PCs, mobile phones, dedicated cockpit hardware etc can trivially access properties and run fgcommands, but that they cannot as easily deal with bindings in the form of Nasal blobs - we can however deal with that problem easily by going through the fgcommand API and registering our MFD/Emesary Callbacks as dedicated MFD specific fgcommands:
Hooray wrote:an fgcommand can be just that: a conventional Nasal callback (including a method) - it's a just a property-tree enabled version of an API/IPC mechanism so that other back-ends don't need to know anything about Nasal.
I do think that James pointed out the power of this approach when you were discussing the "touch animation".
Under the hood, it's really just C++ code that gets a handle to a property tree node and returns true/false - what the Nasal addCommand() is doing is provide a mechanism to allow arbitrary Nasal code to be registered in the form of an fgcommand.
What that means is that fgcommands can invoke bindings that don't need to support nasal - this is extremely powerful when dealing with stuff that runs outside the fgfs process space - imagine Phi/mongoose, or James' FGQCanvas work, but also any other out-of-process application that may benefit from invoking Nasal code in an RPC/IPC fashion without actually supporting it.
I haven't discussed this with anyone else, only touched on it briefly on the forum and in a few wiki articles - but if in doubt, I'd suggest to check back with some of other core developers/long-term contributors to see if they can see the merits of pursuing this or not.
The takeaway really is that Emesary callbacks can be provided in the form of fgcommands - which means that your Nasal code can remain "as is" - but that all stuff using Emesary can transparently invoke Nasal code, without having to know anything about it - which kinda is the whole point of a framework like Emesary, right ?
Regarding the question you raised (passing a Nasal hash as a property) - that is what props.nas has helpers for: setValues() and .getValues() will transparently do just that.
As you can probably tell by now, I am not suggesting anything novel or complicated - but merely a shim layer to provide fgcommand-based bindings for Emesary, so that other use-cases (outside fgfs) may not need to actually know anything about Nasal or Emesary, which I think is the point of the exercise, isn't it ?
If in doubt, just take a brief look at these:
http://wiki.flightgear.org/Nasal_librar ... mand.28.29
http://wiki.flightgear.org/Howto:Add_ne ... FlightGear
This isn't to say that the Emesary framwork itself will need to be exposed that way, but merely some of its event/action handling routines - because that is typically what other front-ends and back-ends are likely to be interested in: triggering events and actions.
So, I am really having the bigger picture in mind here - i.e. a distributed fgfs setup with a handful of instances, and what they'd need in terms of infrastructure and building blocks to properly sync/replicate Canvas related MFD state (think Stuart's G1000) across multiple instances using a single IPC-enabled MFD framework.
So this is not about asking you to implement something, but rather to encourage having the discussion to see if/how we can have our cake and eat it - I don't care if you end up using fgcommands or not - it's just something that I tend to do, and recommend, for the lack of better tools; but also in the light of other folks being slightly concerned about important features being solely implemented in scripting space (think Advanced Weather), and that would surely also apply to stuff like Emesary, because people (read: core devs) who don't like Nasal, surely won't go crazy about adopting a Nasal based IPC framework for pretty much the same reasons that they don't like Nasal in the first place.
To sum up things: With the goals stated above, I do think that adding Emesary support to the MFD framework would be a good idea, but I also think that establishing a way to prototype/test MFDs using a standalone GUI dialog with skins/themes does make sense - and I would rather not see people using low-level Nasal blobs all over the place to trigger events and actions in response to someone clicking a button or cockpit hotspot, but would rather see them use a single "command layer" that has nothing to do with Nasal - which is what fgcommands are good at (despite the back-end code still residing in Nasal space possibly). The point being that FGQCanvas, dedicated hardware/tablet PCs or mobile phones can then render a working G1000 MFD without any of the front-ends having to know low-level details about niche technologies like Emesary or Nasal.
Equally, using the approach where an enumerated list of events/actions and callbacks can be traversed with some meta data to provide labels/tooltips for each action (think cockpit dial) would make it straightforward to let Phi render a G1000-style MFD, without Torsten having to tinker with Nasal/Emesary at all - that is, as long as everything goes through APIs that all other external software simply understands - namely, properties & fgcommands.
Again, please don't spend even just a single minute implementing any of this if you don't think it's a good idea - but please do consider discussing such goals with people involved in the various efforts (e.g. Stuart/FG1000 and James/FGQCanvas, Torsten/Phi).
What we have been doing in the Canvas department in the last 5+ years is hugely problematic and adding to the pile of work we have, and even more problematic due to Nasal's general status/reputation, but also the fact that this stufff (Nasal+Canvas) runs in the main loop.
A good, and properly-designed, MFD framework can be protoyped in scripting space and could be moved to native code sooner or later to address these challenges in a feasible way - but for that to succeed, we literally need to look at the use-cases we currently have and make sure that people can eat their cake and have it, which means providing an IPC mechanism that allows people disliking Nasal still using it, without them having to know anything about the underlying implementation details.
Hooray wrote:the rationale for my suggestion to encapsulate Nasal use for hooking up Emesary notifications via fgcommands are out-of-process front-ends that need to interact with the in-sim Canvas MFD:
Torsten's Phi/mongoose front-end:
http://wiki.flightgear.org/Phi
Stuart's FG1000 effort:
http://wiki.flightgear.org/FG1000
James' FGQCanvas:
ThomasS Canvas httpd streaming support:
http://wiki.flightgear.org/Read_canvas_image_by_HTTP
I think, you'll agree that Emesary could be THE IPC solution to solve the problem, but that adding/requiring Nasal support would be a little far-fetched - nevertheless, the people/end-users using these mechanisms would definitely want to be able to interact with the MFD.
And these are just a few examples - there are others to be found, e.g. where people are interfacing their cell phones/tablet to FlightGear for pretty much the same reasons, or where they'd like to interface actual cockpit hardware to FlightGear that needs to interact with the Canvas MFD.
Using an IPC mechanism like Emesary here is definitely the right solution, but requiring Nasal in the command/bindings part is probably considered controversial and not desirable from the standpoint of those opposed to Nasal.
Using the fgcommand route would also mean that other back-ends, e.g. those using Python, could still trivially interact with the same Canvas MFD bindings, without having to know anything about Nasal at all.
Again, this is not to convince you - but just to encourage you to solicit feedback and make up your own mind. For instance, just imagine for a second what it would take to render Stuart's FG1000 in Phi - all we'd need is the streaming patch we have already, and we could trivially render a Canvas remotely - the difficult part is elsewhere, i.e. making it respond to events coming from another process that are usually implemented in the form of Nasal blobs executed in the <bindings> part of the dialog/cockpit panel.
Once you begin using only fgcommands here (wrapping Emesary itself), the front-end no longer matters at all ...
(hope I am making sense, even if you should disagree on technical grounds ...)