LXforProcessing question

LXSeries open source projects are hosted on github.
Post Reply
Fausto
Posts: 33
Joined: Sun Dec 11, 2016 3:36 am
Location: Sydney NSW
Contact:

LXforProcessing question

Post by Fausto »

Hi Claude,

I am very interested to understand a little bit more how to use your LXforProcessing library.

I would like to use Processing for outputting Artnet/sACN. I have tried to use the examples contained in your library but got a bit stuck. I am not sure how I actually could output DMX via Processing using your library, and I am not sure what hardware I need.

I am trying to build a simple visual interface with Processing, that would let me control a cluster of lights to behave in a certain way according to mouse & MIDI live interaction.

Ideally I would like to output DMX via ethernet using a eDMX1 PRO.

I'd imagine you must be really busy with all your projects, but I was wondering if you could give me a couple of tips just to get me started?

cheers and thank you very much for writing the Processing library and put it up for sharing, I wish I had the coding skills to do that too.
Fausto
NSW Sydney
admin
Site Admin
Posts: 1643
Joined: Mon Nov 05, 2007 1:26 am
Contact:

Post by admin »

Try building the two scene demo project. This example creates a basic two scene type controller that is capable of various DMX output methods.

If the eDMX1 PRO is compatible with an ENTTEC DMX USB PRO, it should work with that output type selected.

The (somewhat mis-named) setupNetworkSocket() function is where the dmx interface object is created. Its misnamed because if the serial ENTTEC connection is selected, that type of object is created and that class has nothing to do with a network socket:

dmx = LXENTTEC.createDMXSerial(this, widget_port_name_field.value, 9600);

The example uses a simple slider interface element. You could use a library like MIDIBus to easily hook up a DMX interface object to MIDI input instead of the sliders. Something like this would map control changes directly to DMX addresses.

void controllerChange(int channel, int number, int value) {
dmx.setSlot(number, value*2);
}

The only thing you need after setting up MIDIBus and creating the dmx object is to call the following in the draw method:

if ( dmx != null ) {
dmx.sendDMX();
}
Fausto
Posts: 33
Joined: Sun Dec 11, 2016 3:36 am
Location: Sydney NSW
Contact:

Post by Fausto »

Wow, thank you!

My computer and DMX device are both out running a show at the moment, will definitely try this once they get back at the end of the month.

I'm speechless, so generous to help me out on this.

Thanks again.
admin
Site Admin
Posts: 1643
Joined: Mon Nov 05, 2007 1:26 am
Contact:

Post by admin »

I looked up the eDMX1 PRO and it is an Art-Net/sACN interface, not a serial USB interface. I would start looking at the simpler Art-Net Two Scene example.

You'll need to make sure that your computer can control the eDMX1 PRO through Art-Net. You should be able to test this with the utility program for the interface. You need to know the name of the network interface for your computer. On newer Mac laptops with only built-in wireless, its "en0"

You can download the MIDIBus library. Stripping out the unessential parts so there's no user interface, the following will convert MIDI control changes into Art-Net:

Code: Select all

/**
 * Copyright (c) 2017 by Claude Heintz Design
 *
 * This file is part of a library called LXforProcessing - https://github.com/claudeheintz/LXforProcessing
 * 
 * LXforProcessing is free software: you can redistribute it and/or modify
 * it under the terms of a BSD style license that should have been included with this file.
 * If not, see https://www.claudeheintzdesign.com/lx/opensource.html.
 * 
 ********************************************************************
 *
 * MIDI to Art-Net
 *
 *   This example converts MIDI control changes to Art-Net.  There is no 
 *   user interface.  See console for messages.
 *
 *   You'll need to edit the sketch to provide the name of your computer's
 *   network interface that you want to use (default is en0).
 *
 *.  You'll need to supply the name of the MIDI device that will send the 
 *.  control changes (default is "SLIDER/KNOB" for Korg nanoKONTROL)
 *
 *. In both cases, the sketch prints out other options if the requested
 *. is not found.
 *
*/

import java.net.*;
import java.util.*;
import lx4p.*;
import themidibus.*;

//*********************************  Global Variables  *********************************

// if you specify a network interface name, binding address can be set automatically
String interfaceToFind = "en0";        //may be different than this

// networkInterfaceIndex is used to search through available interfaces
int networkInterfaceIndex = 0;

// Uncomment the next three lines to use the first network interface found
// String firstNetworkInterface = getNextNetworkInterfaceName();
// interfaceToFind = firstNetworkInterface;

// ***** DMX output
// the next two lines are used if you want to limit sending to a specific interface name
String desiredArtNetNodeName = "ArtNet2USART";
boolean searchForDesiredNode = false;

// DMX interface object
LXDMXInterface dmx;

// ***** MIDI
MidiBus myBus = null; // MidiBus object from themidibus library
String midiDeviceName = "SLIDER/KNOB";



//*********************************  setup *********************************

