diff options
Diffstat (limited to 'src/control.zig')
| -rw-r--r-- | src/control.zig | 206 |
1 files changed, 117 insertions, 89 deletions
diff --git a/src/control.zig b/src/control.zig index 0ea6712..72abf6f 100644 --- a/src/control.zig +++ b/src/control.zig @@ -16,11 +16,10 @@ fn verify_args(expected: u8, got: []const u8) !void { fn set_one( comptime T: type, dest: *T, - argc: c_int, - argv: [*c][*c]c.lo_arg, + argv: [][*c]c.lo_arg, types: []const u8, ) !void { - if (argc != 1) + if (types.len != 1) return error.sizeMismatch; switch (T) { @@ -50,11 +49,10 @@ fn set_one( fn set_array( comptime T: type, dest: []T, - argc: c_int, - argv: [*c][*c]c.lo_arg, + argv: [][*c]c.lo_arg, types: []const u8, ) !void { - if (argc != dest.len) + if (types.len != dest.len) return error.sizeMismatch; switch (T) { @@ -88,14 +86,12 @@ fn set_array( fn set_texture( progress: std.Progress.Node, - project_root: std.fs.Dir, dest: *?gl.Texture, texture_type: gl.Texture.Type, - argc: c_int, - argv: [*c][*c]c.lo_arg, + argv: [][*c]c.lo_arg, types: []const u8, ) !void { - if (argc != 1 or types[0] != 's') return error.invalidType; + if (types.len != 1 or types[0] != 's') return error.invalidType; if (dest.*) |old| { old.destroy(); @@ -103,7 +99,7 @@ fn set_texture( } var buffer: [1024]u8 = undefined; - const filepath = try project_root.realpathZ(@ptrCast(&argv[0].*.s), buffer[0..]); + const filepath = try std.fs.cwd().realpathZ(@ptrCast(&argv[0].*.s), buffer[0..]); buffer[filepath.len] = 0; dest.* = try video.loadVideo(progress, @ptrCast(filepath), texture_type); @@ -111,7 +107,6 @@ fn set_texture( pub const ControlServer = struct { server: c.lo_server, - reload_requested: bool, cache: *gl.UniformCache, config: *cfg.Config, @@ -127,7 +122,6 @@ pub const ControlServer = struct { var self: *ControlServer = try allocator.create(ControlServer); self.* = .{ .server = null, - .reload_requested = false, .cache = cache, .config = config, @@ -135,31 +129,15 @@ pub const ControlServer = struct { .allocator = allocator, }; - switch (config.osc) { - .Manual => |conf| { - var port = [_]u8{0} ** 6; - _ = std.fmt.formatIntBuf(port[0..], conf.port, 10, .lower, std.fmt.FormatOptions{}); - const proto: c_int = switch (conf.protocol) { - .udp => c.LO_UDP, - .tcp => c.LO_TCP, - .unix => c.LO_UNIX, - }; - - std.debug.print( - "listening for OSC messages on {} port {}\n", - .{ conf.protocol, conf.port }, - ); - self.server = c.lo_server_new_with_proto(port[0..], proto, handle_error); - }, - .URL => |url| { - std.debug.print("listening for OSC messages at {s}\n", .{url}); - self.server = c.lo_server_new_from_url(url[0..].ptr, handle_error); - }, - } + std.debug.print("listening for OSC messages at {s}\n", .{config.osc}); + self.server = c.lo_server_new_from_url(config.osc.ptr, handle_error); if (self.server == null) return error.serverInitializationError; - _ = c.lo_server_add_method(self.server, null, null, handle_method, @as(*anyopaque, @ptrCast(self))); + + _ = c.lo_server_add_method(self.server, "/-/shader", "s", handle_shader, @as(*anyopaque, @ptrCast(self))); + // _ = c.lo_server_add_method(self.server, "/-/reload", "", handle_reload, @as(*anyopaque, @ptrCast(self))); + _ = c.lo_server_add_method(self.server, "/*", null, handle_uniform, @as(*anyopaque, @ptrCast(self))); return self; } @@ -182,8 +160,7 @@ pub const ControlServer = struct { fn set_uniform( self: *ControlServer, path: []const u8, - argv: [*c][*c]c.lo_arg, - argc: c_int, + argv: [][*c]c.lo_arg, types: []const u8, ) !void { var parts = std.mem.tokenizeScalar(u8, path, '/'); @@ -217,61 +194,61 @@ pub const ControlServer = struct { } try switch (value) { - .FLOAT => |val| set_one(f32, val, argc, argv, types), - .DOUBLE => |val| set_one(f64, val, argc, argv, types), - .INT => |val| set_one(i32, val, argc, argv, types), - .UNSIGNED_INT => |val| set_one(u32, val, argc, argv, types), - .BOOL => |val| set_one(u32, val, argc, argv, types), - .FLOAT_VEC2 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_VEC3 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_VEC4 => |val| set_array(f32, val.*[0..], argc, argv, types), - .DOUBLE_VEC2 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_VEC3 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_VEC4 => |val| set_array(f64, val.*[0..], argc, argv, types), - .INT_VEC2 => |val| set_array(i32, val.*[0..], argc, argv, types), - .INT_VEC3 => |val| set_array(i32, val.*[0..], argc, argv, types), - .INT_VEC4 => |val| set_array(i32, val.*[0..], argc, argv, types), - .UNSIGNED_INT_VEC2 => |val| set_array(u32, val.*[0..], argc, argv, types), - .UNSIGNED_INT_VEC3 => |val| set_array(u32, val.*[0..], argc, argv, types), - .UNSIGNED_INT_VEC4 => |val| set_array(u32, val.*[0..], argc, argv, types), - .BOOL_VEC2 => |val| set_array(u32, val.*[0..], argc, argv, types), - .BOOL_VEC3 => |val| set_array(u32, val.*[0..], argc, argv, types), - .BOOL_VEC4 => |val| set_array(u32, val.*[0..], argc, argv, types), - .FLOAT_MAT2 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT3 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT4 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT2x3 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT2x4 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT3x2 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT3x4 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT4x2 => |val| set_array(f32, val.*[0..], argc, argv, types), - .FLOAT_MAT4x3 => |val| set_array(f32, val.*[0..], argc, argv, types), - .DOUBLE_MAT2 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT3 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT4 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT2x3 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT2x4 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT3x2 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT3x4 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT4x2 => |val| set_array(f64, val.*[0..], argc, argv, types), - .DOUBLE_MAT4x3 => |val| set_array(f64, val.*[0..], argc, argv, types), + .FLOAT => |val| set_one(f32, val, argv, types), + .DOUBLE => |val| set_one(f64, val, argv, types), + .INT => |val| set_one(i32, val, argv, types), + .UNSIGNED_INT => |val| set_one(u32, val, argv, types), + .BOOL => |val| set_one(u32, val, argv, types), + .FLOAT_VEC2 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_VEC3 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_VEC4 => |val| set_array(f32, val.*[0..], argv, types), + .DOUBLE_VEC2 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_VEC3 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_VEC4 => |val| set_array(f64, val.*[0..], argv, types), + .INT_VEC2 => |val| set_array(i32, val.*[0..], argv, types), + .INT_VEC3 => |val| set_array(i32, val.*[0..], argv, types), + .INT_VEC4 => |val| set_array(i32, val.*[0..], argv, types), + .UNSIGNED_INT_VEC2 => |val| set_array(u32, val.*[0..], argv, types), + .UNSIGNED_INT_VEC3 => |val| set_array(u32, val.*[0..], argv, types), + .UNSIGNED_INT_VEC4 => |val| set_array(u32, val.*[0..], argv, types), + .BOOL_VEC2 => |val| set_array(u32, val.*[0..], argv, types), + .BOOL_VEC3 => |val| set_array(u32, val.*[0..], argv, types), + .BOOL_VEC4 => |val| set_array(u32, val.*[0..], argv, types), + .FLOAT_MAT2 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT3 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT4 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT2x3 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT2x4 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT3x2 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT3x4 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT4x2 => |val| set_array(f32, val.*[0..], argv, types), + .FLOAT_MAT4x3 => |val| set_array(f32, val.*[0..], argv, types), + .DOUBLE_MAT2 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT3 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT4 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT2x3 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT2x4 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT3x2 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT3x4 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT4x2 => |val| set_array(f64, val.*[0..], argv, types), + .DOUBLE_MAT4x3 => |val| set_array(f64, val.*[0..], argv, types), .SAMPLER_2D, .SAMPLER_2D_SHADOW, .INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_2D, - => |val| set_texture(self.progress, self.config.project_root, val, .TEXTURE_2D, argc, argv, types), + => |val| set_texture(self.progress, val, .TEXTURE_2D, argv, types), .SAMPLER_2D_ARRAY, .SAMPLER_2D_ARRAY_SHADOW, .INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, - => |val| set_texture(self.progress, self.config.project_root, val, .TEXTURE_2D_ARRAY, argc, argv, types), + => |val| set_texture(self.progress, val, .TEXTURE_2D_ARRAY, argv, types), .SAMPLER_3D, .INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_3D, - => |val| set_texture(self.progress, self.config.project_root, val, .TEXTURE_3D, argc, argv, types), + => |val| set_texture(self.progress, val, .TEXTURE_3D, argv, types), else => error.uniformNotSupported, }; @@ -279,29 +256,80 @@ pub const ControlServer = struct { uniform.setShaderValue(self.cache.shader.*); } - fn handle_method( + fn handle_shader( + path: [*c]const u8, + types: [*c]const u8, + argv: [*c][*c]c.lo_arg, + argc: c_int, + msg: c.lo_message, + userdata: ?*anyopaque, + ) callconv(.C) c_int { + const self: *ControlServer = @ptrCast(@alignCast(userdata.?)); + const code: [*:0]const u8 = @ptrCast(&argv[0].*.s); + + _ = path; + _ = types; + _ = argc; + _ = msg; + + _ = e: { + self.cache.shader.loadString(std.mem.span(code)) catch |err| break :e err; + self.cache.refresh() catch |err| break :e err; + } catch |err| { + std.debug.print("{} while loading shader from OSC\n", .{err}); + }; + + return 0; + } + + fn handle_reload( + path: [*c]const u8, + types: [*c]const u8, + argv: [*c][*c]c.lo_arg, + argc: c_int, + msg: c.lo_message, + userdata: ?*anyopaque, + ) callconv(.C) c_int { + const self: *ControlServer = @ptrCast(@alignCast(userdata.?)); + + _ = path; + _ = types; + _ = argc; + _ = argv; + _ = msg; + + _ = e: { + self.cache.shader.loadFile(self.config.fragment, 2048) catch |err| break :e err; + self.cache.refresh() catch |err| break :e err; + } catch |err| { + std.debug.print("{} while reloading shader from file\n", .{err}); + }; + + return 0; + } + + fn handle_uniform( _path: [*c]const u8, _types: [*c]const u8, - argv: [*c][*c]c.lo_arg, + _argv: [*c][*c]c.lo_arg, argc: c_int, msg: c.lo_message, userdata: ?*anyopaque, ) callconv(.C) c_int { _ = msg; - const self = @as(*ControlServer, @ptrCast(@alignCast(userdata.?))); + const self: *ControlServer = @ptrCast(@alignCast(userdata.?)); const path = _path[0..c.strlen(_path)]; - const types = _types[0..@as(u32, @intCast(argc))]; + const argv: [][*c]c.lo_arg = _argv[0..@intCast(argc)]; + const types = _types[0..@intCast(argc)]; - if (std.mem.eql(u8, path, "/-/reload")) { - self.reload_requested = true; - return 1; - } - - self.set_uniform(path, argv, argc, types) catch |err| { - std.debug.print("{} while processing {s}\n", .{ err, path }); + self.set_uniform(path, argv, types) catch |err| { + if (err != error.notFound) { + std.debug.print("{} while processing {s}\n", .{ err, path }); + } return 1; }; + return 0; } |
