Page 1 of 1

Support for quick "rock'n'roll" shows/busking with

Posted: Mon Oct 24, 2016 8:35 am
by freadZdead
Hi Claude,


It has been a while, and I have followed the various improvements that have come through - great stuff as always.

The following request goes towards greater speed/convenience/updatability when it comes to working with movers and EFX in "busking" situations, i.e. minimal plot/setup time, again potentially touring and thus important that specifically the movers can be quickly re-adjusted to the new environment.

Dynamic Defined Values/Pallettes? Or just expanding the dynamic group recording?

Premise
While it is fine to work with Defined Values, the downfall is that when you use them, they are "hard-coded" as subchannel DMX values into individual cues, which becomes tedious if you want to re-use these and then change them later with the goal to track this change through the entire show. Not necessarily a biggy with colour perhaps, but really likely to happen when working with positional values, where you want to be able to easily record, update and use what some boards call Focus Points (others Position Pallettes).

In the past, you have implemented the use of dynamic groups using "G" in cues, which is already quite good. Remind me, was there any way of when recording a group to already give it a recording Mask? Scenario would be -

1. I set my 6 movers to full
2. I grab each one individually (sidenote - is there a "next/all" button that cycles to the current channel selection one by one while remembering the whole group, so that with the "all" you could then select all six again?), and pan/tilt/zoom/focus until I am happy
3. I select those 6 movers again and then press what I believe might not be in existence yet - i.e. "r(ecord) g(roup) 1 p(osition)b(eam)" or even "n(on-intensity subchannels)", only including what is on my "whitelist" of subchannels for this group? Kind of like the window you have in groups to unmark channels. At the moment, safe from setting the relevant intensities at zero AND unmarking the channels, it is a clunky process as you then have to go into the groups to delete the intensities out of it...

Functional movement&effect patterns

Particularly for movers It would be great to define effects not just as step based but as formulas (to achieve something like sawtooth, circles, randomness in movement), i.e.:
x = time, scalable with EFXRate
pan = base_pan + sin(x)*size_pan (sizes being new parameters, ideally controllable in the way that EFXRate is)
tilt = base_tilt + cos(x)*size_tilt
It would be interesting to think how one could come up with a good way of (re-)using base/focuspoints that were discussed above - i.e. using positional values from a dynamic group would be great, if they exist for a fixture?

MiB / Move in Black

It would be great to have a more intuitive/less chatty/more dynamic control of how/when non-intensity values fade... i.e.

1. I have a cue 0.5 which is just a blackout
2. In cue 1, I have the movers in a mixture of red and blue, and pointed at my dynamic focus point (maybe from a G_roup that is included).
3. What would be great would be having a way to "mark" cue 1 to require "Move in Black". If this happens, in its simplest form it would mean that dynamically (without programming these into cue 0.5), all non-intensity sub-channels get set in cue 0.5, just after cue 0.5's own fade is complete, and only intensities get faded in cue 1.
4. Obviously, this does not take into account if i.e. some or all of the fixtures are actually with an intensity greater than 0 in cue 0.5 - thus making the move visible again. But as a start, what is described in 3. should help enormously in simplifying the bid to avoid "live moves" where possible without employing more tedious/deliberate features like part cues and the likes. Fully acknowledging of course that if somebody should jump from another cue other than having executed 0.5 prior will still see live changes.


I hope these features make sense and don't seem like mere indulgence. I believe that this combined packet would go a long way of making LXConsole (in its otherwise undisputed greatness) a preferred choice for me when it comes to more complex shows with movers etc, as it would speed up the efficiency of programming greatly.

What do you think?

Posted: Mon Oct 24, 2016 8:02 pm
by admin
To record only selected channels into a group press [a] [g] then the group number followed by [enter]. [a] expands to "@" When following @, [g] expands to "record group:".

Assume your six movers are channels 11, 13, 15, 17, 19, and 21. Lets say you have recorded their intensity into group 11. You can turn them all on using [g] [1] [1] [f]
which is group:11@100.

