/*
* MissingLink Firmware
* Copyright 2011 Jabrudian Industries LLC
*
* MissingLink Firmware is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MissingLink Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MissingLink Firmware. If not, see .
*
*/
#include
#include
#include
#include
#include "Parse.h"
#include "Output.h"
bool getMessageInfo(OSCMessage& oscMess, MessageInfo& mi)
{
const char* addr = oscMess.getOSCAddress();
int addrLen = oscMess.getOSCAddressLen();
if (addrLen <= 0)
return false;
mi.isZ = (addrLen > 2) && (addr[addrLen - 2] == '/') && (addr[addrLen - 1] == 'z');
mi.hasX = ((addr[0] == 'x') || addr[0] == 'X');
mi.hasY = ((addr[0] == 'y') || addr[0] == 'Y');
for (int i = 1; i < addrLen; i++)
{
mi.hasX |= ((addr[i] == 'x' || addr[i] == 'X') && (addr[i-1] != '0'));
mi.hasY |= (addr[i] == 'y' || addr[i] == 'Y');
}
// Make sure this message passes basic checks
// Make sure we've got at least one argument if we're reference it in the message
if ((mi.hasX || mi.isZ) && oscMess.getArgsNum() < 1)
return false;
// Make sure there's a y argument if we're referencing y
if (mi.hasY && oscMess.getArgsNum() < 2)
return false;
return true;
}
uint8_t getTouchArg(OSCMessage& oscMess, uint8_t arg, float fScale, float fOffset)
{
switch( oscMess.getTypeTag(arg) )
{
case 'i':
return oscMess.getInteger32(arg);
break;
case 'f':
{
const float HAXVALUE = 0.9f; // Make sliders in TouchOSC happier
return trunc(oscMess.getFloat(arg) * (fScale+HAXVALUE)) + fOffset;
}
break;
case 's':
default :
return 0xFF;
break;
}
}
int getValue(const char* str, char** numstr, OSCMessage& oscMess)
{
char* currOffset = (char*) str;
float offset = 0.0f;
float scale = 127.0f;
int argIndex = -1;
int whichBits = 0; // 0 = all, 1 = lsb7, 2 = msb7
// Eat whitespace
while ((*currOffset == ' ') || (*currOffset == '_'))
currOffset++;
// Handle constants
if (*currOffset >= '0' && *currOffset <= '9')
{
return strtol(currOffset, numstr, 0);
}
// Handle variables
if (*currOffset == 'x' || *currOffset == 'y' || *currOffset == 'z' ||
*currOffset == 'X' || *currOffset == 'Y' || *currOffset == 'Z')
{
switch (*currOffset)
{
case 'X' :
case 'x' : // first var
argIndex = 0;
break;
case 'Y':
case 'y': // second var
argIndex = 1;
break;
case 'Z' :
case 'z' : // first var for /z messages
argIndex = 0;
break;
}
currOffset++;
if (*currOffset == 'L')
{
whichBits = 1;
currOffset++;
} else {
if (*currOffset == 'M')
{
whichBits = 2;
currOffset++;
}
}
// Check for offset/scale
if (*currOffset == '(')
{
currOffset++; // (
const char* oldOffset = currOffset;
float lowEnd = (float) strtol(currOffset, &currOffset, 0);
// Check for parse issues
if (oldOffset == currOffset)
return 0;
// Skip ".."
currOffset += 2;
// Parse the next param
oldOffset = currOffset;
float highEnd = (float) strtol(currOffset, &currOffset, 0);
if (oldOffset == currOffset)
return 0;
currOffset++; // )
offset = lowEnd;
scale = highEnd - lowEnd;
}
*numstr = currOffset;
int ret = getTouchArg(oscMess, argIndex, scale, offset);
switch (whichBits)
{
case 1 :
return ret & 0x7F;
break;
case 2 :
return (ret >> 7) & 0x7F;
break;
default :
return ret;
break;
}
}
return 0;
}
void sendChunk(const char* inbuffer, const uint8_t inlen, OSCMessage& oscMess)
{
char* currOffset = (char*) inbuffer;
while (currOffset < inbuffer + inlen)
{
cli();
const char* oldOffset = currOffset;
uint8_t val = (uint8_t) getValue(currOffset, &currOffset, oscMess);
if (oldOffset != currOffset)
{
sendByte(val);
} else {
currOffset++;
}
sei();
}
DEBUG_PRINTF("\n");
}