aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2025-07-30 17:20:53 +0000
committers-ol <s+removethis@s-ol.nu>2025-07-30 17:20:57 +0000
commitf372f217202c4966bd132123831184de4436cce6 (patch)
tree117a73a5ce5779ea2ada1ac5f3afae1cfd0557e7
parentaccept format and format_options for ffmpeg sources (diff)
downloadglsl-view-f372f217202c4966bd132123831184de4436cce6.tar.gz
glsl-view-f372f217202c4966bd132123831184de4436cce6.zip
add freeze and step controls to Source
-rw-r--r--src/control.zig34
-rw-r--r--src/ffmpeg.zig8
-rw-r--r--src/gl.zig9
-rw-r--r--src/tsv.zig2
4 files changed, 48 insertions, 5 deletions
diff --git a/src/control.zig b/src/control.zig
index 032a927..4f4d547 100644
--- a/src/control.zig
+++ b/src/control.zig
@@ -175,6 +175,9 @@ pub const ControlServer = struct {
if (build_config.have_tsv) {
_ = c.lo_server_add_method(self.server, "/texture/*/tsv", "ss", wrapCallback(handle_texture_tsv), @as(*anyopaque, @ptrCast(self)));
}
+ _ = c.lo_server_add_method(self.server, "/texture/*/freeze", "T", wrapCallback(handle_texture_freeze), @as(*anyopaque, @ptrCast(self)));
+ _ = c.lo_server_add_method(self.server, "/texture/*/freeze", "F", wrapCallback(handle_texture_freeze), @as(*anyopaque, @ptrCast(self)));
+ _ = c.lo_server_add_method(self.server, "/texture/*/step", "", wrapCallback(handle_texture_step), @as(*anyopaque, @ptrCast(self)));
_ = c.lo_server_add_method(self.server, "/texture/*/destroy", "", wrapCallback(handle_destroy_texture), @as(*anyopaque, @ptrCast(self)));
return self;
@@ -380,6 +383,35 @@ pub const ControlServer = struct {
return true;
}
+ fn handle_texture_freeze(self: *ControlServer, path: []const u8, types: []const u8, argv: []const [*c]c.lo_arg) !bool {
+ _ = argv;
+
+ var parts = std.mem.tokenizeScalar(u8, path, '/');
+ _ = parts.next();
+ const name = parts.next() orelse unreachable;
+
+ if (self.cache.textures.get(name)) |source| {
+ source.freeze = types[0] == 'T';
+ } else return false;
+
+ return true;
+ }
+
+ fn handle_texture_step(self: *ControlServer, path: []const u8, types: []const u8, argv: []const [*c]c.lo_arg) !bool {
+ _ = argv;
+ _ = types;
+
+ var parts = std.mem.tokenizeScalar(u8, path, '/');
+ _ = parts.next();
+ const name = parts.next() orelse unreachable;
+
+ if (self.cache.textures.get(name)) |source| {
+ source.step.store(true, .monotonic);
+ } else return false;
+
+ return true;
+ }
+
fn handle_destroy_texture(self: *ControlServer, path: []const u8, types: []const u8, argv: []const [*c]c.lo_arg) !bool {
_ = types;
_ = argv;
@@ -394,6 +426,6 @@ pub const ControlServer = struct {
self.cache.allocator.free(kv.key);
} else return false;
- return false;
+ return true;
}
};
diff --git a/src/ffmpeg.zig b/src/ffmpeg.zig
index 67c3c2c..dda3f8c 100644
--- a/src/ffmpeg.zig
+++ b/src/ffmpeg.zig
@@ -286,7 +286,6 @@ pub const VideoSource = struct {
self.* = .{
.source = .{
.texture = undefined,
-
.deinit_fn = deinit,
},
.decoder = if (is_hap and build_config.have_hap)
@@ -356,7 +355,6 @@ pub const StreamSource = struct {
self.* = .{
.source = .{
.texture = texture,
-
.deinit_fn = deinit,
},
@@ -389,7 +387,11 @@ pub const StreamSource = struct {
if (self.packet.*.stream_index != self.stream) return;
self.decoder.num_frames = 0;
- _ = try self.decoder.process_packet_fn(self.decoder, self.packet, &self.source.texture);
+ _ = try self.decoder.process_packet_fn(
+ self.decoder,
+ self.packet,
+ if (self.source.shouldStep()) &self.source.texture else null,
+ );
}
fn deinit(source: *gl.Source, allocator: std.mem.Allocator) void {
diff --git a/src/gl.zig b/src/gl.zig
index 2b7e9ea..b578350 100644
--- a/src/gl.zig
+++ b/src/gl.zig
@@ -941,11 +941,20 @@ pub const Source = struct {
};
texture: Texture,
+ freeze: bool = false,
+ step: std.atomic.Value(bool) = std.atomic.Value(bool).init(false),
+
deinit_fn: *const fn (self: *Source, allocator: std.mem.Allocator) void,
pub fn deinit(self: *Source, allocator: std.mem.Allocator) void {
self.deinit_fn(self, allocator);
}
+
+ pub fn shouldStep(self: *Source) bool {
+ const step = !self.freeze or self.step.load(.acquire);
+ if (step) self.step.store(false, .release);
+ return step;
+ }
};
pub const UniformCache = struct {
diff --git a/src/tsv.zig b/src/tsv.zig
index 687a2ed..a723a52 100644
--- a/src/tsv.zig
+++ b/src/tsv.zig
@@ -44,7 +44,6 @@ pub const TSVSource = struct {
self.* = .{
.source = .{
.texture = gl.Texture.create(texture_type),
-
.deinit_fn = deinit,
},
.name = try allocator.dupeZ(u8, std.mem.span(name)),
@@ -86,6 +85,7 @@ pub const TSVSource = struct {
}
fn update(self: *TSVSource) void {
+ if (!self.source.shouldStep()) return;
_ = c.gl_client_recv_image(
get_or_init_client(),
self.name.ptr,