Now you proceed as described to place the six movers into locations that you want to record (just the pan and tilt perhaps) into group 12. Select all six channels by clicking on them individually in the main display. The command line should read 11&13&15&17&19&21. Press [a] [g] [1] [2] The command line should read 11&13&15&17&19&21@record group:12. Press [enter]. If the selected channels have more than an intensity subchannel, you will be presented with the option of recording only certain subchannels into the group. Assuming that you select only pan and tilt, group 12 will contain only the pan and tilt of the selected channels, regardless of pan and tilt of any other channels or any other levels at all.

More or less completely separate from the meaning of a group as used above, there is a column in the channel table labeled "Group". This functions as a label for the general function of channels. However, it also has a shortcut purpose. If you hold down the option key while clicking on any channel with a labeled group name, all other channels with the same group name are selected. Continuing the above example, assume that channels 11,13,15,17,19 and 21 have the name "movers" in the group column of the channels table. Then, selecting all six is simply a matter of holding down the option key and clicking on any one of the six channels.

The move in black type function is found in the channel menu and is called Delay Hilited Channels or Delay Channels. These commands create a new part to a cue that delays its time until the main part of the cue is finished running. The net result is the same as if you created an auto-following cue that changed the colors or pan/tilt positions after the first cue faded the intensity to black. Except that this is contained within parts of the same cue rather than being a separate cue. You can set the default move time for automatically created delayed parts in the Setup window.

Function based effects have been mentioned before. They are on the list of future features.

Posted: Tue Oct 25, 2016 12:26 pm
by freadZdead
Thanks Claude,

I'll give this a whirl...

On another note, theoretically speaking, do you think that via external or internal applescripts, and/or by sending i.e. osc, I could be able to control movers with a programmed effect like the one mentioned in a performant and stable way?

Posted: Sat Oct 29, 2016 3:09 pm
by freadZdead
Hey Claude,


I have tried to set this up via external means (Quartz Composer acting as LFO generator and OSC Sender/Receiver) for a relative, positional effect on a mover, with some limited success.

Here some observations and speed bumps:

1. What I am after is a positional effect relative to the current position, i.e. a "base point" - defined as any positional data for this fixture coming from within LX Console (as affected by LXConsole Effects, Cues, Programmer).

2. If there could be an OSC address for fixtures to accept offsetting "live" data (that would be by definition ephemeral, non-recordable, i.e. say in addition to the existing CCPan a CCLivePan etc), and if these Livehooks could in fact be treated as being additive to the existing LXConsole subchannel data, then that would mean I could easily send an external relative effect to a group of fixtures rather than individual fixtures...

Let's imagine:

- I have three fixtures, 51, 53, 55, each set to a specific basepoint, say i.e. by a cue. They all belong to group 4.

- I have my external effect setup, and it sends i.e. a sine wave with an amplitude of 0.1 to CCLivePan, and a cosinus wave with an amplitude of 0.2 to CCLiveTilt via OSC to group 4.

- The effect is that all three fixtures describe circles around their respective base point, as their CCPan and CCTilt adds the (sometimes negative, sometimes positive) external data.

- This could show up with a similar or same look and feel like a QLab internal effect would in the Channel Table and in the Channel Controls (or with a different colour), but if I were to hit record, this external data would NOT be recorded.

- Optional it would be great to get additional OSC out hooks (say CCPan also gets CCLivePan) that allow you to choose between either receiving data that incorporates the external effect piled on or the LXConsole internal data (neglecting what comes from the outside).

With those extra OSC hooks, I could realize quite effective external effects - is this a possibility, and would it be preferable to you over adding on to the existing effects engine?

One thing I noted though is that, using the latest build, the speed of LXConsole Abending seems to be directly related to the speed of the OSC sender patch in Quartz Composer - something like a buffer of received OSC Commands being overrun? this is admittedly in the crude commandline form, i.e. I am sending 25 times per second one command each of /cmd.lxconsole/CCPan and /cmd.lxconsole/CCTilt. Report in the next post.

Error Report

Posted: Sat Oct 29, 2016 3:12 pm
by freadZdead

Code: Select all

Crash report removed as to not clutter the forum

Posted: Sat Oct 29, 2016 3:14 pm
by freadZdead

Code: Select all

 Crash report removed as to not clutter the forum

Posted: Tue Nov 08, 2016 1:13 pm
by freadZdead
Hi Claude,

Any thoughts on the error - i.e. does that have to do with potentially having to throttle OSC message input? And/or is it an accumulative effect?

