1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
const std = @import("std");
const c = @import("c.zig").c;
const gl = @import("gl.zig");
const ctrl = @import("control.zig");
const util = @import("util.zig");
pub const Source = struct {
texture: gl.Texture,
update_fn: ?*const fn (self: *Source) anyerror!bool = null,
deinit_fn: *const fn (self: *Source, allocator: std.mem.Allocator) void,
register_fn: ?*const fn (self: *Source, name: []const u8, control: *ctrl.ControlServer) void = null,
unregister_fn: ?*const fn (self: *Source, name: []const u8, control: *ctrl.ControlServer) void = null,
update_uniform_fn: ?*const fn (self: *Source, param: []const u8, value: gl.UniformPointer) anyerror!void = null,
pub fn deinit(self: *Source, allocator: std.mem.Allocator) void {
self.deinit_fn(self, allocator);
}
pub fn register(self: *Source, name: []const u8, control: *ctrl.ControlServer) void {
if (self.register_fn) |register_fn| {
register_fn(self, name, control);
}
}
pub fn unregister(self: *Source, name: []const u8, control: *ctrl.ControlServer) void {
if (self.unregister_fn) |unregister_fn| {
unregister_fn(self, name, control);
}
}
pub fn update(self: *Source) bool {
if (self.update_fn) |update_fn| {
return update_fn(self) catch return true;
}
return false;
}
pub fn updateUniform(self: *Source, param: []const u8, value: gl.UniformPointer) anyerror!void {
if (self.update_uniform_fn) |update_uniform_fn| {
try update_uniform_fn(self, param, value);
}
}
};
pub const StreamFlags = struct {
freeze: bool = false,
step: std.atomic.Value(bool) = std.atomic.Value(bool).init(false),
pub fn register(self: *StreamFlags, name: []const u8, control: *ctrl.ControlServer) void {
control.add_method_for(StreamFlags, self, &.{ "/source", name, "freeze" }, "T", handle_freeze) catch unreachable;
control.add_method_for(StreamFlags, self, &.{ "/source", name, "freeze" }, "F", handle_freeze) catch unreachable;
control.add_method_for(StreamFlags, self, &.{ "/source", name, "step" }, "I", handle_step) catch unreachable;
control.add_method_for(StreamFlags, self, &.{ "/source", name, "step" }, "", handle_step) catch unreachable;
}
pub fn unregister(self: *const StreamFlags, name: []const u8, control: *ctrl.ControlServer) void {
_ = self;
control.del_method(&.{ "/source", name, "freeze" }, "T") catch unreachable;
control.del_method(&.{ "/source", name, "freeze" }, "F") catch unreachable;
control.del_method(&.{ "/source", name, "step" }, "") catch unreachable;
}
pub fn shouldStep(self: *StreamFlags) bool {
const step = !self.freeze or self.step.load(.acquire);
if (step) self.step.store(false, .release);
return step;
}
fn handle_freeze(self: *StreamFlags, path: []const u8, types: []const u8, argv: []const [*c]c.lo_arg) !bool {
_ = path;
_ = argv;
self.freeze = types[0] == 'T';
return true;
}
fn handle_step(self: *StreamFlags, path: []const u8, types: []const u8, argv: []const [*c]c.lo_arg) !bool {
_ = path;
_ = types;
_ = argv;
self.step.store(true, .monotonic);
return true;
}
};
|