aboutsummaryrefslogtreecommitdiffstats
path: root/src/control.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/control.zig')
-rw-r--r--src/control.zig127
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;
}
};