Some fixes, formatting

main
Jurij Podgoršek 2024-09-03 15:03:08 +02:00
parent fc469e0fa3
commit 5a764293fc
1 changed files with 118 additions and 147 deletions

View File

@ -23,12 +23,10 @@ SLIPDecoder {
// Buffer for OSC bundles/messages // Buffer for OSC bundles/messages
const bufferSize = 4096; const bufferSize = 4096;
var <>deviceName, <>rate, <>prepend, <port, decode, trace, stop, <reader; var <>deviceName, <>rate, <>prepend, <port, <>trace = false, <running = false, <reader;
*new { |deviceName="/dev/ttyUSB0", rate=115200, prepend=""| *new { |deviceName="/dev/ttyUSB0", rate=115200, prepend=""|
deviceName.postln; ^super.newCopyArgs(deviceName, rate, prepend);
//^super.newCopyArgs(deviceName, rate, prepend).init;
^super.newCopyArgs(deviceName, rate, prepend);//.init;
} }
readInt32 { |byteArr| readInt32 { |byteArr|
@ -43,22 +41,19 @@ SLIPDecoder {
// Return array [string, strlen (bytes)] // Return array [string, strlen (bytes)]
readNextString { |byteArr| readNextString { |byteArr|
var str = "", idx = 0; var str = "", idx = 0;
while({ (idx + 4) <= byteArr.size }, while({ (idx + 4) <= byteArr.size }, {
{ str = str ++ String.newFrom(
str = str ++ String.newFrom( byteArr[(idx..(idx + 3))]
byteArr[(idx..(idx + 3))] .removeEvery([0, nil])
.removeEvery([0]) .collect({|x| x.asAscii})
.collect({|x| x.asAscii}) );
);
// If last byte is null, return // If last byte is null, return
if ( isNil(byteArr[idx + 3]) || (byteArr[idx + 3] == 0), { if ( isNil(byteArr[idx + 3]) || (byteArr[idx + 3] == 0), {
^[str, idx + 4] ^[str, idx + 4]
}); });
idx = idx + 4;
idx = idx + 4; });
}
);
// If end of byteArr, return // If end of byteArr, return
^[str, idx]; ^[str, idx];
@ -68,175 +63,151 @@ SLIPDecoder {
// ce je stevilo, v razponu crk, stevk in znakov, vrni char, sicer kar cifro // ce je stevilo, v razponu crk, stevk in znakov, vrni char, sicer kar cifro
if (x.isInteger && (x >= 0x20) && (x <= 0x7E), if (x.isInteger && (x >= 0x20) && (x <= 0x7E),
{ ^x.asAscii }, { ^x.asAscii },
{ ^x }) { ^x }
);
} }
init { init {
"init".postln;
dump(this);
deviceName.postln;
rate.postln;
port = SerialPort(deviceName, rate); port = SerialPort(deviceName, rate);
trace = false;
stop = false;
"init done".postln;
}
trace { |val|
trace = val;
val;
} }
traceMsg { |...msg| traceMsg { |...msg|
if (trace, { "> ".post; msg.join(' ').postln; }); if ((trace), { "> ".post; msg.join(' ').postln; });
} }
// Function for decoding the properly-SLIP-decoded message. // Function for decoding the properly-SLIP-decoded message.
decode { |data| decode { |data|
// Is it a bundle? (read header from first 8 bytes)
var header = data.at((0..7)); var header = data.at((0..7));
if (header == oscBundleHeader, // Is it a bundle? (read header from first 8 bytes)
if ((header == oscBundleHeader), {
// OSC bundle // OSC bundle
{ var nextMsgLen, nextMsgStart, nextMsgEnd, bundlePart;
var timetag, nextMsgLen, nextMsgStart, nextMsgEnd, bundlePart; this.traceMsg("BUNDLE");
this.traceMsg("BUNDLE"); // Next 8 bytes are a time tag (or null)
/* @TODO handle timetags!
var timetag = data.at((8..15));
*/
// Next 8 bytes are a time tag (or null) // First message starts after the time tag
/* @TODO handle timetags! nextMsgStart = 16;
timetag = data.at((8..15));
*/
// First message starts after the time tag // Loop for each message
nextMsgStart = 16; while({ nextMsgStart < data.size }, {
// Further 4 bytes hold the next message length
nextMsgLen = this.readInt32(data.at((nextMsgStart..(nextMsgStart + 3))));
nextMsgStart = nextMsgStart + 4;
nextMsgEnd = min(nextMsgStart + nextMsgLen - 1, data.size - 1);
bundlePart = data.at((nextMsgStart..nextMsgEnd));
// Loop for each message // Recursively decode; each bundle part can be another bundle
while({ nextMsgStart < data.size }, this.decode(bundlePart);
{
// Further 4 bytes hold the next message length
nextMsgLen = this.readInt32(data.at((nextMsgStart..(nextMsgStart + 3))));
nextMsgStart = nextMsgStart + 4;
nextMsgEnd = nextMsgStart + nextMsgLen - 1;
bundlePart = data.at((nextMsgStart..nextMsgEnd));
// Recursively decode; each bundle part can be another bundle nextMsgStart = nextMsgEnd + 1;
this.decode(bundlePart); });
}, {
nextMsgStart = nextMsgEnd + 1;
}
);
},
// OSC message // OSC message
{ var nextString, index, address, type, args = [];
var nextString, index, address, type, args = [];
// Message Address // Message Address
nextString = this.readNextString(data); nextString = this.readNextString(data);
address = nextString[0]; address = nextString[0];
data = data[(nextString[1]..(data.size - 1))]; data = data[(nextString[1]..(data.size - 1))];
nextString = this.readNextString(data); nextString = this.readNextString(data);
type = nextString[0]; type = nextString[0];
data = data[(nextString[1]..(data.size - 1))]; data = data[(nextString[1]..(data.size - 1))];
type.do({ |t| type.do({ |t|
t.switch ( t.switch (
$i, { $i, {
args = args.add(this.readInt32(data)); args = args.add(this.readInt32(data));
data = data[(4..(data.size - 1))]; data = data[(4..(data.size - 1))];
}, },
$f, { $f, {
args = args.add(this.readFloat32(data)); args = args.add(this.readFloat32(data));
data = data[(4..(data.size - 1))]; data = data[(4..(data.size - 1))];
}, },
$s, { $s, {
nextString = this.readNextString(data); nextString = this.readNextString(data);
args = args.add(nextString[0]); args = args.add(nextString[0]);
data = data[(nextString[1]..(data.size - 1))]; data = data[(nextString[1]..(data.size - 1))];
} }
/* @TODO implement strings, bytearrays */ /* @TODO implement strings, bytearrays */
); );
}); });
this.traceMsg("OSC", prepend ++ address, args); this.traceMsg("OSC", prepend ++ address, args);
// Send OSC message to the engine // Send OSC message to the engine
NetAddr.localAddr.sendMsg(prepend ++ address, *args); NetAddr.localAddr.sendMsg(prepend ++ address, *args);
} });
);
} }
start { start {
this.traceMsg("Starting..."); this.traceMsg("Starting...");
dump(this); if ((port == nil), {this.init;});
// TODO fix restart if (port.isOpen.not, {this.init;});
if ((port == nil), {this.init;});
if (port.isOpen.not, {this.init;});
this.traceMsg("opened"); this.traceMsg("opened");
running = true;
reader = fork { reader = fork {
var serialByte, buffer, firstRead; var serialByte, buffer, firstRead;
firstRead = true; firstRead = true;
// Skip data before the first END character // Skip data before the first END character
while({stop.not && firstRead}, { while({running && firstRead}, {
serialByte = port.read; serialByte = port.read;
//this.traceMsg("Read byte"); //this.traceMsg("Read byte");
//this.traceMsg(serialByte.asAscii); //this.traceMsg(serialByte.asAscii);
if (serialByte == slipEND, { if (serialByte == slipEND, {
buffer = Int8Array(maxSize: bufferSize); buffer = Int8Array(maxSize: bufferSize);
firstRead = false; firstRead = false;
}, { }, {
//this.traceMsg("Skip...") this.traceMsg("Skip...")
}); });
}); });
// Start reading data // Start reading data
this.traceMsg("First read!"); this.traceMsg("First read!");
while({stop.not}, { while({running}, {
serialByte = port.read; serialByte = port.read;
//this.traceMsg("Checking", serialByte.asInteger, serialByte.asAscii); //this.traceMsg("Checking", serialByte.asInteger, serialByte.asAscii);
serialByte.switch( serialByte.switch(
// on END, decode buffer // on END, decode buffer
slipEND, { slipEND, {
//this.traceMsg("SLIP END, decoding "); //this.traceMsg("SLIP END, decoding ");
//this.traceMsg(buffer); //this.traceMsg(buffer);
//3.wait; //3.wait;
if (buffer.isEmpty.not, { if (buffer.isEmpty.not, {
this.traceMsg("decode!", buffer); this.traceMsg("decode!", buffer);
this.decode(buffer); this.decode(buffer);
buffer = Int8Array(maxSize: bufferSize); buffer = Int8Array(maxSize: bufferSize);
}); });
}, },
slipESC, { slipESC, {
serialByte = port.read; serialByte = port.read;
serialByte.switch( serialByte.switch(
slipESC_END, { slipESC_END, { buffer.add(slipEND) },
//this.traceMsg("SLIP ESC and ESC_END"); slipESC_ESC, { buffer.add(slipESC) },
buffer.add(slipEND) {"SLIP encoding error.".error }
}, );
slipESC_ESC, { }, {
//this.traceMsg("SLIP ESC and ESC_ESC"); // Otherwise just add the byte
buffer.add(slipESC) //this.traceMsg(buffer);
}, buffer.add(serialByte);
{"SLIP encoding error.".error } });
); });
}, };
{
// Otherwise just add the byte
//this.traceMsg(buffer);
buffer.add(serialByte);
});
});
};
} }
stop { stop {
this.traceMsg("Stopping..."); this.traceMsg("Stopping...");
stop = true; running = false;
port.close; port.close;
this.reader.free;
} }
} }