Photoshop CS2 - Obtaining List of Files Selected in Bridge

Upload Adobe Bridge Scripts, Download Adobe Bridge Scripts, Support for Individual Adobe Bridge Scripts

Moderators: Tom, Kukurykus

Andrew

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by Andrew »

These two scripts achieve a transfer of data from Photoshop CS2 to Bridge back to CS2. Run the first script in Photoshop while Bridge is loaded and has some files selected. The photoshop script will report on which files are selected in Bridge.

Save the following as ah_bridge_selections.js in your CS2 scripts folder.

[If the address of your scripts folder is anything different from /c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts
you will need to make edits in three places across the two scripts.]

Code: Select all// script to be executed in Photoshop CS2
#target "photoshop"

// runs the sFile script in Bridge as a string
function ah_getDataFromBridge (scriptFile, datFile) {
   var targetApp = BridgeTalk.getSpecifier( "bridge", "1");
   var running = BridgeTalk.isRunning( "bridge");
   if( targetApp && running) {
      var bt = new BridgeTalk;
      bt.target = "bridge";
      var sStr = ah_getScriptString(scriptFile);
      bt.body = sStr;
      bt.send();
      alert('Data Request Sent to Bridge\nPress OK to see results');
      var bridgeData  = ah_getScriptString(datFile);
      if (bridgeData.length == 0) alert('Sorry No Valid Files Selected in Bridge');
      else alert(bridgeData);
      function ah_getScriptString  (fStr) {
            f = new File (fStr);
            if (f.open('r')) {
               var lsString = f.read();
               return lsString;
            }
            else throw('failed to open script'+f.fsName);   
      }
   }
   else alert('Bridge is not running');
}

ah_getDataFromBridge ('/c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts/ah_bridge_selections2.txt', '/c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts/ah_bridge_selections.dat');


Save the following as ah_bridge_selections2.txt in the same folder

Code: Select all// script to be executed in Bridge having been sent as a string from Photoshop CS2

ah_writeData = function (tFile,tString) {
   if (tFile.open('w')) {
      if (tFile.write(tString)) tFile.close();
      else throw ("Error saving file list\n" + tFile);
   }
   else throw ('Error, Data File Not Opened\n' + tFile);
}

ah_CollectBridgeData = function (fileString) {
   var tFile = new File (fileString);
   var filestr = ah_fileThumbnailsToFilestr(app.document.selections);
   ah_writeData(tFile,filestr);
}

ah_fileThumbnailsToFilestr = function( thumbnails ) {
   var fileAr = new Array();
   for ( var i = 0; i < thumbnails.length; i++ ) {
      if(thumbnails.spec instanceof File) fileAr.push(thumbnails[ i ].spec);
   }
   return fileAr.toString();
}
ah_CollectBridgeData('/c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts/ah_bridge_selections.dat');

Run ah_bridge_selections.js from Photoshop CS2. Note these are only test scripts. They create a third file ah_bridge_selections.dat also in the scripts folder (something I would not do for a production script).

For preceding discussion read this thread:

bb/viewtopic.php?t=174

Andrew
Andrew

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by Andrew »

Another version that also manages folder selections:

bb/viewtopic.php?t=224

Andrew
Andrew

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by Andrew »

This is a more recent version that does everything in one file and obtains folder selections.

Code: Select allfunction bridgeSelections () {
   var myData = {};
   var procFiles;
   myData.bridgeDat = new File('/c/Program Files/Adobe/Adobe Photoshop CS2/Presets/Scripts/ah_bridge_selections.dat');
   if (app.version[0] == '9') {
      if (BridgeTalk.isRunning( "bridge")) {
         fMod = myData.bridgeDat.modified ;
         count = 0;
         ah_collectDataFromBridge (myData.bridgeDat);
         while (!(myData.bridgeDat.modified > fMod)) {
            $.sleep(1000);
            if (count > 20 && !confirm("Still Collecting Bridge Selections\n To Continue click Yes")) break;
            count++
         }
         if ((procFiles = getBridgeSelections(myData)) == 2) return -1;
      }
   }
   alert(procFiles);
}
function ah_collectDataFromBridge (datFile) {
   var targetApp,running,bt,sStr;
   targetApp = BridgeTalk.getSpecifier( "bridge", "1");
   running = BridgeTalk.isRunning( "bridge");
   if( targetApp && running) {
      bt = new BridgeTalk;
      bt.target = "bridge";
      sStr = bridgeString(datFile);
      bt.body = sStr;
      bt.send();
   }
}

