From 60db3b8a87b4d356ab3c2c43e24a2c060961cd96 Mon Sep 17 00:00:00 2001 From: s-ol Date: Sat, 10 Jan 2026 17:06:04 +0100 Subject: pipe raw video to stdout --- src/control.zig | 7 ++++++- src/gl.zig | 15 +++++++++++++++ src/main.zig | 20 +++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/control.zig b/src/control.zig index 053f985..9810645 100644 --- a/src/control.zig +++ b/src/control.zig @@ -110,6 +110,8 @@ pub const ControlServer = struct { progress: std.Progress.Node, allocator: std.mem.Allocator, + dirty: bool, + pub fn init( allocator: std.mem.Allocator, progress: std.Progress.Node, @@ -127,6 +129,8 @@ pub const ControlServer = struct { .constants = constants, .progress = progress, .allocator = allocator, + + .dirty = false, }; self.server = c.lo_server_new_from_url(config.osc.ptr, handle_error); @@ -221,7 +225,8 @@ pub const ControlServer = struct { const code: [*:0]const u8 = @ptrCast(&argv[0].*.s); try self.cache.shader.loadString(std.mem.span(code)); try self.cache.refresh(); - std.debug.print("reloaded\n", .{}); + self.dirty = true; + return true; } diff --git a/src/gl.zig b/src/gl.zig index 7cdc204..2c7c865 100644 --- a/src/gl.zig +++ b/src/gl.zig @@ -1008,6 +1008,21 @@ pub const FramebufferObject = struct { c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); } + pub fn read(self: FramebufferObject, width: c.GLint, height: c.GLint, data: []u8) void { + _ = self; + c.glReadBuffer(c.GL_COLOR_ATTACHMENT0); + c.glReadnPixels( + 0, + 0, + width, + height, + c.GL_RGBA, + c.GL_UNSIGNED_BYTE, + @intCast(data.len), + data.ptr, + ); + } + pub fn create(width: i32, height: i32) !FramebufferObject { var self: FramebufferObject = undefined; c.glGenFramebuffers(1, &self.buffer_id); diff --git a/src/main.zig b/src/main.zig index 6d70a14..fbe006e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -118,6 +118,15 @@ pub fn main() !void { defer control.destroy(); var loops: u8 = 0; + + const stdout = std.fs.File.stdout(); + var tex_buffer: ?[]u8 = null; + + if (!stdout.isTty()) { + tex_buffer = try std.heap.c_allocator.alloc(u8, @intCast(config.width * config.height * 4)); + } + defer if (tex_buffer) |buf| std.heap.c_allocator.free(buf); + while (c.glfwWindowShouldClose(window) == c.GL_FALSE) { c.glfwMakeContextCurrent(window); @@ -135,7 +144,7 @@ pub fn main() !void { // control.reload_requested = false; // } - { + if (control.dirty) { c.glFinish(); var timer = try std.time.Timer.start(); @@ -144,6 +153,13 @@ pub fn main() !void { main_program.bind(); constants.normalized_quad.draw(); + + if (tex_buffer) |buf| { + fbo.read(config.width, config.height, buf); + std.debug.print("writing {} bytes\n", .{buf.len}); + _ = try stdout.write(buf); + } + fbo.unbind(); c.glFinish(); @@ -152,6 +168,8 @@ pub fn main() !void { if (loops == 0) { std.debug.print("\rrendered in {d:.2}ms\n", .{@as(f64, @floatFromInt(fps)) / std.time.ns_per_ms}); } + + control.dirty = false; } for (outputs.items, 0..) |output, i| { -- cgit v1.2.3