Remotely triggering an action in InDesign?
I see a lot of ways to solve this problem and I can't seem to decide which solution is least bad. Advice please.
I have an environment where InDesign deals with linked images on a remote AFP fileserver, and I would like a script to trigger and run in InDesign when a photo is added to a directory on that fileserver. The model in which I am thinking about this in is the afterAttributeChanged event, which gets fired on a Link if the link status changes to LinkStatus.LINK_OUT_OF_DATE. Of course this model doens't work if the photo is not linked. (In this case, the newly added photo will be replacing an existing FPO photo, but it cannot overwrite the FPO photo, it needs to have a different name. So using the afterAttributeChanged event is not feasible).
My environment is all Macs running CS5. Preferred scripting language is JavaScript.
For OS technical reasons, detection of the files newly added to the fileserver really has to run as a process on the fileserver to be reliable. (Detection is implemented as a kqueue in perl, but that's not really important). So the simplest implementation would be a simple TCP server on the fileserver that accepts a connection from each InDesign client with the Socket API, and then a thread or listener that woke up whenever there was data on the socket to read. (Let's say a new file is added once/hour and I would like InDesign to notice the file within five seconds.)
Unfortunately, InDesign's socket API does not support this, and there's no support for select()/poll() on an existing connection to learn when there is data to read, nor is there support for non-blocking IO. So that's right out.
Approach I: It looks like the Socket API does support non-blocking checks for incoming connections with Socket.poll(), which is really more like a combination of select(2) or poll(2) and accept(2) and not really just plain poll(2). So I could have the InDesign script create a socket to listen on for notifications of file updates, then connect to the server on a secondary connection, tell the server its port number, and then call Socket.poll() on the socket from an idle handler. This means I am polling the TCP socket the idle event handler, which seems bad but not that bad. It's abusing the Socket API because it doesn't support a reasonable approach. And there's no support for INADDR_ANY, so I need to guess at a free TCP port to listen on, but I guess I can iterate so it's not a big deal.
Approach II: Instead of doing all of that, I could write a small helper program to run on each machine that connects to the server and waits for data. When it receives that data, then it could send a message to InDesign telling it the filename. This seems like it would work, but would be kind of cumbersome (more programs, an extra process, etc.). Also, then, how should the process signal InDesign?
Approach II(a): Signal InDesign with AppleScript. My process could just run osascript -e 'tell app "Adobe InDesign CS5" to do script "newPhoto.jsx"'. That seems like it could work, but also there might be annoying problems if message happens to come in while the user is in a modal dialog box.
Approach II(b): Use Bridgetalk. I'm not sure how I would do this -- I don't see a library that I would link my helper program against, so I suppose I would have to have InDesign direct something like Adobe Bridge to talk to my helper program and hope that Bridge's scripting has a richer set of primitives for asynchronous IO.
Approach III: Use Adobe Bridge's HttpConnection.async=true object, and use asynchronous IO in Bridge to implement my helper process, and then have it send messages to InDesign via BridgeTalk.
I don't really like any of these solutions. I feel like Approach II(a) might be better since it doesn't abuse InDesign's idle loop (how fragile is that?), but maye Approach I is cleaner and more maintainable? I have no deal idea on II(b) or III, but it feels like adding a dependency on Adobe Bridge is may be unwise.
Has anyone implemented this sort of thing? Signalling InDesign to perform a task from another process on the same machine, or via a remote machine, with any success? What does your implementation experience tell you?
Thanks!