function bridgeString(datFile) {
   return "   ah_CollectBridgeData( '" + datFile + "');" +
      "function ah_writeData (tFile,tString) {" +
         "if (tFile.open('w')) {" +
            "if (tFile.write(tString)) tFile.close();" +
            "else throw ('Error saving file list ' + tFile);" +
         "}" +
         "else throw ('Error, Data File Not Opened ' + tFile); " +
      "}" +
      "function ah_CollectBridgeData (fileString) {" +
         "var tFile = new File (fileString);app.document.refresh;" +
         "var filestr = ah_fileThumbnailsToFilestr(app.document.selections);" +
         "ah_writeData(tFile,filestr);" +
      "}" +
      "function ah_fileThumbnailsToFilestr ( thumbnails) {" +
         "var fileAr = new Array();" +
         "for ( var i = 0; i < thumbnails.length; i++ ) {" +
            "if(thumbnails.spec instanceof File) fileAr.push('file|' + thumbnails[ i ].spec);" +
            "else if(thumbnails.spec instanceof Folder)  fileAr.push('folder|' + thumbnails[ i ].spec);" +
         "}" +
         "return fileAr.toString();" +
      "}";
}

// reads the dat file which contains the bridge selection info
function getBridgeSelections(myData) {
   var procFiles,bridgeFileStringAr,bridgeFileString,i;
   procFiles=new Array();
   bridgeFileStringAr = [];
   if (BridgeTalk.isRunning( "bridge")) {
      if (myData.bridgeDat.exists && myData.bridgeDat.open('r')) bridgeFileString = myData.bridgeDat.read();
      else throw('failed to open bridge data file '+myData.bridgeDat.toString());
      if (bridgeFileString.length > 2) bridgeFileStringAr = bridgeFileString.split(',');
      else {alert('There appear to be no selections in Bridge'); return 2;}
      for (i = 0; i < bridgeFileStringAr.length; i++) {
         bridgeFileStringAr = bridgeFileStringAr.split('|');
         if (bridgeFileStringAr[0] == 'file') procFiles.push(new File (bridgeFileStringAr[1]));
         else procFiles.push(new Folder (bridgeFileStringAr[1]));
      }      
      return procFiles;
   }
   else {alert('Requested Selected Files - Bridge not running');return 2;}         
}

bridgeSelections();

Andrew
miked

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by miked »

Hi Andrew

I'm wondering how to achieve this in reverse...that is, make selections in Bridge and chose a menu item that then sends the selections to a script in photoshop.

I know how to get at the selections I think, but I'm not sure how to pass them to the script in PS...as arguments? as an array, but again as an argument? via a tmp file saved and read somewhere?

I can see that the "Merge to HDR" command is able to do this (take selections in bridge and get them to a script in photoshop) but i can't figure out the mechanism.

Any pointers would be greatly appreciated.

...Mike
xbytor

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by xbytor »

There are a couple of different ways of doing this. In CS3 you can setup a script to look like an automation plugin. If you take that route, most of the work is done for you already. If you are using CS2, it takes a bit more work. In ContactSheetX, I support both mechanisms and all the gory details can be found in this file:
http://ps-scripts.cvs.sourceforge.net/* ... Bridge.jsx ... Bridge.jsx

Not all of that code is pretty and I haven't really looked at it in awhile, so there may be better ways of getting the job done, but it does work in both CS2 and CS3.

-X
miked

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by miked »

Thanks for the pointers. I don't care about CS2 support at all, so I guess all I want is to make my script looks like an automation target.

Will I be able to glean how to do that from one of your many scripts? If so, which ones should I be focusing on? The one linked is great for the bridge stuff, but I need to know what to do to my script to make it work.

