Well at least it seems to work – with a few minor source patches.
I’m not inclined to go through the rigmarole of forking the github source and making a pull request, and for some reason I can’t add an ‘Issue’ to that page. (The ‘HaiukuArchives/ArtPaint’ page happily accepts issues, but the SampleCode page doesn’t ?!)
I applied you patch, Pete, and pushed it into the BeSampleCode branch “haiku”. Thanks!
I also added an issue tracker for the sample code. I don’t know why there wasn’t one before, but I doubt it was on purpose.
Thanks! Not sure how useful the app actually is. It’s a pretty raw representation of the scripting interface, and I’m not sure how complex a message one could build. I played a while without getting much insight. ‘Hey’ is much more flexible for general use.
I have to admit that the Scripting scheme always has me floundering. It always takes many attempts to get hey to achieve approximately what I want. I think I use hey in exactly one place --actually on my BeOS machine. I have a (shell) script to start BeShare when I turn the machine on, and a hey command minimizes the resulting window. (I see your blog on the topic, and another article – apparently by Ithamar – so maybe I can get some insight there!)
It’d be interesting to know how many people are actually using scripting, and what for. Responses in this thread…?
I’m using it heavily in AGMSScriptOCron (a kind of souped up cron program) and the commercial application based on it, FetchIt. All operations are done through scripting messages, talking to the application thread which processes them. With FetchIt, the GUI talks to the underlying engine using scripting messages, so theoretically it could be in a totally separate program (but it’s slightly faster to send messages within the same program, and it is still a separate BWindow thread).
Here’s an example of the hey commands to set up an AGMSScriptOCron command to run every 15 minutes, adapting a pre-made model of the command:
hey application/scriptocron create command with "name=My Alert" and model=alert
hey application/scriptocron set value of field "Message Text" of command "My Alert" to "Time to put on the tea kettle."
hey application/scriptocron set trigger of command "My Alert" to "* * * * 0,15,30,45"
hey application/scriptocron set LogFileEnable of command "My Alert" to true
hey application/scriptocron do edit of command "my alert"
Now every quarter hour it will pop up an alert with your message. Well, maybe not, if you leave the alert on screen it will consider the command to be still running and not start it again. It’s usable, but it’s a pain to type in that much text, thus the GUI program which does all that much more easily - there’s a text box to enter Field values (your message text) and a Save button, and a Run button, and a log window, etc.
When writing AGMSScriptOCron I usually started by thinking up a scripting command to do something I needed, then wrote the docs for it (actually the PropInfo structure description field), then implemented it, tested it with hey, then used it in the GUI program.
Interesting! Definitely an extensive use! I wonder why Scripting messages are preferable there to plain old BMessages? When you have control of the apps at both ends I’d have thought that making your own message structure would be simpler than going through the scripting layer.
I’ve always rather thought that Be Scripting was one of those neat solutions in search of a problem… If an app has a GUI, one usually uses it interactively and has no need of scripting. If something is automated it usually doesn’t have an App structure with windows so doesn’t really suit the Scripting protocol.
My use of hey for BeShare startup is one of those rare exceptions, as BeShare is both interactive and a ‘server’ to publish files for others. So having hey hide the window immediately is a natural fit.
OTOH I’ve found the BMessage API convenient in a number of places. In fact I’m using the Muscle variant to coordinate my own ‘reminder’ system between machines. The actual simple ‘cron’ like program runs on my Pi 24/7, and clients on my BeOS, Haiku, and Linux systems connect to it through muscle (all in Python). (This is not a package that I’m ever likely to publish! It is especially hacked on the Pi itself, because it signals through the GPIO pins, so the startup is currently complex and manual.)
The scripting is not supposed to be used directly with the GUI elements. That is only the poor man solution for lazy app programmers who did not add proper scripting to their applications.
Here is an interesting use case for proper scripting. I ported the ACE emulator from MorphOS to Haiku. This is an emulator for Amstrad CPC computers (old 8 bit stuff). You can use the emulator with its GUI to play games or whatever. But what’s more interesting about it is the ability to debug the running emulated device using scripting endpoints. You can change the memory, CPU registers, etc; you can simulate keystrokes; you can set or clear breakpoints; and you can also load data in memory from your assembler (including the symbol table so the built-in debugger will show the symbols). Unfortunately, due to its MorphOS origin, it uses REXX scripting (using BeBREXX on Haiku), and not the native scripting system. I will at some point find a way to make these inter-operate somehow.
This is one case where scripting really works well: you have a running application, you need some way to remote control it to trigger events (it doesn’t even need to be a GUI application). I can imagine doing similar things for home automation, for example: a server exposing scripting endpoints to control the lights and heating in your house, and then other apps can easily send commands to it (from a GUI, from an HTTP server, …). And more importantly, there is a defined protocol to discover what’s available (how many lightbulbs? what are their names and where are they located? can they be dimmed or just turned on and off?). This discovery aspect is the most useful part of the scripting interface, and what it brings over the low-level “just send a BMessage” interface.
The scripting system does use BMessages. The difference is that there is some header stuff which specifies which object the message should be sent to. And the command codes are limited to a few standard operations (set, get, count, delete, etc) plus a name and value (the value can be a BMessage too). And there is a way of asking a program for a list of supported commands.
All of that makes it easier to ask a program to do things in a standard way (hey command and equivalents), without having to know much about the program.
I think this was sort of my point… How many apps have ever included custom scripting features? (Excepting the examples from you and Alex.) I think it’s often hard to see in advance where scripting might be useful.
Ahh, yes. I’ll give you that. This could be a very desirable feature.
Humdinger’s example is essentially what I do, though I did it in a slightly more complex way, because I wanted the option to not start BeShare (if I’m just booting for a quick maintenance or something). If you’re interested, here’s my full insertion in UserBootScript:
if [ ! -e /tmp/NOBESHARE ]; then
hey BeShare set Minimize of Window 0 to TRUE
The initial “sleep 30” is so that I have time to click on a trivial xicon script that creates ‘tmp/NOBESHARE’ (which of course otherwise does not exist at boot). The “sleep 1” is not as neat as Humdinger’s “wait” but is for the same purpose. The whole sequence is enclosed in parentheses with a trailing “&”, so that the rest of the script doesn’t have to wait those 31 seconds.
We should drive by example, by including useful scripting entry points in more applications. There are pending patches allowing remote control of MediaPlayer, for example (next/previous track, that kind of thing). And we should keep thinking about more.
mmu_man also made a talk about how the ability to access GUI elements could be used to develop a screen reader for Haiku and allow blind people to use it.
How did you know about this 4 byte command code? That’s the advantage of application scripting right there: if it was done as a full scripting operation then “hey Tracker getsuites” would let you know it exists. No need to read the source code https://git.haiku-os.org/haiku/tree/src/kits/tracker/Commands.h or rely on word of mouth.
By the way, Tracker does have a few scripting operations (emptying trash, making a folder and showing it in a window, showing preferences), but could have a lot more, many more. Might make a good summer student task.
That does remind me that it would be great to have programs create scripts as you use the program. I remember TurboText on the Amiga, which could spit out a list of ARexx application scripting commands that replicated what you did (cursor movements, text searches, editing, etc). You could manually edit it then use it to do fancy operations via ARexx code, or I think you could bind it to a function key too.
We might be able to do it with a bit of standard wedge code that saved scripting BMessages as they came in to an application. The output would be either a binary file (BMessages in archive format) or Hey text equivalents (though Hey has bugs with complex arguments or long strings that have the word “file” somewhere in them). You’d probably want to filter out unimportant operations too, like the GUI periodically asking if anything has changed.