void setup() {
  size(740, 400);
  frameRate( 10 );

  initMIDI();

  setupNetworkSocket();
}

//*********************************  drawing & events  *********************************

void draw() {
  background(255);
  stroke(0);
    
  if ( dmx != null ) {
    dmx.sendDMX();
  }
}

void dispose(){
  if ( dmx != null) {
    dmx.close();
    System.out.print("closed dmx");
  }

  System.out.println("bye bye!");
}

//*********************************  Network Methods  *********************************

void setupNetworkSocket() {
  if ( dmx != null ) {
    dmx.close();
    dmx = null;
  }

    dmx = LXDMXEthernet.createDMXEthernet(LXDMXEthernet.CREATE_ARTNET, interfaceToFind, "0.0.0.0", null);
    ((LXArtNet) dmx).setPollReplyListener(new LXArtNetPollReplyListener() {
      public boolean pollReplyReceived(LXArtNetPollReplyInfo info) {
          System.out.println("Found node:" + info.longNodeName() + " @ " + info.nodeAddress());
          if ( info.longNodeName().equals(desiredArtNetNodeName) ) {
            ((LXArtNet) dmx).setBroadcastAddress(info.nodeAddress());
            searchForDesiredNode = false;
          }
          return false; // set to true to automatically use found address
        }
    });
    checkPollReply();
    
}