So far, hacking around a bit, stolen heavily from the imageprocessor init script, I have this for the bridge part:

Code: Select all#target bridge
photoshop10.tester = function (files) {
   alert("In photoshop.tester");
   try {
      // Make sure this can be run.
      //if (availabilityCheckOptions == null)
      //   availabilityCheckOptions = new AvailabilityCheckOptions ();
         
      //if (!photoshop10.correctPSIsAvailable (availabilityCheckOptions))
      //   return;
      
      if (BridgeTalk.appName != "photoshop") {
         alert("Section 1");
         // Bring Photoshop to the foreground.
         BridgeTalk.bringToFront (photoshop10.versionInfo.btTargetName);
   
         // Create a new BridgeTalk message for Photoshop to invoke
         // Image Processor with the selected files
         var btMessage = new BridgeTalk;
         btMessage.target = photoshop10.versionInfo.btTargetName;
         btMessage.body = "photoshop10.tester (" + files.toSource () + ");";
         alert(btMessage.body);
         // Make sure we attempt to launch it.
         if (!BridgeTalk.isRunning (photoshop10.versionInfo.btTargetName)) {
            BridgeTalk.launch (photoshop10.versionInfo.btTargetName);
         }
            
         btMessage.send ();
      } else {
         alert("Section 2");
   
         // Image Processor script will recognize this and use it
         var gFilesFromBridge = files;
   
         var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
         var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
         var strImageProcessor = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/FileName=btTest.jsx");
         
         var ipFile = new File (app.path + "/" + strPresets + "/" + strScripts + "/" + strImageProcessor);
         alert(ipFile);
         var rememberDialogModes = displayDialogs;
         displayDialogs = DialogModes.ALL;
               
         if (ipFile.exists) {
            if (ipFile.open ('r')) {
               var script = ipFile.read ();
               ipFile.close ();
               eval (script);
            } else {
               alert (localize ("$$$/PSBI/Automate/ImageProcessor/CouldNotOpen=btTest.jsx could not be opened."));
            }
         } else {
            alert (localize ("$$$/PSBI/Automate/ImageProcessor/NotFound=btTest.jsx could not be found."));
         }
         displayDialogs = rememberDialogModes;
      }
   }
   catch (error) {
      if (error.number != 8007) // Don't report user cancelled errors.
         alert (error);
   }
}


//-----------------------------------------------------------------
// This routine is called when the Bridge's Image Processor menu
// item is chosen.
//-----------------------------------------------------------------
photoshop10.testerFromBridge = function ()
   {
   try
      {
      // Make sure this can be run.
      //var availabilityCheckOptions = new AvailabilityCheckOptions ();
         
      //if (!photoshop10.correctPSIsAvailable (availabilityCheckOptions))
      //   return;
      var files = photoshop10.getBridgeFileListForAutomateCommand (true, false);
      alert(files);
      
      if (files.length != 0)
         photoshop10.tester (files);
      }
   catch (error)
      {
      if (error.number != 8007) // Don't report user cancelled errors.
         alert (error);
      }
   }


//-----------------------------------------------------------------
// The code below inserts the Image Processor menu item into the
// Bridge menus.
//-----------------------------------------------------------------
if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion == photoshop10.versionInfo.bridgeTargetVersion))
   {   
   // Use temp function to keep vars out of global namespace.
   var alCommand = new MenuElement( "command", "Test load", "-at the end of Tools","alCommandID" );
        alCommand.onSelect = photoshop10.testerFromBridge;
   }




and this for the photoshop part:

Code: Select allalert("btTest is called.");
var filesFromBridge = gFilesFromBridge;
alert(fileFromBridge);


I know there is a lot missing from the ps part but I have no idea what that is.

I also don't know how to active the part of the code called "Section 2" but one thing at a time. If you or anyone else could point me at how I can get the photoshop script to receive the list of files, I'd be most grateful.

...Mike
xbytor

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by xbytor »

ImageProcessor is not in proper automation format. You need to look at Photomerge. It's one of the ones I read through to figure out how to do it.

-X
miked

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by miked »

