summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/rkt/rkt.c83
1 files changed, 75 insertions, 8 deletions
diff --git a/src/modules/rkt/rkt.c b/src/modules/rkt/rkt.c
index e1a38e7..6fac2c2 100644
--- a/src/modules/rkt/rkt.c
+++ b/src/modules/rkt/rkt.c
@@ -1,5 +1,7 @@
+#include <float.h>
#include <math.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -131,13 +133,29 @@ typedef struct rkt_pipe_t {
til_tap_t tap;
union {
- float f;
- double d;
+ int8_t i8;
+ int16_t i16;
+ int32_t i32;
+ int64_t i64;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ float f;
+ double d;
} var;
union {
- float *f;
- double *d;
+ int8_t *i8;
+ int16_t *i16;
+ int32_t *i32;
+ int64_t *i64;
+ uint8_t *u8;
+ uint16_t *u16;
+ uint32_t *u32;
+ uint64_t *u64;
+ float *f;
+ double *d;
} ptr;
const struct sync_track *track;
@@ -155,9 +173,17 @@ static int rkt_stream_pipe_ctor(void *context, til_stream_t *stream, const void
assert(res_owner_foo);
assert(res_driving_tap);
- if (tap->type != TIL_TAP_TYPE_FLOAT &&
- tap->type != TIL_TAP_TYPE_DOUBLE)
- return 0; /* not interesting to us */
+ if (tap->type == TIL_TAP_TYPE_V2F ||
+ tap->type == TIL_TAP_TYPE_V3F ||
+ tap->type == TIL_TAP_TYPE_V4F ||
+ tap->type == TIL_TAP_TYPE_M4F ||
+ tap->type == TIL_TAP_TYPE_VOIDP)
+ return 0; /* only scalars are interesting to us (for now?) */
+
+ /* TODO: for vector types, rkt /could/ create .{x,y,z,w} suffixed paths
+ * for the individual members... but man would that be some cumbersome stuff
+ * to sequence.
+ */
/* assume pipe ownership, create driving tap and rocket track to stow @ owner_foo */
@@ -224,8 +250,49 @@ static int rkt_pipe_update(void *context, til_stream_pipe_t *pipe, const void *o
*/
val = sync_get_val(rkt_pipe->track, ctxt->rocket_row);
switch (rkt_pipe->tap.type) {
+ /* For *all* integer types, the double must be clamped to the
+ * capacity of the type. Relying on plain truncation isn't safe
+ * since the track data in double form can overflow the integer,
+ * and that's undefined behavior. So it needs to be clamped explicitly
+ * to within the range of the type, while still a double.
+ * From within the range however, plain truncation in the cast to integer
+ * does the right thing, even with negatives. It's unclear to me if
+ * rounding would make sense more often over truncation however. I'm
+ * leaning towards just always doing truncation here, and for taps that
+ * want more explicit control there they should use FLOAT/DOUBLE and convert
+ * to integers on their own with whatever methods they prefer. Even if that
+ * resembles letting Rocket implementation details bleed through to the til_tap
+ * API.
+ */
+#define RKT_CLAMP(_val, _min, _max) \
+ ((_val < _min) ? _min : (_val > _max) ? _max : _val)
+
+ case TIL_TAP_TYPE_I8:
+ rkt_pipe->var.i8 = RKT_CLAMP(val, INT8_MIN, INT8_MAX);
+ break;
+ case TIL_TAP_TYPE_I16:
+ rkt_pipe->var.i16 = RKT_CLAMP(val, INT16_MIN, INT16_MAX);
+ break;
+ case TIL_TAP_TYPE_I32:
+ rkt_pipe->var.i32 = RKT_CLAMP(val, INT32_MIN, INT32_MAX);
+ break;
+ case TIL_TAP_TYPE_I64:
+ rkt_pipe->var.i64 = RKT_CLAMP(val, INT64_MIN, INT64_MAX);
+ break;
+ case TIL_TAP_TYPE_U8:
+ rkt_pipe->var.u8 = RKT_CLAMP(val, 0, UINT8_MAX);
+ break;
+ case TIL_TAP_TYPE_U16:
+ rkt_pipe->var.u16 = RKT_CLAMP(val, 0, UINT16_MAX);
+ break;
+ case TIL_TAP_TYPE_U32:
+ rkt_pipe->var.u32 = RKT_CLAMP(val, 0, UINT32_MAX);
+ break;
+ case TIL_TAP_TYPE_U64:
+ rkt_pipe->var.u64 = RKT_CLAMP(val, 0, UINT64_MAX);
+ break;
case TIL_TAP_TYPE_FLOAT:
- rkt_pipe->var.f = val;
+ rkt_pipe->var.f = RKT_CLAMP(val, FLT_MIN, FLT_MAX);
break;
case TIL_TAP_TYPE_DOUBLE:
rkt_pipe->var.d = val;
© All Rights Reserved