String getNextNetworkInterfaceName() {
	networkInterfaceIndex += 1;
	int ni = 0;
	try {
		Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces&#40;&#41;;
		while &#40; nets.hasMoreElements&#40;&#41; &#41; &#123;
		  NetworkInterface nic = nets.nextElement&#40;&#41;;
		  if &#40; ni == networkInterfaceIndex &#41; &#123;
				return nic.getName&#40;&#41;;
		  &#125;
		  ni ++;
		&#125;
		// did not find, reset and return first &#40;if possible&#41;
		networkInterfaceIndex = -1;
		/*nets = NetworkInterface.getNetworkInterfaces&#40;&#41;;
		if &#40; nets.hasMoreElements&#40;&#41; &#41; &#123;
			return nets.nextElement&#40;&#41;.getName&#40;&#41;;
		&#125;*/
    return "search";
	&#125; catch &#40;Exception e&#41; &#123;&#125;
	return "";
&#125;

void checkPollReply&#40;&#41; &#123;
  try &#123;
    DatagramSocket pollsocket = new DatagramSocket&#40; null &#41;;
    pollsocket.setReuseAddress&#40;true&#41;;
    pollsocket.bind&#40;new InetSocketAddress&#40;InetAddress.getByName&#40;"0.0.0.0"&#41;, &#40;&#40;LXArtNet&#41;dmx&#41;.getPort&#40;&#41;&#41;&#41;;
    pollsocket.setSoTimeout&#40;500&#41;;
    pollsocket.setBroadcast&#40;true&#41;;
    &#40;&#40;LXArtNet&#41;dmx&#41;.sendArtPoll&#40;&#41;;
    &#40;&#40;LXArtNet&#41;dmx&#41;.readArtNetPollPackets&#40;pollsocket&#41;;
    pollsocket.close&#40;&#41;;
  &#125; catch &#40;Exception e&#41; &#123;
  &#125;
&#125;


//*********************************  MIDI Methods  *********************************

void controllerChange&#40;int channel, int number, int value&#41; &#123;
  if &#40; dmx != null &#41; &#123;
    dmx.setSlot&#40;number, 2*value&#41;;
  &#125;
&#125;

void initMIDI&#40;&#41; &#123;
  MidiBus.findMidiDevices&#40;&#41;;
  String&#91;&#93; available = MidiBus.availableInputs&#40;&#41;;
  for &#40;int j=0; j<available.length; j++&#41; &#123;
    if &#40; available&#91;j&#93;.equals&#40;midiDeviceName&#41; &#41; &#123;
      myBus = new MidiBus&#40;this, midiDeviceName, -1&#41;;
      break;
    &#125;
  &#125;
  if &#40; myBus == null &#41; &#123;
  	System.out.println&#40;"Requested MIDI device not found"&#41;;
  	for &#40;int j=0; j<available.length; j++&#41; &#123;
    	System.out.println&#40;available&#91;j&#93;&#41;;
    &#125;
  &#125;
&#125;
Fausto
Posts: 33
Joined: Sun Dec 11, 2016 3:36 am
Location: Sydney NSW
Contact:

Post by Fausto »

Thank you so much, your generosity is overwhelming.

Can't wait to try this out, my computer and ethernet DMXt device are out for a job, should be back in one week.

A couple of questions:
- any particular reason why is the framerate (10) ? is it related to the way DMX works?
- does dmx.setSlot(number, 2*value); sends (channel, DMXvalue) as for example ch97@254 ?

I am a little bit familiar with the MIDIBus library, however I have been using Processing for less than a year, I have no specific training whatsoever, and usually my coding is very basic.

Here below some code that I am considering implementing to your masterpiece for the purpose of my (at the moment unfinished) interface idea.

Code: Select all

//*********************************  MIDI Methods  ********************************* 

void controllerChange&#40;int channel, int number, int value&#41; &#123; 
  if &#40; dmx != null &#41; &#123; 
    dmx.setSlot&#40;number, 2*value&#41;; // i'd imagine this sends &#40;ch,value&#41; for example ch97@255
  &#125; 
  // useful printout for mapping and coding
  println&#40;"ch&#58;", channel, " n&#58;", number, " v&#58;", value&#41;;
  //
  //I have used this line below in other sketches&#58;
  //cc&#91;number&#93; = map&#40;value, 0, 127, 0, 1&#41;; //mapping the range 0, 127 to 0,1 is probably superfluous, I should rethink this
  //
  //then in draw &#40;&#41;, for example&#58; 
  //parameterX = map&#40;cc&#91;97&#93;, 0, 1, 0, width&#41;;
  //parameterY = map&#40;cc&#91;98&#93;, 0, 1, 0, height&#41;;
  //
  //and before the setup &#40;&#41;&#58; 
  //float cc&#91;&#93; = new float&#91;256&#93;; // Array for MIDI cc
&#125; 
Thank you again for your help.
Fausto
Posts: 33
Joined: Sun Dec 11, 2016 3:36 am
Location: Sydney NSW
Contact:

Post by Fausto »

Hi Claude,

I have just tested your sketch and it worked pretty much first go!
I have implemented your code with few lines here and there, only on the Midibus side of things.

I have a BCR2000 connected has MIDI controller, and my eDMX1 pro connected to my router.
This is the print out I am getting when I launch the sketch:

#
Available MIDI Devices:
----------Input----------
[0] "BCR2000"
[1] "Real Time Sequencer"
----------Output----------
[0] "Gervill"
[1] "BCR2000"
[2] "Real Time Sequencer"
Found address for en0 => 10.0.0.3
Bind to 0.0.0.0
Created dmx interface using: 10.0.0.3 sending to: 10.0.0.255
Found node:Arduino @ /10.0.0.3
Found node:DMXking.com eDMX1 PRO S/N 001A192813ED @ /10.0.0.2
#

(I am not sure what is that found node:Arduino though.)

but it all works great! thank you!!

There's another question I would like to ask you about your LX for Processing library.

How do I output DMX, if I want to use the mouse for example? let's say mouseY mapped 0 to 255 to control the lights intensity. I have tried to work it out, but I got a bit stuck.

I understand that one of the key lines in your code is
dmx.setSlot(number, 2*value);
I also had a look at your SimpleTwoSceneArtnet (which also works great with my setup) but couldn't get my mouse to control channels intensity the way I wanted.
dmx.setSlot(outAddresses, outlevel);

The reason of my question is that I believe that there is a great potential in using Processing visual powerfulness, and channeling it into outputting DMX values.

For example, imagine the classic random walk tutorial, applied to pan and tilt of a moving light.
Or easing mouseX and mouseY values to achieve a smooth pan and tilt (or dimming, or color fades).

I am very happy to be able to use my MIDI controller as one bank lighting desk, but I believe that the greatest potential of using Processing to output DMX would be to actually map Processing variables, functions and visual elements to DMX values.

Let me know your thoughts on this and if you think you can help.

Fausto
admin
Site Admin
Posts: 1643
Joined: Mon Nov 05, 2007 1:26 am
Contact:

Post by admin »

The listing you see is received replies to an Art-Net ArtPoll message. The Art-Net specification says that a controller should reply to its own poll. "Arduino" is the default name of the node that uses the LXForProcessing library. Perhaps that should change to "LXProcessing".

To send DMX, you do two things, set the address/value pairs and then call sendDMX. dmx.setSlot(number, 2*value); sets the address(slot) at "number" to twice the MIDI control change value. This is a simplification because the MIDI is 7 bit (0-127) and DMX is 8bit (0-255). There are other ways to do this. (value << 1) might be better. Or (int)round((value/127.0)*255.0) which is a more complicated way of doing essentially the same thing.

To have your mouse control DMX values, you need to map the mouse coordinates into the range 0-255. The Map function conveniently provides a tool for this.

The key is after you have set the x and y of the mouse into two DMX slots, you have to call sendDMX to actually send the Art-Net packet containing the level information.
Fausto
Posts: 33
Joined: Sun Dec 11, 2016 3:36 am
Location: Sydney NSW
Contact:

Post by Fausto »

...code implemented, and it's all tested and working! (i'm not surprised, I know your library rocks, I'm just very happy!)

Thank you again and immensely for sharing your amazing coding understanding and skills. You wrote & shared the library, and explained the key points that I wanted to explore.

I would like to take this chance for thanking you also for putting together the LX Series, an amazing packaging of softwares that I have been using/testing for my lighting designs for about a year now, and purchased last month without a second thought.
Post Reply