const c = @import("c.zig"); const gl = @import("gl.zig"); const std = @import("std"); const param_prefix = "/param/"; pub const ControlServer = struct { server: c.lo_server, shader: gl.ShaderProgram, pub fn init(allocator: *std.mem.Allocator) !*ControlServer { var self: *ControlServer = try allocator.create(ControlServer); self.server = c.lo_server_new("1234", handle_error); _ = c.lo_server_add_method(self.server, null, null, handle_method, @ptrCast(*c_void, self)); return self; } pub fn update(self: *ControlServer, shader: gl.ShaderProgram) void { self.shader = shader; while (c.lo_server_recv_noblock(self.server, 0) > 0) {} } pub fn destroy(self: ControlServer) void { c.lo_server_free(self.server); } fn handle_error(num: c_int, msg: [*c]const u8, where: [*c]const u8) callconv(.C) void { std.debug.warn("OSC error {} @ {s}: {s}\n", .{ num, @ptrCast([*:0]const u8, where), @ptrCast([*:0]const u8, msg) }); } 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 { const self = @ptrCast(*ControlServer, @alignCast(@alignOf(ControlServer), userdata.?)); const path = _path[0..c.strlen(_path)]; const types = _types[0..@intCast(u32, argc)]; if (std.mem.startsWith(u8, path, param_prefix)) { const param_name = path[param_prefix.len..]; const uniform = self.shader.uniformLocation(@ptrCast([*]const u8, param_name.ptr)) catch { std.debug.warn("param {s} doesn't exist\n", .{param_name}); return 0; }; if (argc == 0) { std.debug.warn("param get: {s}\n", .{param_name}); return 0; } if (std.mem.eql(u8, types, "f")) { self.shader.setUniform1f(uniform, argv[0].*.f); } else if (std.mem.eql(u8, types, "ff")) { self.shader.setUniform2f(uniform, argv[0].*.f, argv[1].*.f); } else if (std.mem.eql(u8, types, "fff")) { self.shader.setUniform3f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f); } else if (std.mem.eql(u8, types, "ffff")) { self.shader.setUniform4f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f, argv[3].*.f); } else if (std.mem.eql(u8, types, "i")) { self.shader.setUniform1i(uniform, argv[0].*.i); } else { std.debug.warn("unsupported types: {s}\n", .{types}); } return 0; } std.debug.warn("unhandled OSC message {s} ({s})\n", .{ path, types }); return 1; } fn handle_bundle_start(time: c.lo_timetag, userdata: ?*c_void) callconv(.C) c_int { return 1; } fn handle_bundle_end(userdata: ?*c_void) callconv(.C) c_int { return 1; } };