Returning values from BridgeTalk

General Discussion of Scripting for Adobe Bridge

Moderators: Tom, Kukurykus

Mike Hale

Returning values from BridgeTalk

Post by Mike Hale »

If I use BridgeTalk to send a simple script/function to Photoshop and that function returns a value, how do I get that value back in Bridge?
xbytor

Returning values from BridgeTalk

Post by xbytor »

In the Bridge docs, there's a section called 'Passing values between applications' on page 190 that describes how to do it.

The code you'd probably be interested in is this:
Code: Select allvar bt = new BridgeTalk;
bt.target = "bridge";

//the script passed to the target application returns the object using "toSource"
bt.body = "var tn = new Thumbnail(File('C:\\Myphotos\\photo1.jpg'));\r" +
   "var md = {fname:tn.metadata.FileName,  fsize:tn.metadata.FileSize};\r" +
   "md.toSource();"

//For the result, use eval to reconstruct the object
bt.onResult = function(resObj) {
   md = bt.result = eval(resObj.body);

   // Now you can access fname and fsize properties
   doSomething (md.fname, md.fsize);
};

//launch the Bridge if it's not already running
if (!BridgeTalk.isRunning("bridge")) {
   BridgeTalk.launch("bridge");
}

// send the message
bt.send();

The key here is defining the onResult method in the BridgeTalk object. When the expression has been eval'd on the other side, the result of that expression is sent back as the parameter to the onResult method. Note that this happens asynchronously. I'm not sure if there is a way of forcing this to work synchronously.

-X
Mike Hale

Returning values from BridgeTalk

Post by Mike Hale »

I have been banging my head against those pages all day without out it getting through. And I have be unable to find a 'real world' example

When I run the bt in estk with a breakpoint on the first line in the onResult functiion, it never breaks. In step by step mode it skips the whole function.

Mike
xbytor

Returning values from BridgeTalk

Post by xbytor »

I'll try and cook up a real-world example later this weekend. I've done some bridgetalk work so I should be able to bang my way through this...

-X
Mike Hale

Returning values from BridgeTalk

Post by Mike Hale »

Note that this happens asynchronously.

Let me guess... That is why it doesn't break?
Mike Hale

Returning values from BridgeTalk

Post by Mike Hale »

For what it's worth, I replaced the filename in the sample code with a file I have on the desktop and the function inside the onResult method with an alert.

The alert never gets called. I even added a $.sleep(10000); to the end to wait for the results and still no go.

Code: Select allvar bt = new BridgeTalk;
bt.target = "bridge";
bt.body = "var tn = new Thumbnail(File('~/Desktop/angie2.tif'));\r" +
   "var md = {fname:tn.metadata.FileName,  fsize:tn.metadata.FileSize};\r" +
   "md.toSource();"
bt.onResult = function(resObj) {
   md = bt.result = eval(resObj.body);
   alert(md)
};
if (!BridgeTalk.isRunning("bridge")) {
   BridgeTalk.launch("bridge");
}
bt.send();

I tried it in ESTK with both Photoshop and Bridge as targets and in Photosop from the scripts menu.

All the posts I can find on this subject makes it sound like this should be easy.
xbytor

Returning values from BridgeTalk

Post by xbytor »

Here's a general solution: a synchronous 'send' method for BridgeTalk objects. I'll post a more industrial version of this later with better error handling, but this should be sufficient in almost all cases.

Code: Select all// Send a synchronous message. The result is returned.
// If a result doesn't come back in 'timeout' seconds, undefined is returned.
BridgeTalk.prototype.sendSynch = function(timeout) {
  var self = this;
  self.onResult = function(res) {
    this.result = res.body;
    this.complete = true;
  }
  self.complete = false;

  self.send();

  if (timeout) {
    for (var i = 0; i < timeout; i++) {
      BridgeTalk.pump();       // process any outstanding messages
      if (!self.complete) {
        $.sleep(1000);
      } else {
        break;
      }
    }
  }

  var res = self.result;
  self.result = self.complete = self.onResult = undefined;
  return res;
};
// for typos, provide an alias
BridgeTalk.prototype.sendSync = BridgeTalk.prototype.sendSynch;


Now, let's see how easy this is to use:

Code: Select allfunction test() {
  var bridgeApp = "bridge-1.0";

  if (!BridgeTalk.isRunning(bridgeApp)) {
    BridgeTalk.launch(bridgeApp);
  }

  var bt = new BridgeTalk();
  bt.target = bridgeApp;
  bt.body = "new Date().toString()";
  var res = bt.sendSynch(10);
  alert(res);
};

test();


-X
Mike Hale

Returning values from BridgeTalk

Post by Mike Hale »

Thank you so much for this X. This is a 'real world' example I can understand. The examples in the adobe's bridge forum were to hard for me to follow.

Just to make sure I understand this, if I wanted to pass an object and had 'obj.toSource' in the bt.body I would need to eval(res) right?

Mike
xbytor

Returning values from BridgeTalk

Post by xbytor »

I figured out what to do by looking in AdobeLibrary1.jsx. I later discover that Jack Galloway had posted a similar chunk of code on Adobe's Bridge forum back in January.

Just to make sure I understand this, if I wanted to pass an object and had 'obj.toSource' in the bt.body I would need to eval(res) right?


Yep. In general, you should use the toSource/eval idiom when passing data back and forth.

-X
amandak695

Returning values from BridgeTalk

Post by amandak695 »

xbytor wrote:In the Bridge docs, there's a section called 'Passing values between applications' on page 190 that describes how to do it.

The code you'd probably be interested in is this:
Code: Select allvar bt = new BridgeTalk;
bt.target = "bridge";

//the script passed to the target application returns the object using "toSource"
bt.body = "var tn = new Thumbnail(File('C:\\Myphotos\\photo1.jpg'));\r" +
   "var md = {fname:tn.metadata.FileName,  fsize:tn.metadata.FileSize};\r" +
   "md.toSource();"

//For the result, use eval to reconstruct the object
bt.onResult = function(resObj) {
   md = bt.result = eval(resObj.body);

   // Now you can access fname and fsize properties
   doSomething (md.fname, md.fsize);
};

//launch the Bridge if it's not already running
if (!BridgeTalk.isRunning("bridge")) {
   BridgeTalk.launch("bridge");
}

// send the message
bt.send();

The key here is defining the onResult method in the BridgeTalk object. When the expression has been eval'd on the other side, the result of that expression is sent back as the parameter to the onResult method. Note that this happens asynchronously. I'm not sure if there is a way of forcing this to work synchronously.

-X
Well, great work! You have helped me to improve my knowledge about this field. Thank you so much for sharing.