error handling
s-ol
2 years ago
4 | 4 | |
5 | 5 | const param_prefix = "/param/"; |
6 | 6 | |
7 | fn set_array(comptime T: type, dest: []T, argc: c_int, argv: [*c][*c]c.lo_arg) void { | |
8 | std.debug.assert(argc == dest.len); | |
7 | fn verify_args(expected: u8, got: []const u8) !void { | |
8 | for (got) |typ| { | |
9 | if (typ != expected) | |
10 | return error.typeMismatch; | |
11 | } | |
12 | } | |
13 | ||
14 | fn set_array(comptime T: type, dest: []T, argc: c_int, argv: [*c][*c]c.lo_arg, types: []const u8) !void { | |
15 | if (argc != dest.len) | |
16 | return error.sizeMismatch; | |
17 | ||
9 | 18 | switch (T) { |
10 | 19 | f32 => { |
20 | try verify_args('f', types); | |
11 | 21 | for (dest) |*v, i| |
12 | 22 | v.* = argv[i].*.f; |
13 | 23 | }, |
14 | 24 | f64 => { |
25 | try verify_args('d', types); | |
15 | 26 | for (dest) |*v, i| |
16 | 27 | v.* = argv[i].*.d; |
17 | 28 | }, |
18 | 29 | i32 => { |
30 | try verify_args('i', types); | |
19 | 31 | for (dest) |*v, i| |
20 | 32 | v.* = argv[i].*.i; |
21 | 33 | }, |
22 | 34 | u32 => { |
23 | for (dest) |*v, i| | |
35 | try verify_args('i', types); | |
36 | for (dest) |*v, i| { | |
37 | const val = argv[i].*.i; | |
38 | if (val < 0) | |
39 | return error.signDisallowed; | |
24 | 40 | v.* = @intCast(u32, argv[i].*.i); |
41 | } | |
25 | 42 | }, |
26 | else => {} | |
43 | else => return error.invalidType, | |
27 | 44 | } |
28 | 45 | } |
29 | 46 | |
31 | 48 | server: c.lo_server, |
32 | 49 | cache: *gl.UniformCache, |
33 | 50 | |
34 | pub fn init(allocator: *std.mem.Allocator, config: cfg.OSCConfig, cache: *gl.UniformCache) !*ControlServer { | |
51 | pub fn init( | |
52 | allocator: *std.mem.Allocator, | |
53 | config: cfg.OSCConfig, | |
54 | cache: *gl.UniformCache, | |
55 | ) !*ControlServer { | |
35 | 56 | var self: *ControlServer = try allocator.create(ControlServer); |
36 | ||
37 | 57 | self.cache = cache; |
38 | 58 | |
39 | 59 | switch (config) { |
47 | 67 | else => unreachable, |
48 | 68 | }; |
49 | 69 | |
50 | std.debug.warn("listening for OSC messages on {} port {}\n", .{ conf.protocol, conf.port }); | |
70 | std.debug.warn( | |
71 | "listening for OSC messages on {} port {}\n", | |
72 | .{ conf.protocol, conf.port }, | |
73 | ); | |
51 | 74 | self.server = c.lo_server_new_with_proto(port[0..], proto, handle_error); |
52 | 75 | }, |
53 | 76 | .URL => |url| { |
73 | 96 | } |
74 | 97 | |
75 | 98 | fn handle_error(num: c_int, msg: [*c]const u8, where: [*c]const u8) callconv(.C) void { |
76 | std.debug.warn("OSC error {} @ {s}: {s}\n", .{ num, @ptrCast([*:0]const u8, where), @ptrCast([*:0]const u8, msg) }); | |
99 | std.debug.warn( | |
100 | "OSC error {} @ {s}: {s}\n", | |
101 | .{ num, @ptrCast([*:0]const u8, where), @ptrCast([*:0]const u8, msg) }, | |
102 | ); | |
77 | 103 | } |
78 | 104 | |
79 | fn handle_method(_path: [*c]const u8, _types: [*c]const u8, argv: [*c][*c]c.lo_arg, argc: c_int, msg: c.lo_message, userdata: ?*c_void) callconv(.C) c_int { | |
105 | fn set_uniform( | |
106 | self: *ControlServer, | |
107 | uniform_name: []const u8, | |
108 | argv: [*c][*c]c.lo_arg, | |
109 | argc: c_int, | |
110 | types: []const u8, | |
111 | ) !void { | |
112 | var buffer: [256]u8 = undefined; | |
113 | std.mem.copy(u8, buffer[0..], uniform_name); | |
114 | buffer[uniform_name.len] = 0; | |
115 | const name = buffer[0 .. uniform_name.len + 1]; | |
116 | const uniform = (try self.cache.get(name)) orelse return error.notFound; | |
117 | ||
118 | try switch (uniform.value) { | |
119 | .FLOAT => |*val| set_array(f32, @ptrCast([*]f32, val)[0..1], argc, argv, types), | |
120 | .DOUBLE => |*val| set_array(f64, @ptrCast([*]f64, val)[0..1], argc, argv, types), | |
121 | .INT => |*val| set_array(i32, @ptrCast([*]i32, val)[0..1], argc, argv, types), | |
122 | .UNSIGNED_INT => |*val| set_array(u32, @ptrCast([*]u32, val)[0..1], argc, argv, types), | |
123 | .BOOL => |*val| set_array(u32, @ptrCast([*]u32, val)[0..1], argc, argv, types), | |
124 | .FLOAT_VEC2 => |*val| set_array(f32, val[0..], argc, argv, types), | |
125 | .FLOAT_VEC3 => |*val| set_array(f32, val[0..], argc, argv, types), | |
126 | .FLOAT_VEC4 => |*val| set_array(f32, val[0..], argc, argv, types), | |
127 | .DOUBLE_VEC2 => |*val| set_array(f64, val[0..], argc, argv, types), | |
128 | .DOUBLE_VEC3 => |*val| set_array(f64, val[0..], argc, argv, types), | |
129 | .DOUBLE_VEC4 => |*val| set_array(f64, val[0..], argc, argv, types), | |
130 | .INT_VEC2 => |*val| set_array(i32, val[0..], argc, argv, types), | |
131 | .INT_VEC3 => |*val| set_array(i32, val[0..], argc, argv, types), | |
132 | .INT_VEC4 => |*val| set_array(i32, val[0..], argc, argv, types), | |
133 | .UNSIGNED_INT_VEC2 => |*val| set_array(u32, val[0..], argc, argv, types), | |
134 | .UNSIGNED_INT_VEC3 => |*val| set_array(u32, val[0..], argc, argv, types), | |
135 | .UNSIGNED_INT_VEC4 => |*val| set_array(u32, val[0..], argc, argv, types), | |
136 | .BOOL_VEC2 => |*val| set_array(u32, val[0..], argc, argv, types), | |
137 | .BOOL_VEC3 => |*val| set_array(u32, val[0..], argc, argv, types), | |
138 | .BOOL_VEC4 => |*val| set_array(u32, val[0..], argc, argv, types), | |
139 | .FLOAT_MAT2 => |*val| set_array(f32, val[0..], argc, argv, types), | |
140 | .FLOAT_MAT3 => |*val| set_array(f32, val[0..], argc, argv, types), | |
141 | .FLOAT_MAT4 => |*val| set_array(f32, val[0..], argc, argv, types), | |
142 | .FLOAT_MAT2x3 => |*val| set_array(f32, val[0..], argc, argv, types), | |
143 | .FLOAT_MAT2x4 => |*val| set_array(f32, val[0..], argc, argv, types), | |
144 | .FLOAT_MAT3x2 => |*val| set_array(f32, val[0..], argc, argv, types), | |
145 | .FLOAT_MAT3x4 => |*val| set_array(f32, val[0..], argc, argv, types), | |
146 | .FLOAT_MAT4x2 => |*val| set_array(f32, val[0..], argc, argv, types), | |
147 | .FLOAT_MAT4x3 => |*val| set_array(f32, val[0..], argc, argv, types), | |
148 | .DOUBLE_MAT2 => |*val| set_array(f64, val[0..], argc, argv, types), | |
149 | .DOUBLE_MAT3 => |*val| set_array(f64, val[0..], argc, argv, types), | |
150 | .DOUBLE_MAT4 => |*val| set_array(f64, val[0..], argc, argv, types), | |
151 | .DOUBLE_MAT2x3 => |*val| set_array(f64, val[0..], argc, argv, types), | |
152 | .DOUBLE_MAT2x4 => |*val| set_array(f64, val[0..], argc, argv, types), | |
153 | .DOUBLE_MAT3x2 => |*val| set_array(f64, val[0..], argc, argv, types), | |
154 | .DOUBLE_MAT3x4 => |*val| set_array(f64, val[0..], argc, argv, types), | |
155 | .DOUBLE_MAT4x2 => |*val| set_array(f64, val[0..], argc, argv, types), | |
156 | .DOUBLE_MAT4x3 => |*val| set_array(f64, val[0..], argc, argv, types), | |
157 | else => error.uniformNotSupported, | |
158 | }; | |
159 | ||
160 | uniform.setShaderValue(self.cache.shader.*); | |
161 | } | |
162 | ||
163 | fn handle_method( | |
164 | _path: [*c]const u8, | |
165 | _types: [*c]const u8, | |
166 | argv: [*c][*c]c.lo_arg, | |
167 | argc: c_int, | |
168 | msg: c.lo_message, | |
169 | userdata: ?*c_void, | |
170 | ) callconv(.C) c_int { | |
80 | 171 | const self = @ptrCast(*ControlServer, @alignCast(@alignOf(ControlServer), userdata.?)); |
81 | 172 | const path = _path[0..c.strlen(_path)]; |
82 | 173 | const types = _types[0..@intCast(u32, argc)]; |
83 | 174 | |
84 | if (std.mem.startsWith(u8, path, "/param/")) { | |
85 | if (!std.mem.endsWith(u8, path, "/set")) { | |
86 | std.debug.warn("unhandled OSC message {s} ({s})\n", .{ path, types }); | |
87 | return 1; | |
88 | } | |
89 | ||
90 | const param_name = path["/param/".len .. path.len - "/set".len]; | |
91 | var buffer: [256]u8 = undefined; | |
92 | std.mem.copy(u8, buffer[0..], param_name); | |
93 | buffer[param_name.len] = 0; | |
94 | ||
95 | const uniform = self.cache.get(buffer[0 .. param_name.len + 1]) | |
96 | catch { return 0; } | |
97 | orelse { return 0; }; | |
98 | ||
99 | switch (uniform.value) { | |
100 | .FLOAT => |*val| val.* = argv[0].*.f, | |
101 | .FLOAT_VEC2 => |*val| set_array(f32, val[0..], argc, argv), | |
102 | .FLOAT_VEC3 => |*val| set_array(f32, val[0..], argc, argv), | |
103 | .FLOAT_VEC4 => |*val| set_array(f32, val[0..], argc, argv), | |
104 | .DOUBLE => |*val| val.* = argv[0].*.d, | |
105 | .DOUBLE_VEC2 => |*val| set_array(f64, val[0..], argc, argv), | |
106 | .DOUBLE_VEC3 => |*val| set_array(f64, val[0..], argc, argv), | |
107 | .DOUBLE_VEC4 => |*val| set_array(f64, val[0..], argc, argv), | |
108 | .INT => |*val| val.* = argv[0].*.i, | |
109 | .INT_VEC2 => |*val| set_array(i32, val[0..], argc, argv), | |
110 | .INT_VEC3 => |*val| set_array(i32, val[0..], argc, argv), | |
111 | .INT_VEC4 => |*val| set_array(i32, val[0..], argc, argv), | |
112 | .UNSIGNED_INT => |*val| val.* = @intCast(u32, argv[0].*.i), | |
113 | .UNSIGNED_INT_VEC2 => |*val| set_array(u32, val[0..], argc, argv), | |
114 | .UNSIGNED_INT_VEC3 => |*val| set_array(u32, val[0..], argc, argv), | |
115 | .UNSIGNED_INT_VEC4 => |*val| set_array(u32, val[0..], argc, argv), | |
116 | .BOOL => |*val| val.* = @intCast(u32, argv[0].*.i), | |
117 | .BOOL_VEC2 => |*val| set_array(u32, val[0..], argc, argv), | |
118 | .BOOL_VEC3 => |*val| set_array(u32, val[0..], argc, argv), | |
119 | .BOOL_VEC4 => |*val| set_array(u32, val[0..], argc, argv), | |
120 | .FLOAT_MAT2 => |*val| set_array(f32, val[0..], argc, argv), | |
121 | .FLOAT_MAT3 => |*val| set_array(f32, val[0..], argc, argv), | |
122 | .FLOAT_MAT4 => |*val| set_array(f32, val[0..], argc, argv), | |
123 | .FLOAT_MAT2x3 => |*val| set_array(f32, val[0..], argc, argv), | |
124 | .FLOAT_MAT2x4 => |*val| set_array(f32, val[0..], argc, argv), | |
125 | .FLOAT_MAT3x2 => |*val| set_array(f32, val[0..], argc, argv), | |
126 | .FLOAT_MAT3x4 => |*val| set_array(f32, val[0..], argc, argv), | |
127 | .FLOAT_MAT4x2 => |*val| set_array(f32, val[0..], argc, argv), | |
128 | .FLOAT_MAT4x3 => |*val| set_array(f32, val[0..], argc, argv), | |
129 | .DOUBLE_MAT2 => |*val| set_array(f64, val[0..], argc, argv), | |
130 | .DOUBLE_MAT3 => |*val| set_array(f64, val[0..], argc, argv), | |
131 | .DOUBLE_MAT4 => |*val| set_array(f64, val[0..], argc, argv), | |
132 | .DOUBLE_MAT2x3 => |*val| set_array(f64, val[0..], argc, argv), | |
133 | .DOUBLE_MAT2x4 => |*val| set_array(f64, val[0..], argc, argv), | |
134 | .DOUBLE_MAT3x2 => |*val| set_array(f64, val[0..], argc, argv), | |
135 | .DOUBLE_MAT3x4 => |*val| set_array(f64, val[0..], argc, argv), | |
136 | .DOUBLE_MAT4x2 => |*val| set_array(f64, val[0..], argc, argv), | |
137 | .DOUBLE_MAT4x3 => |*val| set_array(f64, val[0..], argc, argv), | |
138 | else => { | |
139 | std.debug.warn("unsupported types: {s}\n", .{types}); | |
140 | return 0; | |
141 | } | |
142 | } | |
143 | ||
144 | uniform.setShaderValue(self.cache.shader.*); | |
145 | return 0; | |
175 | if (!std.mem.startsWith(u8, path, "/")) { | |
176 | std.debug.warn("invalid OSC message {s} ({s})\n", .{ path, types }); | |
177 | return 1; | |
146 | 178 | } |
147 | 179 | |
148 | std.debug.warn("unhandled OSC message {s} ({s})\n", .{ path, types }); | |
149 | return 1; | |
180 | self.set_uniform(path[1..], argv, argc, types) catch |err| { | |
181 | std.debug.warn("{}\n", .{err}); | |
182 | }; | |
183 | return 0; | |
150 | 184 | } |
151 | 185 | |
152 | 186 | fn handle_bundle_start(time: c.lo_timetag, userdata: ?*c_void) callconv(.C) c_int { |
153 | 187 | return 1; |
154 | 188 | } |
189 | ||
155 | 190 | fn handle_bundle_end(userdata: ?*c_void) callconv(.C) c_int { |
156 | 191 | return 1; |
157 | 192 | } |