Subscribe to "Save" and get name of the file that was saved

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

themagiczebra
Posts: 1
Joined: Mon Sep 19, 2016 6:27 pm

Subscribe to "Save" and get name of the file that was saved

Post by themagiczebra »

Hi there,

I'm new to PS-Scripts and Photoshop scripting in general, so please excuse my noobiness.

I'm working on a NodeJS desktop application that interacts with Photoshop. Users of this app have the ability to click on a button and open a file directly into Photoshop. Once the user has finished editing their photo and saved the changes, my application does some additional processing on the updated file. This processing should only happen if the file was saved in PS, however.

I'm currently using the PhotoshopClient (lib/photoshop.js) class from https://github.com/adobe-photoshop/generator-core to manage the connections, command execution, and event subscription. Through various code samples and documentation, I've learned that you can subscribe to an event via the following command:

Code: Select all

function subscribeToEvent(client, event) {
var s = "var idNS = stringIDToTypeID('networkEventSubscribe');";
s += "var desc1 = new ActionDescriptor();";
s += "desc1.putClass(stringIDToTypeID('eventIDAttr'), stringIDToTypeID('" + event + "'));";
s += "executeAction(idNS, desc1, DialogModes.NO);";
client.sendCommand(s);
}
My app currently listens to the "save" event in order to detect when a document was saved. Here is a sample of that code:

Code: Select all


var client = new PhotoshopClient({
hostname: '127.0.0.1',
password: 'passwd'
});

client.on('connect', () => { subscribeToEvent(client, 'save'); });

client.on('event', (messageId, eventName, parsedValue) => {
// handle event
});

client.on('message', (messageId, parsedValue, rawMessage) => {
// handle message
});
When a save occurs, the callback to "message" fires. Both the "parsedValue" and "rawMessage" evaluate to the string "save". Unfortunately, I do not appear to be getting back any other information about which document was saved. As a workaround, once a save notification comes in I immediately ask PS for the active document via:

Code: Select all

if (parsedValue === 'save') {
client.sendCommand('"SAVED:" + activeDocument.name');
} else {
let parts = parsedValue.split('SAVED:');
if (parts.length === 2) {
let fileName = parts[1];
// do something with the file
}
}
Although this works, it's a bit unreliable. Should the active document be closed immediately after the save occurs, then my second command to retrieve the active document's name will fail.

After some more digging, I found that there is an event named "imageChanged" that provides me with some basic metadata about the file that changed. I modified my code to subscribe to that event instead. This time, when I receive a message it doesn't come through the "message" handler but rather the "event" handler and includes all the information I'm after.

The one drawback to this approach is that the "imageChanged" event fires way more frequently than the "save" event, and even when the document hasn't been saved yet. For example, I've seen the following actions trigger the "imageChanged" event:

* Opening a file
* Changing the active document by cycling between tabs
* Performing a crop/rotate without actually saving the changes
* Saving the doc

I'm sure there are other cases where "imageChanged" would fire, but the problem this poses for me is that I can't rely on that event due to not being able to tell exactly what type of "change" it was. The additional JSON data that comes packaged with this event looks pretty much the same regardless of the action taken.

I'd really like to continue using the "save" event instead because it only fires at the exact time I need it to, but I can't unless I can figure out how to get it to display more information. I attempted wrapping my brain around ActionDescriptor and ActionReference, but the docs I'm reading don't clearly explain what these things are and how to use them. I'm pretty lost at the moment and would really appreciate some help.

Thanks a bunch!