Setup OSC communication for Photoshop
In this post, we’ll setup Photoshop to use OSC (Open Sound Control).
We’ll use a Generator plugin called Openbuttkiss, which gives OSC messages access to Photoshop’s API. More specifically, when an OSC message with an argument of 1 is recieved, the foreground and background colors are swapped. Utilized by this plugin is a Nodejs module that provides the protocols to communicate via OSC. I made the plugin to demonstrate this sort of integration at its most fundamental level; it is left simple and concise. Expansion will come later.
I used some code from Tom Krcha’s getting-started-plugin - this provided a good foundation for my plugin and the features I would add. Big thanks to him and the others out there that made great tutorials employing Photoshop-Generator and Nodejs:
Andy Hall: Node.js + Photoshop: How Comments Feed Design and Generator, JSConf.Asia 2013
Lee Brimelow: Introduction to Photoshop Generator
Tom Krcha: can no longer locate videos
The purpose of writing this post is to explain and understand the OSC implementation that is happening in my plugin. I’d like to clear up any areas of the code that are prone to confusion, and that may have caused myself some frustration.
To follow along, you’ll need:
Photoshop CC, Generator-Core, Node.js, Osculator, Openbuttkiss
Download openbuttkiss.
In terminal, cd to the plugin folder (openbuttkiss) and run npm install
to download any dependencies.
Follow one of the methods below to set up the plugin with a Photoshop Generator.
Built-in Generator
Place the plugin inside the Photoshop Plug-ins folder:
Applications/Adobe Photoshop CC/Plug-ins/Generator
Open Photoshop. Go to
Photoshop > Preferences > Plug-ins
and checkEnable Generator
. You may need to restart Photoshop for this to take effect.
External Generator
Run the plugin from a locally cloned generator-core library (think of this as our external generator, which exists outside of the Photoshop application). Don’t forget to
npm install
, to grab all the generator-core dependencies. My workflow when using this library consists of having all my plugins inside the generator-core plugins folder:In terminal, cd to
generator-core
and run:
node app.js -f test/plugins/openbuttkiss
This app.js contains all the magic needed to run our plugin. The plugin location is specified at the end of the command.
Photoshop can use Built-in and External Generators to process a plugin; each generator provides a slightly different workflow. Regardless of which generator is being used, the plugin should produce the same results. Be aware that conflicts may arise when using both internal and external generators. In my experience, I had to disable the built-in generator to properly run openbuttkiss with the external generator.
Read more on Photoshop Generators and the Generator Architecture.
After completing the above steps, openbuttkiss should now be available for use. In Photoshop, select the plugin from the drop down menu:
File > Generate > openbuttkiss
Plugin being run by the Built-in Generator
Plugin being run by an External Generator
When selected, the plugin name in the Generate dropdown menu should be checked, telling us and Photoshop that it’s enabled. To disable the plugin, select it again.
Now that we’re running openbuttkiss, we are ready to send it some OSC action. We’ll need to use a program that can handle sending/recieving OSC messages. Here, I’ll be using Osculator, which is free and fully functional to download, minus the 20 second timeouts.
Configuring Osculator
Open up Osculator.
Go to
View > Parameters
, or click on theParameters
icon. This page stores any OSC addresses we plan on communicating to, with each address, being stored as a target. Under theOSC URL or choice from gear menu
column, double click on the empty address slot of target #1. Type in:
osc.udp://localhost:3333
Click the
+
symbol located in the bottom left corner of the Parameters page. Close the Parameters page.Go to
Routing > Manually Create Message...
Name it whatever you want and hit ok. A new message appears in the application window.Click the empty message parameter under the
Event Type
column, selectOSC Routing
from the dropdown menu.Click the empty message parameter under the
Value
column, selectĐ
from the dropdown menu.
Done!
Our new OSC message should now be targeting the address we specified earlier. We should now be able to send it to Photoshop. Do this by clicking the small grey box on the left hand side of the message we just created, it should flash green.
If everything went over smoothly, when we trigger the message in Osculator, we should see the foreground and background colors swap in Photoshop. Remember that openbuttkiss must be enabled in Photoshop.
package.json
{
"name": "openbuttkiss",
"description": "osc-ps plugin",
"version": "0.0.0",
"main": "main.js",
"generator-core-version": ">=1.0.0",
"dependencies": {
"node-osc": "0.2.1"
},
"devDependencies": {}
}
The "main"
field tells us that main.js will be the primary entry point of the plugin.
The "generator-core-version"
field tells us what version of generator we are using. Inaccurately specified version may render the plugin incompatible.
The "dependencies"
field lists any dependencies that our plugin requires to run. Node-osc is the module our plugin uses to process OSC messages. As a matter of fact, if you were to look at node-osc’s package.json, you’d find that node-osc requires another nodejs module, osc-min. This module was used in the original buttkiss. Check out some other popular nodejs OSC modules - maybe you’ll find one you really like!
main.js
var oscR = require('node-osc'),
Retrieve the logic for receiving OSC messages. The logic comes from the node-osc dependency we installed earlier, which exists in the node_modules folder of our plugin.
oscServer = new oscR.Server(3333, '127.0.0.1'),
Create an osc server and assign it to the variable oscServer. Server initialization happens when we run the plugin from terminal, or, if using the internal/built-in Generator, whenever we start up Photoshop. Once we set up a listerner, our server will be able to recieve incoming osc messages at 127.0.0.1 (localhost), port 3333.
Don’t get the oscServer mixed up with our server listener, they are two different things.
toggler = 0,
Toggler gets assigned either a 0 or 1 based on the plugin’s menu-state - whether is is checked or unchecked.
psToFront = "app.bringToFront();";
Switch to Photoshop application. Bring it to the front of any other applications we have open. Must be passed to _generator.evaluateJSXString().
var colorFlip = "var fColor = app.foregroundColor;
app.foregroundColor = app.backgroundColor;
app.backgroundColor = fColor;";
Swap foreground and background colors. Both colorFlip and psToFront are extendscript code (.jsx) and must be handled differently than other javascript in main.js. They are passed through _generator.evaluateJSXString(). I got stuck on this when I first tried to use extendscript in my Generator plugins - Check out my issue at Github.
oscServer.on("message", function (msg, rinfo) {
if(toggler==1 && msg[1]==1){
actions();
}
});
oscServer.on is the server’s listener - it listens for incoming osc messages. The plugin must be enabled at least once for the listener to initialize. After that, the server will always be listening, choosing whether or not to execute actions() based on the conditions of the if statement. If these conditions are not met, the message will still be recieved, but nothing will be done.
There are probebly other ways in which our plugin menu-state can influence our OSC server and server listener. To enable/disable these components, in accordance to our our menu-state, might be a better alternative to our current setup.
function actions(){
_generator.evaluateJSXString(colorFlip);
_generator.evaluateJSXString(psToFront);
}
Called from our oscServer.on, this function executes two things, colorFlip followed by our psToFront. Both of these are passed to _generator.evaluateJSXString().
if(checked==true) {
toggler = 1;
console.log("OSC enabled!");
} else {
toggler = 0;
console.log("OSC disabled!");
}
Inside the onMenuClicked() function. Each time the plugin’s menu-state changes, an if / else statement is executed, setting toggler to 0 or 1.
Node-osc gives us access to different parts of our osc message.
The message bubbahjubbah, sent from Osculator to openbuttkiss, could be broken down like this:
bubbahjubbah transmits two arguments each time it is triggered
msg | msg[0] | msg[1] |
---|---|---|
[ ‘bubbahjubbah’, 1 ] | bubbahjubbah | 1 |
[ ‘bubbahjubbah’, 0 ] | bubbahjubbah | 0 |
I’m sure node-osc and other Nodejs OSC modules allow for a more elaborate parsing of messages. I haven’t fully explored Open Sound Control, and my involvment with it has not surpassed a most basic usage. The benefits of osc seem to be in its ability to develop a rich organization of flexible parameter names. Openbuttkiss keeps clear of all that. Its only interest is a message, of any address, with an argument of 1.
For more info on Open Sound Control: