JS / CS2 loading files selected in Bridge

General Discussion of Scripting for Adobe Bridge

Moderators: Tom, Kukurykus

Andrew

JS / CS2 loading files selected in Bridge

Post by Andrew »

Can anyone help me get started with Bridge / CS2. How to obtain the list of files (as File objects preferably) selected in Bridge to use with a script from the photoshop scripts folder. Seems pretty basic but can't find the right place in either the CS2 JS docs, or the Bridge help (let alone the PS help). Equivalent to using the list of files selected in the File Browser in CS (via the function in Dr Brown's Image Processor).

Also, related question, should I be able to launch my PS scripts from Bridge (how? no scripts option) and does doing so require modification of the scripts.

Just a few pointers would be much appreciated.

Andrew
Andrew

JS / CS2 loading files selected in Bridge

Post by Andrew »

Hmmm this is getting seriously frustrating. Now trying to call a script from Bridge following the instructions in the Bridge JS Reference:

Code: Select allnewMenu = new MenuElement( "menu", "MyMenu", "after Help", "myMenu" );
alertCommand = new MenuElement( "command", "Run Test", "at the end of myMenu",
"myAlert" );
myScript = '/c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts/nn-test.js';
alertCommand.onSelect = function () { alert(myScript);photoshop.executeScript (myScript); }

When I run the menu item the first alert(myScript) does happen and photoshop does get opened but no script is run. The idea here is that I can somehow access the list of selected images from Bridge (can I?) but run the PS script across those images? Can I access the list as file objects / names or must the images be loaded?

Andrew
rstucky

JS / CS2 loading files selected in Bridge

Post by rstucky »

Andrew -

Bridge is a bit different, as it appears you found out! First off, it doesn't have a "Scripts" menu. Scripts are run by creating menus in bridge. You then select the set of files to operate on, and select the menu.

AdobeLibrary1.jsx (you can download this, along with 2 other libraries from Adobe Exchange) contains a function:

getBridgeFiles( mask, getFolderChildren, filesOnly, firstOnly )

mask is a set of extensions ( "jpg,crw,tif" ). It will return files of the types you specify. Leave it blank to return all files

getFolderChildren - if true - it will return the first level children of any selected folder

filesOnly - if true it will only return files, no selected folders

firstOnly - if true returns the first file selected

It also performs a synch with VersionCue so if the user is selecting VC files, they will be downloaded to the local drive before the function returns.

If the user has selected nothing in the bridge window, getBridgeFiles returns all of the files in the active document. You can look this function as doing a reasonable job of interpretting what the user wants and giving you the files.

To do the same thing without this function, you'd be looking at

app.document.selections - which is a list of selected thumbnails.

or

app.document.thumbnail.children which is the list of children of the current document.

When you look at photosho.executeScript() you'll notice that all it does is take the TEXT of a script and execute it via an eval statement. So it won't execute a PS script by passing the file name.

var f = new File( [your path] );
f.open( "r" );
var buf = f.read();
f.close();
photoshop.executeScript( buf );

that would execute the script you wanted, but it wouldn't pass the set of selected files.

Since I don't have the script you are attempting to execute, I can't give you specific guidance on getting files selected in Bridge to execute with it. More than likely, it will take some minor modifications of the script.

When using BridgeTalk (which is what photoshop.executeScript does ), files are passed as an array of paths.

So, if your script expected to see an array called "files", looking something like this:

for ( var i = 0; i < files.length; i++ ) {
// do something in PS
}


you could execute it this way:

var files = getBridgeFiles();
var f = new File( [YOUR PATH] );
f.open( "r" );
var buf = f.read();
f.close();

var script = "var files = eval( " + files.toSource() "); \n";
script += buf;
photoshop.executeScript( script );

More in the next post


Bob
rstucky

JS / CS2 loading files selected in Bridge

Post by rstucky »

Ok, now for the more sophisticated approaches. Assuming that you have a PS script ready to go and that it operates on one or more files....

There are two basic approaches to executing scripts from bridge in PS:
1. Send the script and a list of files, allow PS to chew on the files as a group
2. Send the script and 1 file at a time.

In both approaches, you have to save a copy of the script in StartupScripts. Bridge knows nothing of the script in the PS script location.
Hopefully, they will get a handle on this and create a script file structure that is uniform across all products.

In general, I prefer #2 for almost all scripts. Unless there is a long, dedicated process to be run in the target app, sending a script to operate on 1 file is cleaner code, and easier to do.

So I would start by modifying your PS script.

Add a menu to bridge, hide the menu call in something like this

if ( BridgeTalk.appName == "bridge" ) {
//add your menu
}

modify your script so that it has a "function" to call as an entry point from bridge.

The entry point function would look somehting like this:

theScriptCode = function( file ) {
// do something with the file
}
bridgeEntryPoint = function() {
files = getBridgeFiles( TYPES.PHOTOSHOP_OPENABLE );
var bti = new BridgeTalkIterator(); // a library thing
for ( var i = 0; i < files.length; i++ ) {
var scp = "var file = eval( " + files..toSouce() + " );\n";
scp += "theScript = " + theScriptCode + "\n";
scp = "theScript( file );";
bti.addMessage( "photoshop", scp );
}
bti.send();
}

BridgeTalkIterator's is in li1, its constructor is:

BridgeTalkIterator = function( showProgress, text, title, notifyComplete )

showProgress - boolean - show a progress bar on how things are going in PS
text - text for progress bar
title - tile for progress bar palette
notifyComplete - if true - makes an alert and beep when done

To execute in the other mode (send all files at once) you may want to look at BridgeTalkLongProcess, also in lib1 as a way to do that and show progress bars in bridge. The contact sheet for ID is an example script on how to use this.

Bob

Bob
xbytor

