<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>
<chapter name="Tutorial 51: Jitter Java">
<setdocpatch name="51jJava" patch="51jJava.maxpat"/>

<previous name="jitterchapter50">Procedural Texturing &amp; Modeling</previous>
<next name="jitterchapter52">Jitter Networking</next>
<parent name="jitindex">Jitter Tutorials</parent>



<h1>Tutorial 51: Jitter Java</h1>
<p>This tutorial assumes that the reader is familiar with the process of programming <o>mxj</o> Java classes. The details for how this is done are contained in the <i>Writing Max Externals in Java</i> document.</p>

<p>In this Tutorial we'll outline how <o>mxj</o> classes can operate directly on the cells of an input matrix. We also will see how to create classes in the Java programming language that internally load Jitter objects and define and execute a processing network. Finally, we will learn how to design hardware-accelerated user interface elements by attaching a "listener" to a drawing context and polling a window for mouse events.</p>

<p>The Jitter Java API centers around the <b>JitterObject</b> class, which provides a way for <o>mxj</o> classes to instantiate Jitter objects. The following line of code creates a <o>jit.op</o> Jitter object.</p>

<code language="java">
JitterObject jo = new JitterObject("jit.op");</code>
<p>We can send messages to objects in our Java code by using JitterObject's call() or send() methods. For instance, we might set the operator in the above instance of jit.op as follows:</p>

<code language="java">
jo.send("op", "+");</code>
<p>We could alternatively set this attribute using the setAttr() method:</p>

<code language="java">
jo.setAttr("op","+");</code>
<p>The <b>JitterMatrix</b> class extends JitterObject &#x2013; after all, <o>jit.matrix</o> is a Jitter Object. Since <o>jit.matrix</o> is such a common object it is handy to have convenience methods dedicated to its creation and destruction. For instance, the below line of code creates a new <m>4</m>-plane JitterMatrix of type <m>char</m> and dimensions <m>320</m> by 240.</p>

<code language="java">
JitterMatrix jm = new JitterMatrix(4, "char", 320, 240);</code>
<p>We can also create a JitterMatrix object by specifying the matrix <m>name</m>:</p>

<code language="java">
JitterMatrix jm = new JitterMatrix("Stanley");</code>
<p>If a <o>jit.matrix</o> object named <m>Stanley</m> already exists, this Java peer JitterMatrix object will refer to it. In this case a new <o>jit.matrix</o> object is not created.</p>

<p>Conveniences are nice, but the primary reason the JitterMatrix class exists is to provide native methods to access the data in the matrix cells. We'll see an example of this in action when we open the tutorial patch.</p>

<h2>Accessing an Input Matrix</h2>
<bullet>Open the tutorial patch <openpatchlink>51jJava</openpatchlink> in the Jitter Tutorials folder. Double-click on the <m>matrix info</m> subpatcher. Click on the <o>button</o> object and look at the output in the Max console.</bullet>
<illustration><img src="images/jitterchapter51a.png"/>Information about our matrix printed in the Max console.</illustration>
<p>In this subpatcher, clicking on the <o>button</o> object causes the <o>jit.noise</o> object to send a <m>4</m> plane <m>64</m> by <m>48</m> <m>float32</m> matrix into an <o>mxj</o> object with the <i>j51matrixinfoexample</i> class loaded. This Java class sends some basic information about the input matrix out its outlet. Let's examine the code for the class:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class j51matrixinfoexample extends MaxObject {

   public void jit_matrix(String s)
   {
     JitterMatrix jm = new JitterMatrix(s);

     outlet(0,"name", jm.getName());
     outlet(0,"planecount", jm.getPlanecount());
     outlet(0,"type", jm.getType());
     outlet(0,"dim", jm.getDim());
   }
}</code>
<p>The class consists of a single jit_matrix method. Of course since matrices are passed between Jitter objects as named references, we think of a matrix being input as just a simple two element list, and this is how <o>mxj</o> sees it. The argument of the jit_matrix message is of course the matrix <m>name</m>, so the first thing our method does is create a new JitterMatrix object with the <m>name</m> of the input matrix as the constructor's only argument. The JitterMatrix object that is created will have that named <o>jit.matrix</o> object as its peer. The next four lines of code simply output the results of some basic queries that can be made using the methods of the JitterMatrix class.</p>

