Coding with CITP

A friend of mine asked about using CITP with openframeworks. Here is a quick overview of how to use CITP in your own application.

CITP and a subset of it called MSEX are used to communicate between a lighting desks, mediaservers and 3D visualizers. The two most common uses are transferring media thumbnails to a lighting desk from a mediaserver and showing the output of a mediaserver on a lighting desk or 3D visualizer.

The very first thing you should do when starting to code a application is to get the CITP standard. You can find it at http://www.citp-protocol.org/viewtopic.php?f=1&t=241

Another thing that helped me a lot while coding was to use wireshark to sniff the traffic between a lighting desk and a mediaserver. Comparing this real world data to the standard gives a nice insight into how the protocol works. It also quickly showed that in the real world devices don’t necessarily follow the standard. Without wireshark it’s pretty much impossible to pinpoint the fault in these nonstandard situations.

You should also be familiar with both UDP and TCP networking as both are used by CITP/MSEX. Multithreading is also needed.

The issues I banged my head against the most were

  • nonstandard implementations
  • UCS2 strings
  • bit offsets in sending stuff

 

Nonstandard implementationsa

I was developing a media server. The standard says the following about choosing a tcp port for the mediaserver to listen on

1.4 Media server behaviour

TCP listening socket on any (known) port:
­ Accept incoming connections from any lighting console or visualizer. If the media server can only handle a limited number of simultaneous

connections then it should actively refuse any further connection attempts.

Datagram (UDP) socket, port 4809, joined to multicast address 224.0.0.180:
­ Regularly send a CITP/PINF/PLoc message containing the port on which the listening socket is listening.

So the idea is that a mediaserver send a UDP packet to a multicast address that tells the lighting desk which port the mediaserver is listening on. After a while I realized that MagicQ doesn’t listen to the Ploc message and instead it tries to connect to port 4811 (which is pretty much the default port) and if that fails then 4814. So to get your mediaserver to work with MagicQ you need to set the mediaserver TCP port to 4811. My code is from september 2014, so things might not be this way anymore these days, but that’s how they were back then. MagicQ didn’t give any error messages but with wireshark it was very easy to see that it was trying to connect to port 4811 and failing because no one was listening there.

 

UCS2 strings

This is another thing that took ages to figure out. There are some strings that are supposed to be sent as UCS2. Converting UTF8 strings to UCS2 and getting the right output sounded easy but in practice was very hard.

 

2.1 Data types
All fields of CITP messages use little endian byte order (least significant byte first, “PC standard”).

ucs1, ucs2  // 8‐bit and 16‐bit unicode characters (character types correspond to uint8 and uint16)

Open arrays of ucs1 or ucs2 are null terminated strings.

 

What this means in the real world is that sending “Hello” should look like 00 68 00 65 00  6c 00 6c 00 6f. So it’s pretty much just ascii but padded with 00 before each character. This is very obvious when looking the output of wireshark.

 

Bit offsets

The standard defines the length of different fields very clearly. While coding I always seemed to end up with one or two bytes too much. Valgrind was a very good tool to figure these out http://www.valgrind.org/info/

I kept a log of useful commands and this is one I used a lot

g++ -g program -o <program name> && valgrind –tool=memcheck –trace-origins <program name>

 

The rest of this post is pieces of information and links that might be useful to you when developing a app that uses CITP/MSEX

Zip file of my code for a unfinished mediaserver

Some documentation on how to get results with different lighting consoles

My post on OpenFrameworks.cc with some more tips

A excellent project by jwarwick (not me) to get a grasp what coding for CITP looks like.

Another good source of examples. This one is by a spanish guy. I forked the repo to save the code from vanishing

I hope this has helped you get some ideas on how to make your application support CITP