aboutsummaryrefslogtreecommitdiffstats
path: root/src/source.zig
blob: 96ba87884464972d2fab004f20276961dd4a5f72 (plain)
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
const std = @import("std");
const c = @import("c.zig");
const gl = @import("gl.zig");
const ctrl = @import("control.zig");
const util = @import("util.zig");

pub const Source = struct {
    texture: gl.Texture,
    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,

    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 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;
    }
};