diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-25 16:36:11 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-25 16:57:31 +0000 |
| commit | 9d2d72db724de3b21a7ade4623c3b1a8603e85f3 (patch) | |
| tree | 3f2ef21dfcc66db486b4871c2352ece0eea744e4 /src | |
| parent | basic OSC support (diff) | |
| download | glsl-view-9d2d72db724de3b21a7ade4623c3b1a8603e85f3.tar.gz glsl-view-9d2d72db724de3b21a7ade4623c3b1a8603e85f3.zip | |
OSC configuration in config.yaml
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.zig | 105 | ||||
| -rw-r--r-- | src/control.zig | 25 | ||||
| -rw-r--r-- | src/main.zig | 12 | ||||
| -rw-r--r-- | src/output.zig | 2 |
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, }; } |
