Copying String arguments in OSC

Currently I have a working prototype based on the #lighthack project that has three encoders (for the time being) and 4 buttons. The buttons control "layers" (a local int and switch cases) to determine which parameters are being controlled by the encoder, and what is displayed on the screen. One of these days I'm going to figure out how to use the active wheels to determine the active parameters...

But in the mean time, does anyone know how to copy string type arguments to a local variable? getString returns the number of characters so I dug into the OSC API and I still can't find the right code to use it as a local String to display. 

  • So from what I'm seeing, this uses an index and struct to assign a string corresponding to a parameter to the encoder, but it isn't using anything from the console to determine which string to assign. I want an argument of the OSC message to determine what to parameter is assigned to the encoder.

    Planning to look into using pattern matching from the OSC lib next.

  • The first item of the struct is the parameter name from the console, the second is the name you wont see on display which is optional. The parameter name are fixed, maybe you want do it dynamicly?

  • Which micro controller you use? Teensy? I'm working also on a project with 3 encoders with dynamic parameters.

  • Yes, the plan is to make the parameters dynamic. I'm thinking I'll use Match to compare your struct parameter names with /eos/out/active/wheel/ to determine what encoders are active.

    Currently I'm using an UNO, just because it was what I have available for prototyping; once I've got it working, I plan to move to a Feather M0. I've got a couple of teensy based projects and it is a GREAT board, but I want to see what the Feather can do.

  • /eos/out/active/wheel will get you some part of the way but some of the parameter names don't match to their parameters if you want to control with the parameter rather than the /wheel.  Mixing of the two formats doesn't currently work for anything that would have a space in the name and many of the more complex named parameters.  If you use the/wheel you can get what category that each wheel is in but you are locked to using the wheel number to control the parameter.  If you use the parameter name you can't get the dynamic selected parameters.  It's a bit of a conundrum. You have to choose which part of the puzzle you want and stick with it.

  • With an Arduino UNO you will have no luck because of the limited USB capabilities. Also my code with fixed parameters works on UNO only with some tricks (the ring buffer must increased), the this post community.etcconnect.com/.../would-it-be-possible-to-have-the-encoders-control-the-intensity-and-color-instead-of-pan-tilt

  • Helpful infos, thank you. I will give dynamic parameters a try, I know it will a hard fight. I think if a parameter name send with /eos/out/active/wheel, you must replace the space with an underline, hope this will work.

  • I played a little bit around what is the easiest way to parse the wheel message, so I wrote this code snippet (I used https://coderunnerapp.com to test, so printf doesn't work with Arduino, but the rest should).
    It gives back wheel number, parameter name and value as a string, also the category.
    Next step is to do it for more than one parameter and dynamic storage.

    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    
    char message[] = "/eos/out/active/wheel/12\0\0\0\0,si\0Shutter Strobe [100]\0\0\0\0\0\0\0";
    uint8_t messageSize = sizeof(message);
    const char wheelAddress[] = "/eos/out/active/wheel/";
    
    struct Parameter {
    	uint8_t wheel;
    	char name[64];
    	char value[12];
    	uint8_t category;
    	} parameter;
    
    bool parseWheelMessage(struct Parameter* param,char *msg, int size) {
    	if(strncmp(msg, wheelAddress, 22) == 0) { // check if the OSC message is a wheel message
    		uint8_t valueStartPos;
    		uint8_t valueEndPos;
    		uint8_t parameterStartPos = 28; // 28 is the start position of the paramter name if wheel number < 10
    		
    		char wheelStr[4]; //
    		strncpy(wheelStr, msg + 22, 3); // 22 is the start position of the wheel number inside the message
    		param->wheel = atoi(wheelStr); // convert string to integer
    		if(param->wheel > 9)
    			parameterStartPos = 32; // 32 is the start position of the paramter name if wheel number > 9
    		
    		for (uint8_t i = parameterStartPos; i < (size - 4); i++) { // here we start parsing for the parameter and value
    			if(msg[i] == ' ') msg[i] = '_'; // change spaces to underscore
    			if(msg[i] == '[') valueStartPos = i; // reaching the value open square bracket
    			if(msg[i] == ']') { // reaching the value closing square bracket
    				valueEndPos = i;
    				break; // here we can stop
    				}
    			}
    		strncpy(param->name, msg + parameterStartPos, valueStartPos - parameterStartPos -1);
    		strncpy(param->value, msg + valueStartPos + 1, valueEndPos - valueStartPos - 1); // value inside the square brackets
    		param->category = msg[size] - 48; // ascii to number
    		return true;
    		}
    	return false;		
    	}
    
    int main(int argc, char *argv[]) {
    	message[messageSize] = '2'; // workaround for category in message
    	if(parseWheelMessage(&parameter, message, sizeof(message)) == true) {
    		printf("Wheel %d\n", parameter.wheel);
    		printf("Parameter %s\n", parameter.name);
    		printf("Value %s\n", parameter.value);
    		printf("Category %d\n", parameter.category);
    		}
    
    	while(1) {
    		return 0;
    		}
    	}