And what do you think about the live offset mechanism described above?

Thanks for contemplating/sharing your thoughts.

Posted: Tue Nov 08, 2016 4:47 pm
by admin
Just posting a crash report without explanation does not really tell much. Occasionally a crash report will directly point out an error. That's rare. More often, all the crash report indicates is that the application crashed in a place that it shouldn't have. But what led to that circumstance is anyone's guess. That's why the need for some sort of elaboration and not just the crash report.

The forum is meant to be a place where people can come to find information because it is possible that someone else has already had the same question and it has been answered. A crash report is better sent directly because it does not provide useful information to anyone searching the forum. Its better to post the steps that led to a crash and follow up with an e-mail of the crash report. That way others can benefit (but not be confused or have to wade through information that is largely meaningless to them).

Its not even clear that the crash report in this thread relates to the original post. (Occasionally people tack on to an existing thread with an unrelated question).

In answer to your question about OSC, there's no reason why that shouldn't work. It is possible to send so many OSC messages that LXConsole will get behind processing them. That is not likely to result in a crash, only in messages getting dropped and the interface lagging quite a bit. As a practical matter, more messages are not necessarily better and useful. Messages that update a channel at a rate that exceeds the maximum DMX rate of ~40 times a second are superfluous. Above 40/sec, updates are just wasting bandwidth.

OSC is probably better than trying to write external controls using AppleScript. There's significant overhead to AppleScript that does not lend itself to time sensitive functions. It is quite possible to send OSC to LXConsole from something like MAX or Processing which, especially the latter, should allow you to experiment with what you are trying to do.

Posted: Tue Nov 08, 2016 9:25 pm
by freadZdead
Thanks Claude,

All that makes sense, and will keep that in mind going forward.

Re: The crashes

The crash report related to the original post in that it was trying to achieve live effects (in this case through external programs) for busking shows, and in the course of this, LXConsole repeatedly crashed, which it rarely has done for me, with the speed of the crash relating directly to the update rate of sending OSC messages to LXConsole. While it took longer for the crashes to happen, it did happen with as little as 15 updates per second.

In terms of steps leading up to the crash, what I failed to mention is that currently, the updates are sent as /cmd.lxconsole/CCPan ; would it be better to look at a different way of setting the parameters rather than command line?

Re: the suggested addition

Finally, the biggest question I have relates to the suggested addition of OSC hooks that would be treated ephemeral, incremental live values (EILVs), i.e. /g1/EILVPan (to select all channels in group 1) or /EILVTilt (for selected channels) - these would be
  • * non-recordable into cues,groups,subs,
    * incremental/decremental to existing values in LX Console, but excluding in this any previous EILVs (so strictly overwriting previous EILVs)
Is this something you would consider?

Posted: Wed Nov 09, 2016 10:41 pm
by admin
The crash was the result of a multi-thread conflict where the interface was trying to update at the same time as incoming OSC was telling the channel controls to change. This should be fixed in the latest build 4.6.5.

LXConsole 4.6.5 is a latest build that also includes Art-Net 3 support. This may change the DMX Out settings required. To continue to broadcast Art-Net, both the "Send to address" and "Set to broadcast" boxes need to be checked. Do not use this version for a currently running production. Allow time to evaluate it for your specific use.

This has been tested with the following code for Processing which may serve as a guide for constructing dynamic controls through OSC:

Code: Select all

/*
   Example for testing OSC control of LXConsole.
   Copyright 2016 Claude Heintz Design
   For license see https://www.claudeheintzdesign.com/lx/opensource.html
*/
import java.net.*;
// requires LXforProcessing library
// https://github.com/claudeheintz/LXforProcessing
import lx4p.*;

// edit the target IP and port for outgoing OSC
String targetAddressString = "127.0.0.1";
int udpPort = 7699;

// adjust these values to modify effect
// period is total time of the cycle in seconds
float period = 10.0f;
// pan_center is the center of the pan channel in 0.0-1.0 rather than percent
double pan_center = 0.5;
// pan_range is how far (0.0-1.0) above and below the pan value travels
double pan_range = 0.1;
// tilt_center is the center of the pan channel in 0.0-1.0 rather than percent
double tilt_center = 0.5;
// tilt_range is how far (0.0-1.0) above and below the tilt value travels
double tilt_range = 0.06;