JS / CS2 loading files selected in Bridge

Post by xbytor »

rstucky wrote:
When you look at photosho.executeScript() you'll notice that all it does is take the TEXT of a script and execute it via an eval statement. So it won't execute a PS script by passing the file name.

var f = new File( [your path] );
f.open( "r" );
var buf = f.read();
f.close();
photoshop.executeScript( buf );

that would execute the script you wanted, but it wouldn't pass the set of selected files.



Instead of doing this, could you not (more simply) do:

Code: Select allphotoshop.executeScript('//@include "[your path]";');

which would eval the include directive in the context of the PS interpreter. You could also stick an includepath directive in there as well. Or am I missing something here?
rstucky

JS / CS2 loading files selected in Bridge

Post by rstucky »

Never tried it, never really thot about it either - but it should work...


I've spent my time writing scripts that appear and function as fully vested features in Bridge. In that regard, the scripts I've done have extensive UI, etc. and don't really work in the XDOM (cross-app document object model) world.

So while I've seen this stuff like the XDOM, I haven't really had the time to play with it much or even think about the best ways to do things.

From my personal perspective the advantage Bridge brings to the table is its scriptability, and with that is the ability to create scripts that look and feel like they are part of the core product.

In fact, we got into a bind developing the original bridge scripts for CS2. Our original specs were to write some basic scripts. When they hit QA, the biggest complaint was that the scripts looked like features, and therefore needed more validation, error checking, UI review, etc. Ended up barely making the ship date with the extended functionality demands. One of those features: scripts executed in any point app from bridge had to show progress bars of what was happening in the target app. Not a trivial implementation.

I have a friend who has started http://www.barredrocksoftware.com (she's raises chickens too) to write and sell bridge scripts that are true feature additions to bridge. Her work centers around bridge metadata and bridge->photoshop automation. She only looks for $5 - $10 a script, hopefully just enough to allow her to continue doing this full time.
Andrew

JS / CS2 loading files selected in Bridge

Post by Andrew »

Thank you very much for that Bob, it helps a lot, I will work on it today and see if I can get the basic steps sorted out. In the meantime a related structural question - kind of a 3 to your 1 and 2

Can I run a script from CS2 that sends a request to Bridge to return the list of selected files and then continues to work on things within PS. Can I also test that files actually were selected (as opposed to just getting the list of all files in the folder).

PS ..Bridge..PS

Incidentally, I can see there's a wealth of useful stuff in those libraries, I must spend some time going through them carefully. One way I think this site could contribute usefully to the development of the Adobe scripting project would be in helping to extend and improve basic function libraries like that - people can submit, critique and hack functions so we get a feedback system for ever improving scripting tools.

Your friend sounds interesting (and incredibly good value too) - I live out in the sticks as well, 165 acres, nearest neighbour 1 km away. The good life except for my terrible internet connection.

Andrew
rstucky

JS / CS2 loading files selected in Bridge

Post by rstucky »

Wife and I are "sticks" dwellers too. We have neighbors, but the nearest anything is about 15 miles. We use Starband satellite service. Does pretty well given the other options.

In theory you can. My experience says no. Or at least not easily.

There's a bug in PS' BridgeTalk implementation that prevents an onResult handler from firing. The problem will be that you wouldn't get a signal to continue after firing off the message to bridge.

To get the selected files/folders use app.document.selections. That returns an array of thumbnail objects. You can use thumbnailsToFiles() which takes an array of thumbnails and returns an array of files/folders.

var bt = new BridgeTalk();
bt.target = "bridge";
bt.body = "var f = thumbnailsToFiles( app.document.selections ); f.toSource()";
bt.onResult = function( msg ) {
var files = eval( msg.body );
for ( var i = 0; i < files.length; i++ ) {
$.writeln( files[ i ].toSource() );
}

}
bt.onError = function( msg ) {
alert( msg.body );
}
bt.send();


if everything is working you'll get a list of the selected files in the ESTK window. You get that if you run it from the ESTK. If you switch the ESTK to PS, you'll get nothing (which means the onResult handler isn't firing).

I wish I had reason to try that before CS2 shipped, but I didn't.

Is there a compelling reason for the script to be started from PS and not from Bridge?
Andrew

JS / CS2 loading files selected in Bridge

Post by Andrew »

I'm not sure about the compelling reason, I'm still getting my head around workflow with Bridge and PS separated. My favourite way of working with finished scripts is to use my script-launcher that has 1 FKey to launch any number of scripts (and actions) from PS - most of which then go to a dialog that includes file selection plus whatever other options I want to provide. Almost always I like to provide the options of browse to folder (with various file name mask options) and 'use selected'. It seems Bridge does not allow FKeys to be assigned?

So far I am not getting to stage 1. I have now tried (inside a menu onSelect)

Code: Select all{
alert('hello from bridge');
photoshop.executeScript( 'alert("hello from PS");' );
alert('hello from bridge 2');
}

It issues the first hello, goes to PS but does not issue the second one. When I return to Bridge the second alert has been issued. Before that I tried getting the string from an external script and the string comes over fine (of course) but again it does not execute. Doesn't look good so far.

Your Open and Close script works fine but putting the whole script inside the menu button is another story when there are many scripts some of which are 1000's of lines long. Maybe I am still missing the point.

Andrew
Andrew

JS / CS2 loading files selected in Bridge

Post by Andrew »

Some success at last. I've now tried reading the target script as a string into the OpenShut.remoteScript function in your Open Close script, then doing an eval on the string and that is working.

I guess that is a workable method. I think that means that Bridge would be reading the target script every time it loads (not a good idea once there are a heap of scripts) - next I will try to tie it up in a onSelect so it only gets read when it is selected.

It seems for some reason that executeScript does not work for me.

Andrew