<h2>Operating on a Matrix</h2>
<bullet>Close the <m>matrix info</m> subpatcher. Open the <m>striper</m> subpatcher.</bullet>
<p>The <m>striper</m> subpatcher gives us an example of a class that operates on the data of an input
matrix. Note that there are two classes set up to be used, with a <link name="gswitch2" type="refpage">Ggate</link> object allowing us to switch between them; we will be comparing two different ways of performing the same operation to see which is more efficient.</p>

<bullet>Click on the <o>toggle</o> box to start the <o>qmetro</o> object.</bullet>
<illustration><img src="images/jitterchapter51b.png"/>A "striping" effect on a Jitter matrix.</illustration>
<p>These classes "stripe" an input matrix by iterating across each row of the matrix and
overwriting the values of some of the cells. Which cells are written to depends on the
values of the <m>on</m> and <m>off</m> attributes: if the <m>on</m> attribute has value <i>v</i> and <m>off</m> has value <i>w</i>, the
algorithm will overwrite <i>v</i> cells, then not write to <i>w</i> cells, and so on as it iterates row-wise through the matrix. </p>

<p>Here is the code for <i>j51matrixstriperA</i>:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class j51matrixstriperA extends MaxObject {

   JitterMatrix jm = new JitterMatrix();
   int frgb[] = new int[] {255, 255, 255, 255};
   int on = 2, off = 1;

   j51matrixstriperA()
   {
     declareAttribute("frgb");
     declareAttribute("on");
     declareAttribute("off");
   }

   //note that this method assumes a 2D char matrix!
   public void jit_matrix(String s)
   {
     jm.frommatrix(s);
     int dim[] = jm.getDim();
     int count = 0;
     boolean notoff = true;
     for (int i="0;i&lt;dim[1];i++)"
        for(int j="0;j&lt;dim[0];j++)"
        {
          if (notoff)
             jm.setcell2d(j, i, frgb);
          if ((notoff &amp;&amp;(++count &gt; on))
               ||(!notoff&amp;&amp;(++count &gt; off)))
          {
             count = 0;
             notoff = !notoff;
          }
        }
     outlet(0, "jit_matrix", jm.getName());
   }
}</code>
<p>In the jit_matrix method we use the getDim() method to find out the dimensions of
our matrix and store them in the int array <i>dim</i>, which we then use as the terminal
conditions in the for() loops of our iterative procedure. The setcell2d method allows
us to directly set the value of any cell in the matrix. When we are finished processing, we
send a <m>jit_matrix</m> message out with the name of our JitterMatrix as the argument.</p>

<bullet>Toggle the <link name="gswitch2" type="refpage">Ggate</link> object back and forth. Which class is faster?</bullet>
<p>The only difference between <i>j51matrixstriperA</i> and <i>j51matrixstriperB</i> is the jit_matrix
method. Here is <i>j51matrixstriperB</i>'s jit_matrix method:</p>

<code language="java">
//note that this method assumes a 2D char matrix!
public void jit_matrix(String s)
{
  jm.frommatrix(s);
  int dim[] = jm.getDim();
  int count = 0;
  int planecount = jm.getPlanecount();
  int offset[] = new int[]{0,0};
  boolean notoff = true;
  int row[] = new int[dim[0]*planecount];

  for (int i="0;i&lt;dim[1];i++)"
  {
     offset[1] = i;
     jm.copyVectorToArray(0, offset, row,
                  dim[0]*planecount, 0);
     for(int j="0;j&lt;dim[0];j++)"
     {
       if (notoff)
       {
          for (int k="0;k&lt;planecount;k++)"
            row[j*planecount+k] = frgb[k];
       }
       if ((notoff &amp;&amp;(++count &gt; on))
            ||(!notoff&amp;&amp;(++count &gt; off)))
       {
          count = 0;
          notoff = !notoff;
       }
     }
     jm.copyArrayToVector(0, offset, row,
                  dim[0]*planecount, 0);
  }
  outlet(0, "jit_matrix", jm.getName());
}</code>
<p>Rather than set values in the matrix one cell at a time, the jit_matrix method of
<i>j51matrixstriperB</i> grabs an entire row from the matrix using JitterMatrix's
copyVectorToArray method, overwrites the appropriate values in the row, then writes
the row back to the matrix using JitterMatrix's copyArrayToVector method. As you
may have noticed, this version of the class is significantly faster than the version that sets
cells in the matrix one-by-one. This is an excellent demonstration of the following very
important thing to keep in mind: it is very expensive to cross the C/Java boundary. The
version of this object that uses setcell must go back and forth across the C/Java boundary once for every cell in the matrix. The latter version goes back and forth just twice per row. If you have tried both versions of the object out, the savings are evident.</p>

<p>The copyVectorToArray and copyArrayToVector methods are overloaded with
signatures that cover all the relevant data types. As you can see from a careful
examination of the above code, these methods provide and expect the Java arrays with the
planar data multiplexed so that all of a cell's data is presented contiguously. There are also
copyVectorToArrayPlanar and copyArrayToVectorPlanar methods for moving a single plane's data into Java. </p>

<div>
<techdetail><i>When using mxj classes to process matrices in Jitter there is no built-in usurp functionality, so it is important to always drive the object network using a <b>qmetro</b></i><i> object, or some other construction that defers events to prevent backlog.</i></techdetail>
</div>
<h2>Copying Input Data</h2>
<p>In the above examples may also have noted the different way that we internally use our
JitterMatrix. Whereas in the matrix info example we created a new JitterMatrix every
time an input matrix was received, this time we cache one instance of JitterMatrix and
copy the input data into it every time using the frommatrix method. Why do we do this?</p>

<bullet>Stop the <o>qmetro</o> and close the <m>striper</m> subpatch. Open the <m>why copy?</m> subpatch. Turn on the <o>qmetro</o>.</bullet>
<illustration><img src="images/jitterchapter51c.png"/>Why copy?</illustration>
<p>The <o>trigger</o> object in this subpatch sends the output of the <o>jit.noise</o> object first into an
instance of the <o>mxj</o> class <i>j51whycopy</i>:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class j51whycopy extends MaxObject {

   JitterMatrix jm = new JitterMatrix();
   boolean copy = false;

   j51whycopy()
   {
     declareAttribute("copy");
   }

   public void jit_matrix(String inname)
   {
     //under normal circumstances
     //we would only create this matrix once
     jm = new JitterMatrix();
     if (copy)
     {
        jm.frommatrix(inname);
     }
     else //!copy
     {
        jm = new JitterMatrix(inname);
     }
     zero(jm);
     outlet(0, "jit_matrix", jm.getName());
   }

   //note that this method assumes the matrix is of type char
   private void zero(JitterMatrix m)
   {
     int z[] = new int[m.getPlanecount()];
     for (int i="0;i&lt;m.getPlanecount();i++)"
        z[i] = 0;
     m.setall(z);
   }
}</code>
<p>The <m>copy</m> attribute flips the jit_matrix method between two different modes: if <m>copy</m> is true, the data from the input matrix is copied into our internal JitterMatrix using the frommatrix method. If <m>copy</m> is not true, the JitterMatrix <m>jm</m> is created with the input matrix as its peer. In both cases our JitterMatrix is zeroed using the setall method, and then output.</p>

<bullet>Turn the <m>copy</m> attribute on and off with the <o>toggle</o> box. What happens in the left <o>jit.pwindow</o>?</bullet>
<p>When the <m>copy</m> attribute is off and we create a new JitterMatrix associated with the input
name we operate directly on the data of that matrix. Therefore we may be altering the
contents of the matrix before other objects have had a chance to see it. In this example
patch, when the <m>copy</m> attribute is true the left <o>jit.pwindow</o> correctly shows the matrix
produced by <o>jit.noise</o>. When the <m>copy</m> attribute is false both <o>jit.pwindow</o> objects are black
because our <o>mxj</o> class alters the matrix's data directly. Therefore if we are operating on a
matrix, we should make sure to copy the input data into an internal cache as we do here
with frommatrix.</p>

<h2>Object Composition</h2>
<p>In this section we'll examine the use of multiple JitterObjects within a single Java class.</p>

<bullet>Toggle the <o>qmetro</o> off and close the subpatcher window. Open the composition
subpatcher. Toggle the <o>qmetro</o> on. </bullet>
<illustration><img src="images/jitterchapter51d.png"/>A Jitter processing chain executing within Java.</illustration>
<p>Let's examine the code for the <i>j51composition</i> class:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class j51composition extends MaxObject {
   JitterMatrix jm = new JitterMatrix();
   JitterMatrix temp = new JitterMatrix();
   JitterObject brcosa;
   JitterObject sobel;
   boolean brcosafirst = false;

   j51composition() {
     declareAttribute("brcosafirst");
     brcosa = new JitterObject("jit.brcosa");
     brcosa.setAttr("brightness", 2.0f);
     sobel = new JitterObject("jit.sobel");
     sobel.setAttr("thresh", 0.5f);
   }

   public void jit_matrix(String mname)
   {
     jm.frommatrix(mname);
     temp.setinfo(jm);
     if (brcosafirst)
     {
        brcosa.matrixcalc(jm, temp);
        sobel.matrixcalc(temp, jm);
     }
     else
     {
        sobel.matrixcalc(jm, temp);
        brcosa.matrixcalc(temp, jm);
     }
     outlet(0, "jit_matrix", jm.getName());
   }

   public void notifyDeleted()
   {
     brcosa.freePeer();
     sobel.freePeer();
   }
}</code>
<p> </p>

<p>Two JitterObjects are created in the class's constructor: brcosa controls a peer <o>jit.brcosa</o>
object, and sobel controls a peer <o>jit.sobel</o> object. The jit_matrix method copies the
data from the input matrix to jm, and then sets the dimensions, <m>planecount</m> and <m>type</m> of the
temp matrix to that of jm with the setinfo method. After this the two JitterObjects can be used to process the data in either order: if the attribute <m>brcosafirst</m> is true, the brcosa
operates first and then sobel, and of course vice versa is <m>brcosafirst</m> is false. We operate on
the data in a matrix by calling a JitterObject's matrixcalc method. The two arguments are input and output matrices &#x2013; it is also possible to use arrays of input and output matrices if the peer Jitter object supports multiple matrix inputs or outputs. This simple example shows how it is possible to define a varying network of Jitter objects within a Java class.</p>

<bullet>Toggle the <m>brcosafirst</m> attribute on and off to see the difference in the resulting image.</bullet>
<p>Finally, note that when the <o>mxj</o> object is deleted and the notifyDeleted method is called, the peer Jitter objects are freed by calling the freePeer() method for every JitterObject we've instantiated. If freePeer() is not called the C object peers will persist until the Java memory manager garbage collects, and this could take a while.</p>

<h2>Listening</h2>
<bullet>Toggle the <o>qmetro</o> off and close the subpatch. Open the <m>cubiccurver</m> subpatch. Turn on the <o>toggle</o> box labeled <i>verbose</i>, move the mouse in the <o>jit.pwindow</o> object and observe the results in the Max Console.</bullet>
<illustration><img src="images/jitterchapter51e.png"/></illustration>
<p>This section assumes you've looked at <i>Tutorial 47: Using Jitter Object Callbacks in JavaScript</i>, which covers object callbacks in Javascript. The Jitter Java API provides the same mechanism for "listening" to events generated by named Jitter objects. In this subpatcher we use this mechanism to track mouse movement within a named <o>jit.pwindow</o>. Let's examine the source code for the <i>j51pwindowlistener</i> class:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class j51pwindowlistener extends MaxObject
implements JitterNotifiable
{
   JitterListener listener;
   boolean verbose = false;

   j51pwindowlistener()
   {
     declareIO(1,2);
     declareAttribute("verbose");
   }

   public void name(String s)
   {
     listener = new JitterListener(s,this);
   }

   public void notify(JitterEvent e)
   {
     //this gets the name of the listening context
     String subjectname = e.getSubjectName();
     //this gets the type of event...mouse, mouseidle, etc.
     String eventname = e.getEventName();
     //this gets the arguments of the event
     Atom args[] = e.getArgs();
     if (verbose)
     {
        outlet(1,subjectname);
        outlet(1,eventname,args);
     }

     if ((eventname.equals("mouse"))
||(eventname.equals("mouseidle")))
     {
        int xy[] = new int[] {args[0].toInt(),
args[1].toInt()};
        //output the x and y coordinates of the mouse
        outlet(0, xy);
     }
   }
}</code>
<p>The first thing to notice is that the class implements an interface called JitterNotifiable. This simple interface ensures that the class has a notify method which will be called when an event is "heard". Notice that the notify method takes a JitterEvent as an argument. The notify method in this class illustrates the methods of these JitterEvents that we'll use to extract the pertinent data: getSubjectName returns the name of the listening context, which is useful if we're listening in more than one place; getEventName returns the name of the event that has been heard; and getArgs returns the arguments that detail the parameters of the event. With the <m>verbose</m> attribute enabled, this class's notify method outputs these data out the second outlet and a <o>print</o> object sends it to the Max Console. </p>

<p>The notify method continues by testing the value of <i>eventname</i> for equality with either <m>mouseidle</m> (for normal mouse movement) or <m>mouse</m> (for movement with the button down). If either of these Strings is a match, the first two arguments, which represent the <i>x</i> and <i>y</i> position of the mouse in the window, are output as a list.</p>

<p>The last thing to note about this class is that before any listening can happen the listener must be created with an existing context. In this case that happens when an instance of the class receives a <m>name</m> message. Unlocking the patch will show you how the <o>jit.pwindow</o> object is given a <m>name</m> first; the <m>name</m> message is then sent to the instance of <i>j51pwindowlistener</i>. </p>

<p>The rest of the patch uses the <i>jitcubiccurve</i> example class to render a cubic curve the follows the mouse around. The control points for the cubic curve are calculated using the <i>j51fracdistancer</i> class, whose code you may want to read through to see if you've understood the material in this lesson:</p>

<code language="java">
import com.cycling74.max.*;
import com.cycling74.jitter.*;
import java.util.*;

public class j51fracdistancer extends MaxObject{

   JitterMatrix ctlmatrix =
     new JitterMatrix(1, "float32", 8);
   float ctldata[] = new float[8];
   int offset[] = new int[] {0};
   float frac = 0.5f;
   float noise = 0.5f;
   Random r = new Random();

   j51fracdistancer() {
     declareAttribute("frac");
     declareAttribute("noise");
   }

    //new x,y input
   public void list(int args[])
   {
     if (args.length != 2) return;
     float x = (float)args[0];
     float y = (float)args[1];
     for (int i="0;i&lt;4;i++)"
     {
        ctldata[i*2]   += (x-ctldata[i*2])   * frac +
((float)r.nextGaussian()*noise);
        ctldata[i*2+1] += (y-ctldata[i*2+1]) * frac +
((float)r.nextGaussian()*noise);
     }
     ctlmatrix.copyArrayToVector(0,offset, ctldata, 8, 0);
     outlet(0, "jit_matrix", ctlmatrix.getName());
   }

   public void jit_matrix(String mname)
   {
     JitterMatrix jm = new JitterMatrix(mname);
     if (jm.getDim()[0] != 8) return;
     if (jm.getPlanecount() != 1) return;
     if (!jm.getType().equals("float32")) return;

     ctlmatrix.frommatrix(mname);
     ctlmatrix.copyVectorToArray(0, offset, ctldata, 8, 0);
   }
}</code>
<h2>Summary</h2>
<p>In this tutorial we've introduced the JitterObject, JitterMatrix, and JitterListener classes, and we've seen how to use them to put together <o>mxj</o> classes that operate directly on data, use composition of existing Jitter objects to define graphs of processing, and how to listen to Jitter objects for events in a way that can facilitate the building of user interface components, among other things.</p>

	<seealsolist>
		<seealso name="jit.matrix">The Jitter Matrix!</seealso>
		<seealso name="jit.noise">Generate white noise</seealso>
		<seealso name="jit.op">Apply binary or unary operators</seealso>
		<seealso name="jit.movie">Play or edit a movie</seealso>
		<seealso name="mxj">Java in Max</seealso>
	</seealsolist>
	</chapter>
