aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-01-25 16:36:11 +0000
committers-ol <s-ol@users.noreply.github.com>2020-01-25 16:57:31 +0000
commit9d2d72db724de3b21a7ade4623c3b1a8603e85f3 (patch)
tree3f2ef21dfcc66db486b4871c2352ece0eea744e4 /src
parentbasic OSC support (diff)
downloadglsl-view-9d2d72db724de3b21a7ade4623c3b1a8603e85f3.tar.gz
glsl-view-9d2d72db724de3b21a7ade4623c3b1a8603e85f3.zip
OSC configuration in config.yaml
Diffstat (limited to 'src')
-rw-r--r--src/config.zig105
-rw-r--r--src/control.zig25
-rw-r--r--src/main.zig12
-rw-r--r--src/output.zig2
4 files changed, 116 insertions, 28 deletions
diff --git a/src/config.zig b/src/config.zig
index 3ef8a9e..14f0402 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -3,12 +3,12 @@ const fs = @import("std").fs;
const std = @import("std");
const debug = @import("std").debug;
-pub const OutputType = enum {
- window,
-};
-
pub const OutputConfig = struct {
- type: OutputType,
+ const Type = enum {
+ window,
+ };
+
+ type: Type,
width: i32,
height: i32,
@@ -22,8 +22,22 @@ pub const ParameterConfig = struct {
type: []const u8,
};
+pub const OSCConfig = union(enum) {
+ const Protocol = enum {
+ udp,
+ tcp,
+ unix,
+ };
+
+ Manual: struct {
+ protocol: Protocol = Protocol.udp,
+ port: u16 = 9000,
+ },
+ URL: []const u8,
+};
+
const defaultOutput = OutputConfig{
- .type = OutputType.window,
+ .type = .window,
.width = 800,
.height = 600,
.monitor = "",
@@ -36,15 +50,14 @@ pub const Config = struct {
outputs: []const OutputConfig,
fragment: []const u8,
parameters: []const ParameterConfig,
- arena: std.heap.ArenaAllocator,
+ osc: OSCConfig,
- pub fn parse(filename: []const u8) !Config {
+ pub fn parse(allocator: *std.mem.Allocator, filename: []const u8) !Config {
var parser: c.yaml_parser_t = undefined;
_ = c.yaml_parser_initialize(&parser);
defer c.yaml_parser_delete(&parser);
const file = try fs.cwd().openFile(filename, .{});
- // c.yaml_parser_set_input_file(&parser, @as([*c]c.FILE, file.handle));
var buffer: [1024]u8 = undefined;
const len: usize = try file.read(buffer[0..]);
c.yaml_parser_set_input_string(&parser, &buffer[0], len);
@@ -55,7 +68,7 @@ pub const Config = struct {
.outputs = ([_]OutputConfig{defaultOutput})[0..],
.fragment = "",
.parameters = ([0]ParameterConfig{})[0..],
- .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
+ .osc = .{ .URL = "osc.udp://localhost:9000" },
};
try expectEvent(&parser, c.yaml_event_type_t.YAML_STREAM_START_EVENT);
@@ -79,11 +92,13 @@ pub const Config = struct {
} else if (std.mem.eql(u8, key, "height")) {
config.height = try parseInt(&parser, i32);
} else if (std.mem.eql(u8, key, "fragment")) {
- config.fragment = try parseString(&parser, &config.arena.allocator);
+ config.fragment = try parseString(&parser, allocator);
} else if (std.mem.eql(u8, key, "outputs")) {
- config.outputs = try parseOutputs(&parser, &config.arena.allocator);
+ config.outputs = try parseOutputs(&parser, allocator);
} else if (std.mem.eql(u8, key, "parameters")) {
- config.parameters = try parseParameters(&parser, &config.arena.allocator);
+ config.parameters = try parseParameters(&parser, allocator);
+ } else if (std.mem.eql(u8, key, "osc")) {
+ config.osc = try parseOSC(&parser, allocator);
} else {
debug.warn("unknown key: '{}'\n", .{key});
try skipAny(&parser);
@@ -116,12 +131,7 @@ fn expectEvent(parser: *c.yaml_parser_t, expectedType: c.yaml_event_type_t) !voi
}
}
-fn parseString(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]const u8 {
- var event: c.yaml_event_t = undefined;
- if (c.yaml_parser_parse(parser, &event) != 1)
- return error.YAMLParserError;
- defer c.yaml_event_delete(&event);
-
+fn parseStringEvent(event: *c.yaml_event_t, allocator: *std.mem.Allocator) ![]const u8 {
if (event.type != c.yaml_event_type_t.YAML_SCALAR_EVENT)
return error.InvalidType;
@@ -130,6 +140,15 @@ fn parseString(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]const
return try std.mem.dupe(allocator, u8, value);
}
+fn parseString(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]const u8 {
+ var event: c.yaml_event_t = undefined;
+ if (c.yaml_parser_parse(parser, &event) != 1)
+ return error.YAMLParserError;
+ defer c.yaml_event_delete(&event);
+
+ return parseStringEvent(&event, allocator);
+}
+
fn parseInt(parser: *c.yaml_parser_t, comptime T: type) !T {
var event: c.yaml_event_t = undefined;
if (c.yaml_parser_parse(parser, &event) != 1)
@@ -212,7 +231,7 @@ fn parseOutputs(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]Outp
const key: []const u8 = data.value[0..data.length];
if (std.mem.eql(u8, key, "type")) {
- output.*.type = try parseEnum(parser, OutputType);
+ output.*.type = try parseEnum(parser, OutputConfig.Type);
} else if (std.mem.eql(u8, key, "width")) {
output.*.width = try parseInt(parser, i32);
} else if (std.mem.eql(u8, key, "height")) {
@@ -313,6 +332,52 @@ fn parseParameters(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]P
return parameters[0..param_count];
}
+fn parseOSC(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) !OSCConfig {
+ var event: c.yaml_event_t = undefined;
+ if (c.yaml_parser_parse(parser, &event) != 1)
+ return error.YAMLParserError;
+ defer c.yaml_event_delete(&event);
+
+ if (event.type == c.yaml_event_type_t.YAML_SCALAR_EVENT) {
+ const url = try parseStringEvent(&event, allocator);
+ return OSCConfig{ .URL = url };
+ } else if (event.type != c.yaml_event_type_t.YAML_MAPPING_START_EVENT) {
+ debug.warn("unexpected event: {}\n", .{event.type});
+ return error.InvalidConfiguration;
+ }
+
+ var config: OSCConfig = .{ .Manual = .{} };
+
+ while (true) {
+ if (c.yaml_parser_parse(parser, &event) != 1)
+ return error.YAMLParserError;
+ defer c.yaml_event_delete(&event);
+
+ switch (event.type) {
+ c.yaml_event_type_t.YAML_MAPPING_END_EVENT => break,
+ c.yaml_event_type_t.YAML_SCALAR_EVENT => {
+ const data = event.data.scalar;
+ const key: []const u8 = data.value[0..data.length];
+
+ if (std.mem.eql(u8, key, "protocol")) {
+ config.Manual.protocol = try parseEnum(parser, OSCConfig.Protocol);
+ } else if (std.mem.eql(u8, key, "port")) {
+ config.Manual.port = try parseInt(parser, u16);
+ } else {
+ debug.warn("unknown key: '{}'\n", .{key});
+ try skipAny(parser);
+ }
+ },
+ else => {
+ debug.warn("unexpected event: {}\n", .{event.type});
+ return error.InvalidConfiguration;
+ },
+ }
+ }
+
+ return config;
+}
+
fn skipAny(parser: *c.yaml_parser_t) !void {
var event: c.yaml_event_t = undefined;
var depth: u32 = 0;
diff --git a/src/control.zig b/src/control.zig
index 4937bb7..1a80147 100644
--- a/src/control.zig
+++ b/src/control.zig
@@ -1,6 +1,7 @@
const c = @import("c.zig");
const gl = @import("gl.zig");
const std = @import("std");
+const cfg = @import("config.zig");
const param_prefix = "/param/";
@@ -8,10 +9,30 @@ pub const ControlServer = struct {
server: c.lo_server,
shader: gl.ShaderProgram,
- pub fn init(allocator: *std.mem.Allocator) !*ControlServer {
+ pub fn init(allocator: *std.mem.Allocator, config: cfg.OSCConfig) !*ControlServer {
var self: *ControlServer = try allocator.create(ControlServer);
- self.server = c.lo_server_new("1234", handle_error);
+ switch (config) {
+ .Manual => |conf| {
+ var port = [_]u8{0} ** 6;
+ _ = std.fmt.formatIntBuf(port[0..], conf.port, 10, false, std.fmt.FormatOptions{});
+ const proto: c_int = switch (conf.protocol) {
+ .udp => c.LO_UDP,
+ .tcp => c.LO_TCP,
+ .unix => c.LO_UNIX,
+ else => unreachable,
+ };
+
+ std.debug.warn("listening for OSC messages on {} port {}\n", .{conf.protocol, conf.port});
+ self.server = c.lo_server_new_with_proto(&port[0], proto, handle_error);
+ },
+ .URL => |url| {
+ std.debug.warn("listening for OSC messages at {s}\n", .{url});
+ self.server = c.lo_server_new_from_url(&url[0], handle_error);
+ },
+ else => unreachable,
+ }
+
_ = c.lo_server_add_method(self.server, null, null, handle_method, @ptrCast(*c_void, self));
return self;
diff --git a/src/main.zig b/src/main.zig
index 41ad341..bde9767 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -16,8 +16,10 @@ fn errorCallback(err: c_int, description: [*c]const u8) callconv(.C) void {
}
pub fn main() !void {
- var config = try cfg.Config.parse("config.yaml");
- defer config.arena.deinit();
+ var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+ defer arena.deinit();
+
+ var config = try cfg.Config.parse(&arena.allocator, "config.yaml");
_ = c.glfwSetErrorCallback(errorCallback);
@@ -52,10 +54,10 @@ pub fn main() !void {
var constants = try gl.Constants.create(window);
defer constants.destroy();
- var outputs = try std.ArrayList(*out.Output).initCapacity(&config.arena.allocator, config.outputs.len);
+ var outputs = try std.ArrayList(*out.Output).initCapacity(&arena.allocator, config.outputs.len);
defer outputs.deinit();
for (config.outputs) |output_config, i| {
- try outputs.append(out.Output.create(&config.arena.allocator, output_config, &constants));
+ try outputs.append(out.Output.create(&arena.allocator, output_config, &constants));
}
defer for (outputs.toSlice()) |output| {
output.destroy(output);
@@ -106,7 +108,7 @@ pub fn main() !void {
var offset: f32 = 0;
- const control = try ctrl.ControlServer.init(&config.arena.allocator);
+ const control = try ctrl.ControlServer.init(&arena.allocator, config.osc);
defer control.destroy();
while (c.glfwWindowShouldClose(window) == c.GL_FALSE) {
diff --git a/src/output.zig b/src/output.zig
index b2368d8..c31c191 100644
--- a/src/output.zig
+++ b/src/output.zig
@@ -16,7 +16,7 @@ pub const Output = struct {
pub fn create(allocator: *std.mem.Allocator, config: cfg.OutputConfig, constants: *gl.Constants) *Output {
return switch (config.type) {
- cfg.OutputType.window => WindowOutput.create(allocator, config, constants),
+ .window => WindowOutput.create(allocator, config, constants),
else => unreachable,
};
}