//variables to hold intermediate values used to calculate the final pan and tilt
double pan_value;
double tilt_value;
long time_start;
double time_elapsed;
double progress;
double angle_progress;
double sin_progress;
double cos_progress;

// interface and network variables
LXPVScrollbar sb, sb2, sb3;
DatagramSocket mysocket;
InetAddress target = null;
byte[] _packet_buffer = new byte[100];

// **************************** setup ****************************
void setup() {
  size(500,500);
  sb = new LXPVScrollbar(30,10,24,150,1);
  sb2 = new LXPVScrollbar(60,10,24,150,1);
  sb3 = new LXPVScrollbar(90,10,24,150,1);
  
  try {
    target = InetAddress.getByName(targetAddressString);
    mysocket = new DatagramSocket( null );
    mysocket.setReuseAddress(true);
    mysocket.bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), udpPort));
    mysocket.setSoTimeout(30);
    mysocket.setBroadcast(true);
  } catch (Exception e) {
    System.out.println("oops socket exception" + e);
  }
  
  time_start = System.currentTimeMillis();
}

// **************************** draw ****************************
void draw() {
  // convert elapsed time into 0.0-1.0 progress value
  time_elapsed = (System.currentTimeMillis() - time_start)/1000.0;
  progress = (time_elapsed % period) / period;
  
  //convert progress into sin and cos 
  angle_progress = progress * Math.PI * 2;    // convert v to 0-90 in radians
  sin_progress = Math.sin(angle_progress);   // 0 to 1 to 0
  cos_progress = Math.cos(angle_progress);   // 1 to 0 to -1;
  // apply to pan and tilt to oscillate in a range centered on a value
  // instead of percentage, these values are 0.0-1.0 which is how the argument
  // is going to be added to the OSC message
  pan_value = (pan_center + pan_range*sin_progress);
  tilt_value = (tilt_center + tilt_range*cos_progress);
  
  // set the values of the three scroll bars
  sb.setValue( (int)(127*(sin_progress+1)) );
  sb2.setValue((float)pan_value);
  sb3.setValue((float)tilt_value);
  
  // send a bunch of channels plus pan and tilt in the channel controls window
  for &#40;int j=0; j<40; j++&#41; &#123;
    String f = Integer.toString&#40;j+1&#41;;
    sendOSC&#40;"/cmd.lxconsole/" + f + "@%p", &#40;float&#41;&#40;sb.getValue&#40;&#41;/255.0&#41;&#41;;
  &#125;
  sendOSC&#40;"/cmd.lxconsole/CC2", &#40;float&#41;&#40;sb2.getValue&#40;&#41;/255.0&#41;&#41;;
  sendOSC&#40;"/cmd.lxconsole/CC4", &#40;float&#41;&#40;sb3.getValue&#40;&#41;/255.0&#41;&#41;;
 
  // update the processing interface, redrawing the scroll bars
  sb.update&#40;this&#41;;
  sb.draw&#40;this&#41;;
  sb2.update&#40;this&#41;;
  sb2.draw&#40;this&#41;;
  sb3.update&#40;this&#41;;
  sb3.draw&#40;this&#41;;
&#125;

// **************************** sendOSC ****************************

public void sendOSC &#40; String address, float value &#41; &#123;
    if &#40;&#40; mysocket != null &#41; && &#40; target != null&#41;&#41; &#123;
      // create an OSC message and add a floating point argument
      LXOSCMessage msg = new LXOSCMessage&#40;address&#41;;
      msg.addArgument&#40;value&#41;;
      
      // transfer message to packet/bytes
      int osc_packet_length = msg.addOSCMessageToBytes&#40;_packet_buffer&#41;;
      if &#40; osc_packet_length <= 0 &#41; &#123;
        return;
      &#125;
      // send the message/packet
      try &#123;
        DatagramPacket sendPacket = new DatagramPacket&#40;_packet_buffer, osc_packet_length, target, udpPort&#41;;
        mysocket.send&#40;sendPacket&#41;;
      &#125; catch &#40; Exception e&#41; &#123;
        System.out.println&#40;"send osc exception " + e&#41;;
      &#125;
    &#125;
  &#125;