I've studied the code for an hour or so and the only thing I can find related to this is around line 1060...

Code: Select allphotomerge.doInteractivePano = function ()
{
   // Because of the ",true", the dialog is pre-loaded with any bridge files.
   this.getFilesFromBridgeOrDialog( localize("$$$/Private/Photomerge/PMDialogexv=PMDialog.exv"), true );

   try {
      if (this.stackElements && this.doPanorama())
      {
         fitViewOnScreen();
         var flagDesc = new ActionDescriptor();
         flagDesc.putBoolean( kPhotomergeAdvancedBlendingFlag, photomerge.advancedBlending );
         app.putCustomOptions( "PhotomergeFlags001", flagDesc, true );
      }
   }
   catch (err)
   {
      if (this.stackDoc)
         this.stackDoc.close(SaveOptions.DONOTSAVECHANGES)
   }
}


But I can't identify what makes this an automation ready plug in, what makes this work. It's making me mental because there are *no* docs on this stuff, and the code itself is not documented with any meaningful info I know this is straightforward once I get past a certain point, but I can't grasp what it is that I'm doing wrong

...Mike
xbytor

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by xbytor »

Page 204 in the CS3 PSJS reference guide kinda has docs on how the Automation plugin is supposed to look. Your script needs to have an XML block like this:

Code: Select all<javascriptresource>
<name>Photomerge...</name>
<about>Photomerge^r^rCopyright 2006 Adobe Systems Incorporated. All rights reserved.^r^rCombines several photographs into one continuous image.</about>
<eventid>8cba8cd6-cb66-11d1-bc43-0060b0a13dc4</eventid>
<menu>automate</menu>
</javascriptresource>


at the top of the file. That tells PS that it's an automation plugin.

Your code in the script will need to have a bit of code that looks like this:

Code: Select all      // This code handles the CSX being called via the
      // Automation Framework in CS3
      var lvl = $.level;
      $.level = 0;

      try {
        if (app.playbackParameters.hasKey(sTID('filesList'))) {
          CSXBridge.callFromBridge = true;
          CSXBridge.files = [];
          opts.noUI = false;
          var flist = app.playbackParameters.getList(sTID('filesList'));
          for (var i = 0; i < flist.count; i++) {
            CSXBridge.files.push(flist.getPath(i));
          }

          // since we are only interested in the filesList
          // we can clear the playbackParameters and read in
          // settings from the default ini file
          app.playbackParameters = new ActionDescriptor();
          app.displayDialogs = DialogModes.ERROR;
        }
      } catch (e) {
      }
      $.level = lvl;
    }



This is obviously comes from CSX from the ContactSheetX.jsx file. For integration with Bridge I have a CSXBridge object into which I stuff the list of files. I use photoshop10.runActionCommand to call CSX from Bridge. Photomerge is called using a completely different technique where the list of files is passed as via an Array.toSource() string.

There aren't any examples, except for my CSX and WGX, that use runActionCommand with a script implementing the plugin interface. I had to figure it out on my own with a bit of help from Adobe.

-X
miked

Photoshop CS2 - Obtaining List of Files Selected in Bridge

Post by miked »

I switched over to CSX so that I can figure things out a bit better I hope. Reading the code, this is what is happening, and please correct me if I have something wrong:

1. the menu item runs .runFromBridge, which I understand.

2. .runFromBridge calls .getSelectedFiles which returns a list of file specs based on the selections, which I understand.

3. .runFromBridge then builds a bridgetalk object, which I understand.

4. then sends it to .run, which I understand.

5. .run then does two things I don't understand. First it uses a UUID, and second it uses something called runActionCommand. Ai also assume that if I am oly trying to support CS3, that I can stop at the "if (CSXBridge.isCS3()) {" line.

So I guess my next questions are:

What is the purpose of a UUID, and is it based on something or can I just make one up? I see it's included in a text block at the top, does that block signify something?

Second, WTF is runActionCommand I can't find that one in any manual ( the bridge CS3 stuff from the SDK or the PS one).

Thanks for the help, you have no idea how much I appreciate it.

...Mike[/list]