12 Replies Latest reply on Nov 28, 2011 5:19 PM by John Hawkinson

    Remotely triggering an action in InDesign?

    John Hawkinson Level 5

      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!

        • 1. Re: Remotely triggering an action in InDesign?
          SuperMacGuy Level 2

          I've been using watched folders via Applescript for a long time now. I've had really good success with it, with the caveat that it's never a completely error-free experience. There's the occasional server-unmounting or application crash. But my apps process 1000s of ID files every week, so I think it's pretty high volume and high probably of an error just because of volume we do.

          I've used a couple different methods to watch the folders. Lately I've been going with "do shell script "ls -tr " & quoted form of (POSIX path of (watchedFolder as string))"

          This was a lot more reliable than Finder tells for getting/updating folder contents. Then I can filter for file extension if needed. If you are only adding files to the folder, you'd have to keep a list of file names and compare against that each time the script scans.

          My apps are Applescript-ObjectiveC based now. So I am using the cocoa event timer to run the process every 30 seconds [set myTimer to NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(10, me, "doAutoLoop:", missing value, true)]. The apps have a UI with a start/stop button. They also use some straight ObjectiveC for server/volume re-mounting if the volume isn't found. I like this kind of approach, with a UI, so if the user can control the work that happens. If a user needs to run the automated app, they run it. Or if they can't be interrupted, then they stop it. I'd be worried about how this entire process runs if a user is doing something completely different (or in the modal dialog as you mention).

          I've never considered trying to run the notification process on the server, mainly since I'm not in IT nor would consider windows programming. But, there is the possibility that you could use InDesign server to handle your process more reliably. ??

          • 2. Re: Remotely triggering an action in InDesign?
            John Hawkinson Level 5

            SuperMacGuy: Thanks for the thoughts. I'd really rather the discussion not head towards how to monitor the files outside of InDesign -- I have a solution for that that works pretty well (kqueue), but we can talk about it another thread if you like. I'm very happy with my solution.

             

            For me, the question is triggering InDesign. Do you do that from your script? It sounds like you really doing batch processing, which is not my application here. To the extent that you have anything analagous, I guess your entire batch workflow is written in AppleScript so your easy answer is the equivalent of II(a), though you don't need to run "osascript."

             

            If a user needs to run the automated app, they run it. Or if they can't be interrupted, then they stop it. I'd be worried about how this entire process runs if a user is doing something completely different (or in the modal dialog as you mention). [...]

            But, there is the possibility that you could use InDesign server to handle your process more reliably.

            In short, no. The use case here involves the production editor actively working on a document in InDesign while the photo editor is preparing final photos to replace the FPO placeholders. The script in InDesign is short and sweet, and it's also not the end of the world if it doesn't happen automatically or gets deferred. It's really quite analagous to updating links.

             

            InDesign server would not work because the layouts are actively open and being worked on in ID Desktop. It is also too expensive -- paying around $15k  for this little bit of added functionality doesn't make financial sense.

             

            I've never considered trying to run the notification process on the server, mainly since I'm not in IT nor would consider windows programming.

            Err, this is probably a better question for your other thread, but how did we get to Windows programming? I guess you must be running a Windows fileserver? I guess my solutions wouldn't work for you then.

            • 3. Re: Remotely triggering an action in InDesign?
              John Hawkinson Level 5

              Nobody? Harbs?

               

              I guess I'll start with II(a), helper daemon on each client (probably in perl) that sends an AppleScript message to ID, and we'll see how it goes. Seems easiest to implement...

              • 4. Re: Remotely triggering an action in InDesign?
                Harbs. Level 6

                A pretty good alternative to any of the above is to write a CS Extension to poll the file server using Actionscript.

                 

                You'll need to create the extension launch automatically on app launch off the screen.

                 

                To make it more robust, you can create a second extension that checks that the first is running and relaunches it if it fails. (The two extensions can both check on each other...)

                • 5. Re: Remotely triggering an action in InDesign?
                  John Hawkinson Level 5

                  I'm sure you know that I do need to bone up on my CSXS/ActionScript, so perhaps this is a good chance, but why is this a good alternative? What does AS3 bring to the picture? Does it have richer socket APIs?

                  I guess there is the XMLSocket API...it looks like it has events that fire when data is received...

                   

                  I'm not sure that this is much better than a perl script that does the same thing and triggers InDesign. I guess...platform-independent?

                   

                  What are the things that cause CSXS extensions to need relaunching?

                   

                  Somehow I think of CSXS as being useful when you want to have a panel that looks like an ID panel. But I guess there's a lot more than that...

                  • 6. Re: Remotely triggering an action in InDesign?
                    Harbs. Level 6

                    Yes, there are Socket APIs if you need them. There are also very good HTTP/HTTPS APIs. The APIs make working with HTTP/Network communication very easy, and it all works asynchronously via events.

                     

                    Advantages of ActionScript:

                    1) Nice APIs which make it all very easy to work with and helps organize the code.

                    2) True async communication (which does not run in the main InDesign thread AFAIK) where you can then call the InDesign DOM directly as necessary. (Calls to the InDesign DOM are not ansync.)

                    3) You can run it in a timer loop which is non-blocking as far as InDesign processing is concerned.

                     

                    The only thing that should cause a CSXS extension to need relaunching would be if it crashes or stops responding for some reason -- doesn't usually happen, but it could if there's bugs in the code somewhere...

                     

                    John Hawkinson wrote:

                     

                    Somehow I think of CSXS as being useful when you want to have a panel that looks like an ID panel. But I guess there's a lot more than that...

                    Yup.

                     

                    I wrote a blog post which mentions some of the advantages here:

                    http://in-tools.com/article/thoughts-on-extending-the-creative-suite/

                     

                    Harbs

                    • 7. Re: Remotely triggering an action in InDesign?
                      John Hawkinson Level 5

                      There's something about guys named Gabe...

                      • 8. Re: Remotely triggering an action in InDesign?
                        Harbs. Level 6

                         

                         

                        What? Do we talk too much? Too much "Gab"?

                         

                        Harbs

                        • 9. Re: Remotely triggering an action in InDesign?
                          John Hawkinson Level 5

                          Eeeeeeeeeeeeee!

                           

                          No, you (plural) just seem to like ActionScript.

                          I'm not so keen on adding a compilation step to this particular piece of automation, but maybe it's doomed to get that anyhow.

                          • 10. Re: Remotely triggering an action in InDesign?
                            Harbs. Level 6

                            Actually, the point of my blog post was that Actionscript is not the answer to all problems, but it definitely has a place...

                             

                            Harbs

                            • 11. Re: Remotely triggering an action in InDesign?
                              Muppet Mark Level 5

                              Given the info that you have supplied… I would probably start with the simplest route… somewhere between II & II(a) Why not make an AppleScript 'Stay Open' script… This could have the capabilities to check is ID running, is the server mounted, check for new file existence ( you can use 'do shellscript' if you prefer for these parts ) then comunicate with ID to do your JavaScript… You can set how regular you want these to run and hide the app's from being visible processes in the dock if you so wish… II(b) & III would require that Bridge be a permanent process ( thats my thinking and I would be concerned about users quiting the app )

                              • 12. Re: Remotely triggering an action in InDesign?
                                John Hawkinson Level 5

                                Muppet Mark (congrats on your new movie):

                                Why not make an AppleScript 'Stay Open' script… This could have the capabilities to check is ID running, is the server mounted, check for new file existence

                                Well, because AppleScript is not a good environment for socket programming. It sounds like you're suggesting polling via AppleScript, but one of my goals on this is to not poll. I want asynchronous notification of the change without polling.

                                 

                                With that in mind, then, I would need to write a helper program that would be run from the AppleScript, which gets me no benefits from using AppleScript, so...