diff options
Diffstat (limited to 'src/control.zig')
| -rw-r--r-- | src/control.zig | 127 |
1 files changed, 80 insertions, 47 deletions
diff --git a/src/control.zig b/src/control.zig index 4db7cf1..1008ff4 100644 --- a/src/control.zig +++ b/src/control.zig @@ -16,7 +16,7 @@ fn verify_args(expected: u8, got: []const u8) !void { fn set_one( comptime T: type, dest: *T, - argv: [][*c]c.lo_arg, + argv: []const[*c]c.lo_arg, types: []const u8, ) !void { if (types.len != 1) @@ -49,7 +49,7 @@ fn set_one( fn set_array( comptime T: type, dest: []T, - argv: [][*c]c.lo_arg, + argv: []const[*c]c.lo_arg, types: []const u8, ) !void { if (types.len != dest.len) @@ -85,27 +85,21 @@ fn set_array( } fn set_texture( - progress: std.Progress.Node, cache: *gl.UniformCache, - dest: *?gl.Texture, + dest: *?*gl.Texture, texture_type: gl.Texture.Type, - argv: [][*c]c.lo_arg, types: []const u8, + argv: []const[*c]c.lo_arg, ) !void { if (types.len != 1 or types[0] != 's') return error.invalidType; - const filenameZ: [*:0]const u8 = @ptrCast(&argv[0].*.s); - const filename = std.mem.span(filenameZ); - - if (!cache.textures.contains(filename)) { - const key = try cache.allocator.dupe(u8, filename); - errdefer cache.allocator.free(key); + const nameZ: [*:0]const u8 = @ptrCast(&argv[0].*.s); + const name = std.mem.span(nameZ); - const texture = try video.loadVideo(progress, filenameZ, texture_type); - try cache.textures.put(key, texture); - } + const tex = cache.textures.getPtr(name) orelse return error.texNotFound; + if (tex.type != texture_type) return error.wrongTextureType; - dest.* = cache.textures.get(filename); + dest.* = tex; } pub const ControlServer = struct { @@ -116,6 +110,34 @@ pub const ControlServer = struct { progress: std.Progress.Node, allocator: std.mem.Allocator, + const ZigCallback = fn (*ControlServer, []const u8, []const u8, []const[*c]c.lo_arg) anyerror!bool; + const CCallback = fn ([*c]const u8, [*c]const u8, [*c][*c]c.lo_arg, c_int, c.lo_message, ?*anyopaque) callconv(.C) c_int; + fn wrapCallback(comptime inner: ZigCallback) CCallback { + return struct { + fn wrapped( + _path: ?[*:0]const u8, + _types: ?[*:0]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 path = std.mem.span(_path.?); + const types = std.mem.span(_types.?); + const args = if (_argv) |argv| argv[0..@intCast(argc)] else &.{}; + + _ = msg; + + const res = inner(self, path, types, args) catch |err| { + std.debug.print("Error handling {s}: {}\n", .{ path, err }); + return 1; + }; + return if (res) 0 else 1; + } + }.wrapped; + } + pub fn init( allocator: std.mem.Allocator, progress: std.Progress.Node, @@ -142,6 +164,9 @@ pub const ControlServer = struct { // _ = c.lo_server_add_method(self.server, "/reload", "", handle_reload, @as(*anyopaque, @ptrCast(self))); _ = c.lo_server_add_method(self.server, "/uniform/*", null, wrapCallback(handle_uniform), @as(*anyopaque, @ptrCast(self))); + _ = c.lo_server_add_method(self.server, "/texture/*", "ss", wrapCallback(handle_load_texture), @as(*anyopaque, @ptrCast(self))); + _ = c.lo_server_add_method(self.server, "/texture/*/destroy", "", wrapCallback(handle_destroy_texture), @as(*anyopaque, @ptrCast(self))); + return self; } @@ -155,12 +180,12 @@ pub const ControlServer = struct { fn handle_error(num: c_int, msg: [*c]const u8, where: [*c]const u8) callconv(.C) void { std.debug.print( - "OSC error {} @ {s}: {s}\n", - .{ num, @as([*:0]const u8, @ptrCast(where)), @as([*:0]const u8, @ptrCast(msg)) }, + "OSC error {} @ {?s}: {?s}\n", + .{ num, @as(?[*:0]const u8, @ptrCast(where)), @as(?[*:0]const u8, @ptrCast(msg)) }, ); } - fn handle_shader(self: *ControlServer, path: []const u8, types: []const u8, argv: [][*c]c.lo_arg) !bool { + fn handle_shader(self: *ControlServer, path: []const u8, types: []const u8, argv: []const[*c]c.lo_arg) !bool { _ = path; _ = types; @@ -170,7 +195,7 @@ pub const ControlServer = struct { return true; } - fn handle_reload(self: *ControlServer, path: []const u8, types: []const u8, argv: [][*c]c.lo_arg) !bool { + fn handle_reload(self: *ControlServer, path: []const u8, types: []const u8, argv: []const[*c]c.lo_arg) !bool { _ = path; _ = types; _ = argv; @@ -180,7 +205,7 @@ pub const ControlServer = struct { return true; } - fn handle_uniform(self: *ControlServer, path: []const u8, types: []const u8, argv: [][*c]c.lo_arg) !bool { + fn handle_uniform(self: *ControlServer, path: []const u8, types: []const u8, argv: []const[*c]c.lo_arg) !bool { var parts = std.mem.tokenizeScalar(u8, path, '/'); _ = parts.next(); // skip /uniform @@ -253,18 +278,18 @@ pub const ControlServer = struct { .SAMPLER_2D_SHADOW, .INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_2D, - => |val| set_texture(self.progress, self.cache, val, .TEXTURE_2D, argv, types), + => |val| set_texture(self.cache, val, .TEXTURE_2D, types, argv), .SAMPLER_2D_ARRAY, .SAMPLER_2D_ARRAY_SHADOW, .INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, - => |val| set_texture(self.progress, self.cache, val, .TEXTURE_2D_ARRAY, argv, types), + => |val| set_texture(self.cache, val, .TEXTURE_2D_ARRAY, types, argv), .SAMPLER_3D, .INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_3D, - => |val| set_texture(self.progress, self.cache, val, .TEXTURE_3D, argv, types), + => |val| set_texture(self.cache, val, .TEXTURE_3D, types, argv), else => error.uniformNotSupported, }; @@ -273,32 +298,40 @@ pub const ControlServer = struct { return true; } - const ZigCallback = fn (*ControlServer, []const u8, []const u8, [][*c]c.lo_arg) anyerror!bool; - const CCallback = fn ([*c]const u8, [*c]const u8, [*c][*c]c.lo_arg, c_int, c.lo_message, ?*anyopaque) callconv(.C) c_int; + fn handle_load_texture(self: *ControlServer, path: []const u8, types: []const u8, argv: []const[*c]c.lo_arg) !bool { + _ = types; - fn wrapCallback(comptime inner: ZigCallback) CCallback { - return struct { - fn wrapped( - _path: ?[*:0]const u8, - _types: ?[*:0]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 path = std.mem.span(_path.?); - const types = std.mem.span(_types.?); - const args = _argv[0..@intCast(argc)]; + var parts = std.mem.tokenizeScalar(u8, path, '/'); + _ = parts.next(); + const name = parts.next() orelse unreachable; + if (self.cache.textures.contains(name)) return error.textureNameTaken; - _ = msg; + const texture_typeZ: [*:0]const u8 = @ptrCast(&argv[0].*.s); + const texture_type = std.meta.stringToEnum(gl.Texture.Type, std.mem.span(texture_typeZ)) orelse return error.invalidType; - const res = inner(self, path, types, args) catch |err| { - std.debug.print("Error handling {s}: {}\n", .{ path, err }); - return 1; - }; - return if (res) 0 else 1; - } - }.wrapped; + const filenameZ: [*:0]const u8 = @ptrCast(&argv[1].*.s); + const key = try self.cache.allocator.dupe(u8, name); + errdefer self.cache.allocator.free(key); + + const texture = try video.loadVideo(self.progress, filenameZ, texture_type); + try self.cache.textures.put(key, texture); + + return true; + } + + fn handle_destroy_texture(self: *ControlServer, path: []const u8, types: []const u8, argv: []const[*c]c.lo_arg) !bool { + _ = types; + _ = argv; + + var parts = std.mem.tokenizeScalar(u8, path, '/'); + _ = parts.next(); + const name = parts.next() orelse unreachable; + + if (self.cache.textures.fetchRemove(name)) |kv| { + kv.value.destroy(); + self.cache.allocator.free(kv.key); + } else return false; + + return false; } }; |
