From d86e9efe433f53194f9fc5c03c39d4fcc4a61c8b Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 16:57:00 -0300 Subject: [PATCH 01/69] add main command struct and make fillKeywords mostly-comptime --- src/lang.zig | 81 ++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 34c5004..88dcda1 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -51,6 +51,37 @@ pub const CommandType = enum { Rotate, }; +pub const Type = enum { + /// "LV2 Commands" are commands that receive split, index, and then receive + /// any f64 arguments. + lv2_command, +}; + +pub const NewCommand = struct { + pub const Noop = struct {}; + + pub const Load = struct { + path: []const u8, + }; + + pub const Quicksave = struct {}; + + pub const RunQS = struct { + program: []const u8, + }; + + pub const Amp = struct { + pub const base_type = Type.lv2_command; + gain: f64 + }; + + pub const RFlanger = struct { + pub const base_type = Type.lv2_command; + delay_depth_avg: f64, + law_freq: f64, + }; +}; + pub const Command = struct { command: CommandType, args: ArgList, @@ -182,48 +213,18 @@ pub const Lang = struct { } fn fillKeywords(self: *Lang) !void { - _ = try self.keywords.put("noop", .Noop); - _ = try self.keywords.put("load", .Load); - _ = try self.keywords.put("quicksave", .Quicksave); - _ = try self.keywords.put("runqs", .RunQS); + inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { + const struct_name = cmd_struct_decl.name; - _ = try self.keywords.put("amp", .Amp); - _ = try self.keywords.put("rflanger", .RFlanger); - _ = try self.keywords.put("eq", .Eq); - _ = try self.keywords.put("mbeq", .Mbeq); - _ = try self.keywords.put("phaser", .Phaser); - _ = try self.keywords.put("chorus", .Chorus); - _ = try self.keywords.put("pitchscaler", .PitchScaler); - _ = try self.keywords.put("reverb", .Reverb); - _ = try self.keywords.put("highpass", .Highpass); - _ = try self.keywords.put("delay", .Delay); - _ = try self.keywords.put("vinyl", .Vinyl); - _ = try self.keywords.put("revdelay", .RevDelay); - _ = try self.keywords.put("gate", .Gate); - _ = try self.keywords.put("detune", .Detune); - _ = try self.keywords.put("overdrive", .Overdrive); - _ = try self.keywords.put("talkbox", .TalkBox); - _ = try self.keywords.put("thruzero", .ThruZero); - _ = try self.keywords.put("foverdrive", .Foverdrive); - _ = try self.keywords.put("gverb", .Gverb); - _ = try self.keywords.put("invert", .Invert); - _ = try self.keywords.put("tapedelay", .TapeDelay); - _ = try self.keywords.put("moddelay", .ModDelay); - _ = try self.keywords.put("multichorus", .MultiChorus); - _ = try self.keywords.put("saturator", .Saturator); - _ = try self.keywords.put("vintagedelay", .VintageDelay); + comptime var lowered_command_name = [_]u8{0} ** struct_name.len; + comptime { + for (struct_name) |c, i| { + lowered_command_name[i] = std.ascii.toLower(c); + } + } - // custom implementations (not lv2) - _ = try self.keywords.put("noise", .Noise); - _ = try self.keywords.put("wildnoise", .WildNoise); - _ = try self.keywords.put("write", .Write); - _ = try self.keywords.put("embed", .Embed); - _ = try self.keywords.put("degrade", .Degrade); - _ = try self.keywords.put("repsycho", .RePsycho); - _ = try self.keywords.put("dyncomp", .RePsycho); - - // even more custom - _ = try self.keywords.put("rotate", .Rotate); + _ = try self.keywords.put(&lowered_command_name, @field(CommandType, struct_name)); + } } pub fn getCommand(self: *Lang, stmt: []const u8) ?CommandType { From 27f499dfbb2dd926611865babbab90e58a96dcb5 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 17:48:14 -0300 Subject: [PATCH 02/69] add basics of generic command parsing --- src/lang.zig | 63 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 88dcda1..2b3c003 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -318,32 +318,51 @@ pub const Lang = struct { self.doError("No command given", .{}); continue; } - var command = cmd_opt.?; + const command_string = cmd_opt.?; - var ctype_opt = self.getCommand(command); - var ctype: CommandType = undefined; - if (ctype_opt) |ctype_val| { - ctype = ctype_val; - } else { - self.doError("Unknown command '{}' ({})", .{ command, command.len }); + var found: bool = false; + + inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { + const struct_name = cmd_struct_decl.name; + comptime var lowered_command_name = [_]u8{0} ** struct_name.len; + comptime { + for (struct_name) |c, i| { + lowered_command_name[i] = std.ascii.toLower(c); + } + } + + if (std.mem.eql(u8, &lowered_command_name, command_string)) { + found = true; + + // Based on the command struct fields, we need to decide + // how to actually get its arguments and creating the struct + // itself. + + const command_struct = cmd_struct_decl.data.Type; + var cmd: command_struct = undefined; + inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { + + // TODO: crash when no arguments are left but we still need + // arguments... + const argument = tok_it.next().?; + const argument_value = switch (cmd_field.field_type) { + usize => try std.fmt.parseInt(usize, arg, 10), + i32 => try std.fmt.parseInt(i32, arg, 10), + f32 => try std.fmt.parseFloat(f32, arg), + else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), + }; + + @field(cmd, cmd_field.name) = argument_value; + } + } + } + + if (!found) { + self.doError("Unknown command '{}' ({})", .{ command_string, command_string.len }); continue; } - var args = ArgList.init(self.allocator); - errdefer args.deinit(); - - while (tok_it.next()) |arg| { - try args.append(arg); - } - - // construct final Command based on command - var cmd = Command{ .command = ctype, .args = args }; - self.validateCommand(cmd) catch |err| { - //self.doError("error validating command '{}': {}", command, err); - continue; - }; - - try cmds.append(cmd); + // try cmds.append(cmd); } if (self.has_error) return ParseError.ParseFail; From 154032f9b17c0a21cf8002134a61865e32b52e03 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:25:30 -0300 Subject: [PATCH 03/69] revamp command structure for tags and base types --- src/lang.zig | 155 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 129 insertions(+), 26 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 2b3c003..8a2a9ce 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -58,25 +58,91 @@ pub const Type = enum { }; pub const NewCommand = struct { - pub const Noop = struct {}; + tag: Tag, + + pub const Tag = enum { + noop, + load, + quicksave, + runqs, + + amp, + rflanger, + eq, + phaser, + mbeq, + chorus, + pitchscaler, + reverb, + highpass, + delay, + vinyl, + revdelay, + gate, + detune, + overdrive, + degrade, + repsycho, + talkbox, + dyncomp, + thruzero, + foverdrive, + gverb, + invert, + tapedelay, + moddelay, + multichorus, + saturator, + vintagedelay, + + noise, + wildnoise, + write, + embed, + + rotate, + }; + + pub fn cast(base: *@This(), comptime T: type) ?*T { + if (base.tag != T.base_tag) + return null; + + return @fieldParentPtr(T, "base", base); + } + + pub const Noop = struct { + pub const base_tag = Tag.noop; + base: NewCommand, + }; pub const Load = struct { + pub const base_tag = Tag.load; + base: NewCommand, path: []const u8, }; - pub const Quicksave = struct {}; + pub const Quicksave = struct { + pub const base_tag = Tag.quicksave; + base: NewCommand, + }; pub const RunQS = struct { + pub const base_tag = Tag.runqs; program: []const u8, + base: NewCommand, }; pub const Amp = struct { + pub const base_tag = Tag.amp; pub const base_type = Type.lv2_command; + base: NewCommand, gain: f64 }; pub const RFlanger = struct { + pub const base_tag = Tag.rflanger; pub const base_type = Type.lv2_command; + base: NewCommand, delay_depth_avg: f64, law_freq: f64, }; @@ -183,7 +249,7 @@ pub const Command = struct { } }; -pub const CommandList = std.ArrayList(Command); +pub const CommandList = std.ArrayList(NewCommand); pub const ArgList = std.ArrayList([]const u8); pub const KeywordMap = std.StringHashMap(CommandType); @@ -214,6 +280,14 @@ pub const Lang = struct { fn fillKeywords(self: *Lang) !void { inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { + switch (cmd_struct_decl.data) { + .Type => |typ| switch (@typeInfo(typ)) { + .Struct => {}, + else => continue, + }, + else => continue, + } + const struct_name = cmd_struct_decl.name; comptime var lowered_command_name = [_]u8{0} ** struct_name.len; @@ -297,9 +371,42 @@ pub const Lang = struct { self.has_error = true; } + fn parseCommandArguments( + self: *@This(), + comptime command_struct: type, + tok_it: *std.mem.TokenIterator, + commands: *CommandList, + ) !void { + // Based on the command struct fields, we can parse the arguments. + var cmd = try self.allocator.create(command_struct); + + inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { + comptime { + if (std.mem.eql(u8, cmd_field.name, "base")) { + continue; + } + } + + // TODO: crash when no arguments are left but we still need + // arguments... + const arg = tok_it.next().?; + const argument_value = switch (cmd_field.field_type) { + usize => try std.fmt.parseInt(usize, arg, 10), + i32 => try std.fmt.parseInt(i32, arg, 10), + f32 => try std.fmt.parseFloat(f32, arg), + []const u8 => arg, + else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), + }; + + @field(cmd, cmd_field.name) = argument_value; + } + + try commands.append(cmd.base); + } + pub fn parse(self: *Lang, data: []const u8) ParseError!CommandList { var splitted_it = std.mem.split(data, ";"); - try self.fillKeywords(); + // try self.fillKeywords(); var cmds = CommandList.init(self.allocator); while (splitted_it.next()) |stmt_orig| { @@ -310,7 +417,7 @@ pub const Lang = struct { if (stmt.len == 0) continue; if (std.mem.startsWith(u8, stmt, "#")) continue; - // TODO better tokenizer instead of just tokenize(" "); + // TODO better tokenizer instead of just tokenize(" ")...maybe???? var tok_it = std.mem.tokenize(stmt, " "); var cmd_opt = tok_it.next(); @@ -323,6 +430,14 @@ pub const Lang = struct { var found: bool = false; inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { + switch (cmd_struct_decl.data) { + .Type => |typ| switch (@typeInfo(typ)) { + .Struct => {}, + else => continue, + }, + else => continue, + } + const struct_name = cmd_struct_decl.name; comptime var lowered_command_name = [_]u8{0} ** struct_name.len; comptime { @@ -331,29 +446,17 @@ pub const Lang = struct { } } + // if we have a match, we know the proper struct type + // to use. this actually works compared to storing command_struct + // in a variable because then that variable must be comptime. + + // the drawback of this approach is that our emitted code is basically linear + // because we don't use the hashmap anymore. maybe #5359 can help. + if (std.mem.eql(u8, &lowered_command_name, command_string)) { found = true; - - // Based on the command struct fields, we need to decide - // how to actually get its arguments and creating the struct - // itself. - - const command_struct = cmd_struct_decl.data.Type; - var cmd: command_struct = undefined; - inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { - - // TODO: crash when no arguments are left but we still need - // arguments... - const argument = tok_it.next().?; - const argument_value = switch (cmd_field.field_type) { - usize => try std.fmt.parseInt(usize, arg, 10), - i32 => try std.fmt.parseInt(i32, arg, 10), - f32 => try std.fmt.parseFloat(f32, arg), - else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), - }; - - @field(cmd, cmd_field.name) = argument_value; - } + const cmd_struct_type = cmd_struct_decl.data.Type; + try self.parseCommandArguments(cmd_struct_type, &tok_it, &cmds); } } From f20079b807f5d0a015024f8a9242da21706787c1 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:25:43 -0300 Subject: [PATCH 04/69] disable codepaths not supporting new commands --- src/main.zig | 3 ++- src/runner.zig | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main.zig b/src/main.zig index 04bcf2d..9971f24 100644 --- a/src/main.zig +++ b/src/main.zig @@ -185,7 +185,8 @@ pub fn main() !void { const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path or 'repl'")); if (std.mem.eql(u8, scri_path, "repl")) { - return try doRepl(allocator, &args_it); + @panic("TODO bring repl back"); + // return try doRepl(allocator, &args_it); } var file = try std.fs.cwd().openFile(scri_path, .{}); diff --git a/src/runner.zig b/src/runner.zig index 6276954..5496e8a 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -374,6 +374,8 @@ pub const Runner = struct { try image.runPlugin("http://calf.sourceforge.net/plugins/VintageDelay", pos, params); } + fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void {} + fn runCommand(self: *Runner, cmd: *lang.Command) !void { var params = ParamList.init(self.allocator); defer params.deinit(); @@ -775,14 +777,10 @@ pub const Runner = struct { cmds: lang.CommandList, debug_flag: bool, ) !void { - for (cmds.items) |const_cmd| { - if (debug_flag) const_cmd.print(); - - // copy the command so we own its memory - var cmd = try const_cmd.copy(self.allocator); - defer self.allocator.destroy(cmd); - - try self.runCommand(cmd); + for (cmds.items) |cmd| { + // TODO + // if (debug_flag) const_cmd.print(); + try self.newRunCommand(cmd); } } }; From c3b83c3e4b5d1a35ce7b740856b97596641303f7 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:29:13 -0300 Subject: [PATCH 05/69] replace f64 to f32 on some commands --- src/lang.zig | 8 ++++---- src/runner.zig | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 8a2a9ce..3b65c9d 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -136,15 +136,15 @@ pub const NewCommand = struct { pub const base_tag = Tag.amp; pub const base_type = Type.lv2_command; base: NewCommand, - gain: f64 + gain: f32 }; pub const RFlanger = struct { pub const base_tag = Tag.rflanger; pub const base_type = Type.lv2_command; base: NewCommand, - delay_depth_avg: f64, - law_freq: f64, + delay_depth_avg: f32, + law_freq: f32, }; }; @@ -404,7 +404,7 @@ pub const Lang = struct { try commands.append(cmd.base); } - pub fn parse(self: *Lang, data: []const u8) ParseError!CommandList { + pub fn parse(self: *Lang, data: []const u8) !CommandList { var splitted_it = std.mem.split(data, ";"); // try self.fillKeywords(); var cmds = CommandList.init(self.allocator); diff --git a/src/runner.zig b/src/runner.zig index 5496e8a..bde8eb9 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -778,7 +778,6 @@ pub const Runner = struct { debug_flag: bool, ) !void { for (cmds.items) |cmd| { - // TODO // if (debug_flag) const_cmd.print(); try self.newRunCommand(cmd); } From 47a97636cd472769741666b81162ea71b5a553c4 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:39:45 -0300 Subject: [PATCH 06/69] enable command debug printing --- src/lang.zig | 17 +++++++++++++++++ src/runner.zig | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index 3b65c9d..ff406a9 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -103,6 +103,19 @@ pub const NewCommand = struct { rotate, }; + pub fn tagToType(tag: Tag) type { + return switch (tag) { + .noop => Noop, + .load => Load, + .quicksave => Quicksave, + .runqs => RunQS, + + .amp => Amp, + .rflanger => RFlanger, + else => @panic("TODO"), + }; + } + pub fn cast(base: *@This(), comptime T: type) ?*T { if (base.tag != T.base_tag) return null; @@ -110,6 +123,10 @@ pub const NewCommand = struct { return @fieldParentPtr(T, "base", base); } + pub fn print(base: *const @This()) void { + std.debug.warn("{}\n", .{base.tag}); + } + pub const Noop = struct { pub const base_tag = Tag.noop; base: NewCommand, diff --git a/src/runner.zig b/src/runner.zig index bde8eb9..eacc3c7 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -778,7 +778,7 @@ pub const Runner = struct { debug_flag: bool, ) !void { for (cmds.items) |cmd| { - // if (debug_flag) const_cmd.print(); + cmd.print(); try self.newRunCommand(cmd); } } From eb18d01cdd63d67fbccd54a3a336d813826c3ea2 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:39:52 -0300 Subject: [PATCH 07/69] copy struct base tag into command base tag --- src/lang.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lang.zig b/src/lang.zig index ff406a9..10df1be 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -418,6 +418,8 @@ pub const Lang = struct { @field(cmd, cmd_field.name) = argument_value; } + cmd.base.tag = command_struct.base_tag; + try commands.append(cmd.base); } From 6497fc1dd8d7a600c00c38bfbe5e9df8775a96ed Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:42:41 -0300 Subject: [PATCH 08/69] add split/index decls to Amp, RFlanger --- src/lang.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 10df1be..1a747b9 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -151,15 +151,17 @@ pub const NewCommand = struct { pub const Amp = struct { pub const base_tag = Tag.amp; - pub const base_type = Type.lv2_command; base: NewCommand, + split: usize, + index: usize, gain: f32 }; pub const RFlanger = struct { pub const base_tag = Tag.rflanger; - pub const base_type = Type.lv2_command; base: NewCommand, + split: usize, + index: usize, delay_depth_avg: f32, law_freq: f32, }; From 7d519b73b69de726fb8fbc67f9e07c2c261dd1c0 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 22:56:45 -0300 Subject: [PATCH 09/69] add runner support on command cast --- src/lang.zig | 2 +- src/runner.zig | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 1a747b9..07d3d50 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -116,7 +116,7 @@ pub const NewCommand = struct { }; } - pub fn cast(base: *@This(), comptime T: type) ?*T { + pub fn cast(base: *const @This(), comptime T: type) ?*const T { if (base.tag != T.base_tag) return null; diff --git a/src/runner.zig b/src/runner.zig index eacc3c7..024fa42 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -374,7 +374,23 @@ pub const Runner = struct { try image.runPlugin("http://calf.sourceforge.net/plugins/VintageDelay", pos, params); } - fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void {} + fn newRunCommandSingle( + self: *@This(), + cmd: lang.NewCommand, + comptime tag: lang.NewCommand.Tag, + ) !void { + comptime const typ = lang.NewCommand.tagToType(tag); + const command = cmd.cast(typ).?; + + std.debug.warn("{}\n", .{command}); + } + + fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void { + switch (cmd.tag) { + .load => try self.newRunCommandSingle(cmd, .load), + else => @panic("TODO"), + } + } fn runCommand(self: *Runner, cmd: *lang.Command) !void { var params = ParamList.init(self.allocator); From d518369314cc96348fe0604f314a591f51912aad Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 23:57:34 -0300 Subject: [PATCH 10/69] add random debug statements --- src/lang.zig | 2 +- src/runner.zig | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 07d3d50..77ec179 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -124,7 +124,7 @@ pub const NewCommand = struct { } pub fn print(base: *const @This()) void { - std.debug.warn("{}\n", .{base.tag}); + std.debug.warn("tag: {}\n", .{base.tag}); } pub const Noop = struct { diff --git a/src/runner.zig b/src/runner.zig index 024fa42..a27c945 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -381,6 +381,7 @@ pub const Runner = struct { ) !void { comptime const typ = lang.NewCommand.tagToType(tag); const command = cmd.cast(typ).?; + std.debug.warn("{} {}\n", .{ command.path.ptr, command.path.len }); std.debug.warn("{}\n", .{command}); } @@ -795,7 +796,15 @@ pub const Runner = struct { ) !void { for (cmds.items) |cmd| { cmd.print(); - try self.newRunCommand(cmd); + + switch (cmd.tag) { + .load => { + const proper_cmd = cmd.cast(lang.NewCommand.Load).?; + std.debug.warn("got load! {}\n", .{proper_cmd}); + }, + else => @panic("TODO"), + } + try self.newRunCommand(cmd.*); } } }; From 9c6387973fc5f2d70762905abd45ce38aaef5b9d Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 30 May 2020 23:57:42 -0300 Subject: [PATCH 11/69] convert command list to ptr command list, fixing mem issues --- src/lang.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 77ec179..c45aff8 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -268,7 +268,7 @@ pub const Command = struct { } }; -pub const CommandList = std.ArrayList(NewCommand); +pub const CommandList = std.ArrayList(*NewCommand); pub const ArgList = std.ArrayList([]const u8); pub const KeywordMap = std.StringHashMap(CommandType); @@ -413,21 +413,24 @@ pub const Lang = struct { usize => try std.fmt.parseInt(usize, arg, 10), i32 => try std.fmt.parseInt(i32, arg, 10), f32 => try std.fmt.parseFloat(f32, arg), - []const u8 => arg, + []const u8 => try self.allocator.dupe(u8, arg), else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), }; + std.debug.warn("parsing {}, arg of type {} => {}\n", .{ @typeName(command_struct), @typeName(@TypeOf(argument_value)), argument_value }); + @field(cmd, cmd_field.name) = argument_value; } cmd.base.tag = command_struct.base_tag; + const command = cmd.base.cast(command_struct).?; + std.debug.warn("cmd: {}\n", .{command}); - try commands.append(cmd.base); + try commands.append(&cmd.base); } pub fn parse(self: *Lang, data: []const u8) !CommandList { var splitted_it = std.mem.split(data, ";"); - // try self.fillKeywords(); var cmds = CommandList.init(self.allocator); while (splitted_it.next()) |stmt_orig| { From f9c18517345111994e123b11de3248362667aa4c Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 15:20:19 -0300 Subject: [PATCH 12/69] add support for generic lv2 command running --- src/lang.zig | 8 +++++- src/runner.zig | 69 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index c45aff8..0e8fdd0 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -51,7 +51,7 @@ pub const CommandType = enum { Rotate, }; -pub const Type = enum { +pub const NewCommandType = enum { /// "LV2 Commands" are commands that receive split, index, and then receive /// any f64 arguments. lv2_command, @@ -151,6 +151,9 @@ pub const NewCommand = struct { pub const Amp = struct { pub const base_tag = Tag.amp; + pub const command_type = NewCommandType.lv2_command; + pub const lv2_url = "http://lv2plug.in/plugins/eg-amp"; + base: NewCommand, split: usize, index: usize, @@ -159,6 +162,9 @@ pub const NewCommand = struct { pub const RFlanger = struct { pub const base_tag = Tag.rflanger; + pub const command_type = NewCommandType.lv2_command; + pub const lv2_url = "http://plugin.org.uk/swh-plugins/retroFlange"; + base: NewCommand, split: usize, index: usize, diff --git a/src/runner.zig b/src/runner.zig index a27c945..4ffa606 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -374,6 +374,38 @@ pub const Runner = struct { try image.runPlugin("http://calf.sourceforge.net/plugins/VintageDelay", pos, params); } + fn executeLV2Command(self: *@This(), command: var) !void { + const pos = plugin.Position{ + .split = command.split, + .index = command.index, + }; + + var params = ParamList.init(self.allocator); + defer params.deinit(); + + const typ = @TypeOf(command); + + inline for (@typeInfo(typ).Struct.fields) |cmd_field| { + // ignore fields that can't be symbols for lv2 execution + comptime { + if (std.mem.eql(u8, cmd_field.name, "base") or + std.mem.eql(u8, cmd_field.name, "split") or + std.mem.eql(u8, cmd_field.name, "index")) + { + continue; + } + } + + try params.append(plugin.Param{ + .sym = cmd_field.name, + .value = @field(command, cmd_field.name), + }); + } + + var image = try self.getImage(); + try image.runPlugin(typ.lv2_url, pos, params); + } + fn newRunCommandSingle( self: *@This(), cmd: lang.NewCommand, @@ -381,15 +413,36 @@ pub const Runner = struct { ) !void { comptime const typ = lang.NewCommand.tagToType(tag); const command = cmd.cast(typ).?; - std.debug.warn("{} {}\n", .{ command.path.ptr, command.path.len }); + inline for (@typeInfo(typ).Struct.decls) |decl| { + comptime { + if (!std.mem.eql(u8, decl.name, "command_type")) { + continue; + } + } - std.debug.warn("{}\n", .{command}); + const ctype = typ.command_type; + switch (ctype) { + .lv2_command => try self.executeLV2Command(command.*), + else => @panic("TODO support command type"), + } + } } fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void { + // .load => try self.newRunCommandSingle(cmd, .load), switch (cmd.tag) { - .load => try self.newRunCommandSingle(cmd, .load), - else => @panic("TODO"), + .load => { + const command = cmd.cast(lang.NewCommand.Load).?; + try self.loadCmd(command.path); + }, + .quicksave => { + try self.quicksaveCmd(); + }, + .amp => try self.newRunCommandSingle(cmd, .amp), + else => { + std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); + @panic("TODO support tag"); + }, } } @@ -796,14 +849,6 @@ pub const Runner = struct { ) !void { for (cmds.items) |cmd| { cmd.print(); - - switch (cmd.tag) { - .load => { - const proper_cmd = cmd.cast(lang.NewCommand.Load).?; - std.debug.warn("got load! {}\n", .{proper_cmd}); - }, - else => @panic("TODO"), - } try self.newRunCommand(cmd.*); } } From 94c9695110dc72e50943b89fffd27153f07b8ed7 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 16:55:50 -0300 Subject: [PATCH 13/69] add helper to make lv2 command structs --- src/lang.zig | 91 +++++++++++++++++++++++++++++++++++++++----------- src/runner.zig | 51 ++++++++++++++++------------ 2 files changed, 101 insertions(+), 41 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 0e8fdd0..2749610 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -57,6 +57,23 @@ pub const NewCommandType = enum { lv2_command, }; +fn LV2Command( + comptime tag: NewCommand.Tag, + comptime lv2_url: []const u8, + comptime LV2Parameters: type, +) type { + return struct { + pub const base_tag = tag; + pub const command_type = NewCommandType.lv2_command; + pub const lv2_url = lv2_url; + + base: NewCommand, + split: usize, + index: usize, + parameters: LV2Parameters, + }; +} + pub const NewCommand = struct { tag: Tag, @@ -112,6 +129,33 @@ pub const NewCommand = struct { .amp => Amp, .rflanger => RFlanger, + .eq => Eq, + .phaser => Phaser, + // .mbeq => Mbeq, + // .chorus => Chorus, + // .pitchscaler => Pitchscaler, + // .reverb => Reverb, + // .highpass => Highpass, + // .delay => Delay, + // .vinyl => Vinyl, + // .revdelay => Revdelay, + // .gate => Gate, + // .detune => Detune, + // .overdrive => Overdrive, + // .degrade => Degrade, + // .repsycho => Repsycho, + // .talkbox => Talkbox, + // .dyncomp => Dyncomp, + // .thruzero => Thruzero, + // .foverdrive => Foverdrive, + // .gverb => Gverb, + // .invert => Invert, + // .tapedelay => Tapedelay, + // .moddelay => Moddelay, + // .multichorus => Multichorus, + // .saturator => Saturator, + // .vintagedelay => Vintagedelay, + else => @panic("TODO"), }; } @@ -149,28 +193,37 @@ pub const NewCommand = struct { base: NewCommand, }; - pub const Amp = struct { - pub const base_tag = Tag.amp; - pub const command_type = NewCommandType.lv2_command; - pub const lv2_url = "http://lv2plug.in/plugins/eg-amp"; + pub const Amp = LV2Command( + .amp, + "http://lv2plug.in/plugins/eg-amp", + struct { + gain: f32 + }, + ); - base: NewCommand, - split: usize, - index: usize, - gain: f32 - }; + pub const RFlanger = LV2Command( + .rflanger, + "http://plugin.org.uk/swh-plugins/retroFlange", + struct { + delay_depth_avg: f32, law_freq: f32 + }, + ); - pub const RFlanger = struct { - pub const base_tag = Tag.rflanger; - pub const command_type = NewCommandType.lv2_command; - pub const lv2_url = "http://plugin.org.uk/swh-plugins/retroFlange"; + pub const Eq = LV2Command( + .rflanger, + "http://plugin.org.uk/swh-plugins/dj_eq_mono", + struct { + lo: f32, mid: f32, hi: f32 + }, + ); - base: NewCommand, - split: usize, - index: usize, - delay_depth_avg: f32, - law_freq: f32, - }; + pub const Phaser = LV2Command( + .rflanger, + "http://plugin.org.uk/swh-plugins/lfoPhaser", + struct { + lfo_rate: f32, lfo_depth: f32, fb: f32, spread: f32 + }, + ); }; pub const Command = struct { diff --git a/src/runner.zig b/src/runner.zig index 4ffa606..fe9db82 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -439,6 +439,35 @@ pub const Runner = struct { try self.quicksaveCmd(); }, .amp => try self.newRunCommandSingle(cmd, .amp), + + .rflanger => try self.newRunCommandSingle(cmd, .rflanger), + .eq => try self.newRunCommandSingle(cmd, .eq), + .phaser => try self.newRunCommandSingle(cmd, .phaser), + // .mbeq => try self.newRunCommandSingle(cmd, .mbeq), + // .chorus => try self.newRunCommandSingle(cmd, .chorus), + // .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), + // .reverb => try self.newRunCommandSingle(cmd, .reverb), + // .highpass => try self.newRunCommandSingle(cmd, .highpass), + // .delay => try self.newRunCommandSingle(cmd, .delay), + // .vinyl => try self.newRunCommandSingle(cmd, .vinyl), + // .revdelay => try self.newRunCommandSingle(cmd, .revdelay), + // .gate => try self.newRunCommandSingle(cmd, .gate), + // .detune => try self.newRunCommandSingle(cmd, .detune), + // .overdrive => try self.newRunCommandSingle(cmd, .overdrive), + // .degrade => try self.newRunCommandSingle(cmd, .degrade), + // .repsycho => try self.newRunCommandSingle(cmd, .repsycho), + // .talkbox => try self.newRunCommandSingle(cmd, .talkbox), + // .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), + // .thruzero => try self.newRunCommandSingle(cmd, .thruzero), + // .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), + // .gverb => try self.newRunCommandSingle(cmd, .gverb), + // .invert => try self.newRunCommandSingle(cmd, .invert), + // .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), + // .moddelay => try self.newRunCommandSingle(cmd, .moddelay), + // .multichorus => try self.newRunCommandSingle(cmd, .multichorus), + // .saturator => try self.newRunCommandSingle(cmd, .saturator), + // .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), + else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); @panic("TODO support tag"); @@ -465,28 +494,6 @@ pub const Runner = struct { .Quicksave => try self.quicksaveCmd(), .RunQS => try self.runQSCmd(cmd.args.items[0]), - .Amp => blk: { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "gain"); - try self.ampCmd(pos, params); - }, - - .RFlanger => blk: { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "delay_depth_avg"); - try cmd.appendParam(¶ms, "law_freq"); - try self.rFlangerCmd(pos, params); - }, - - .Eq => blk: { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "lo"); - try cmd.appendParam(¶ms, "mid"); - try cmd.appendParam(¶ms, "hi"); - - try self.eqCmd(pos, params); - }, - .Phaser => blk: { const pos = try cmd.consumePosition(); From b21960d37275380510a4f941ee6b3a718f01dd90 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 16:57:12 -0300 Subject: [PATCH 14/69] remove unused code off parser --- src/lang.zig | 93 +--------------------------------------------------- 1 file changed, 1 insertion(+), 92 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 2749610..883c468 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -335,7 +335,6 @@ pub const KeywordMap = std.StringHashMap(CommandType); /// A parser. pub const Lang = struct { allocator: *std.mem.Allocator, - keywords: KeywordMap, has_error: bool = false, line: usize = 0, @@ -343,105 +342,15 @@ pub const Lang = struct { pub fn init(allocator: *std.mem.Allocator) Lang { return Lang{ .allocator = allocator, - .keywords = KeywordMap.init(allocator), }; } - pub fn deinit(self: *Lang) void { - self.keywords.deinit(); - } + pub fn deinit(self: *Lang) void {} pub fn reset(self: *Lang) void { self.has_error = false; self.line = 0; } - - fn fillKeywords(self: *Lang) !void { - inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { - switch (cmd_struct_decl.data) { - .Type => |typ| switch (@typeInfo(typ)) { - .Struct => {}, - else => continue, - }, - else => continue, - } - - const struct_name = cmd_struct_decl.name; - - comptime var lowered_command_name = [_]u8{0} ** struct_name.len; - comptime { - for (struct_name) |c, i| { - lowered_command_name[i] = std.ascii.toLower(c); - } - } - - _ = try self.keywords.put(&lowered_command_name, @field(CommandType, struct_name)); - } - } - - pub fn getCommand(self: *Lang, stmt: []const u8) ?CommandType { - var kv_opt = self.keywords.get(stmt); - - if (kv_opt) |kv| { - return kv.value; - } else { - return null; - } - } - - fn expectAny(self: *Lang, count: usize, args: ArgList) !void { - if (args.items.len != count) { - self.doError("expected {} arguments, found {}", .{ count, args.items.len }); - return error.ArgRequired; - } - } - - fn expectSingle(self: *Lang, args: ArgList) !void { - return try self.expectAny(1, args); - } - - fn expectFloat(self: *Lang, count: usize, args: ArgList) !void { - var i: usize = 0; - - if (args.items.len != count) { - self.doError("expected {} arguments, found {}", .{ count, args.items.len }); - return error.ArgRequired; - } - - while (i < count) : (i += 1) { - var arg = args.items[i]; - _ = std.fmt.parseFloat(f32, arg) catch |err| { - std.debug.warn("failed to parse f32: {}\n", .{err}); - return error.FloatParseFail; - }; - } - } - - fn validateCommand(self: *Lang, cmd: Command) !void { - switch (cmd.command) { - .Quicksave, .Noop => {}, - .Load, .RunQS => try self.expectSingle(cmd.args), - .Amp => try self.expectFloat(3, cmd.args), - .RFlanger => try self.expectFloat(4, cmd.args), - .Eq => try self.expectFloat(5, cmd.args), - .Phaser => try self.expectFloat(6, cmd.args), - .Mbeq => try self.expectFloat(17, cmd.args), - .Chorus => try self.expectFloat(8, cmd.args), - .PitchScaler => try self.expectFloat(3, cmd.args), - .Reverb => try self.expectFloat(12, cmd.args), - .Highpass => try self.expectFloat(5, cmd.args), - .Delay => try self.expectFloat(12, cmd.args), - .Vinyl => try self.expectFloat(7, cmd.args), - .RevDelay => try self.expectFloat(7, cmd.args), - .Noise => try self.expectFloat(4, cmd.args), - .WildNoise => try self.expectFloat(4, cmd.args), - .Write => try self.expectFloat(3, cmd.args), - .Rotate => try self.expectAny(2, cmd.args), - .Embed => try self.expectAny(3, cmd.args), - else => std.debug.warn("WARN unchecked command {}\n", .{cmd.command}), - } - } - fn doError(self: *Lang, comptime fmt: []const u8, args: var) void { std.debug.warn("error at line {}: ", .{self.line}); std.debug.warn(fmt, args); From dca5d7b644683f1b4c31d84819b9864057ef6b09 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:08:35 -0300 Subject: [PATCH 15/69] parse lv2 commands' split/index automatically --- src/lang.zig | 65 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 883c468..fbc5bf7 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -366,28 +366,57 @@ pub const Lang = struct { ) !void { // Based on the command struct fields, we can parse the arguments. var cmd = try self.allocator.create(command_struct); + const is_lv2_command = switch (command_struct.base_tag) { + .noop, .load, .quicksave, .runqs => false, + else => command_struct.command_type == .lv2_command, + }; - inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { - comptime { - if (std.mem.eql(u8, cmd_field.name, "base")) { - continue; - } + // TODO: crash when no arguments are left but we still need + // arguments... + + if (is_lv2_command) { + cmd.split = try std.fmt.parseInt(usize, tok_it.next().?, 10); + cmd.index = try std.fmt.parseInt(usize, tok_it.next().?, 10); + + inline for (@typeInfo(@typeOf(command_struct.parameters)).Struct.fields) |cmd_field| { + const arg = tok_it.next().?; + const argument_value = switch (cmd_field.field_type) { + f32 => try std.fmt.parseFloat(f32, arg), + else => @compileError("LV2 parameter struct can only have f32 fields"), + }; + + std.debug.warn("parsing {}, arg of type {} => {}\n", .{ + @typeName(command_struct), + @typeName(@TypeOf(argument_value)), + argument_value, + }); + + @field(cmd.params, cmd_field.name) = argument_value; } + } else { + inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { + comptime { + if (std.mem.eql(u8, cmd_field.name, "base")) { + continue; + } + } + const arg = tok_it.next().?; + const argument_value = switch (cmd_field.field_type) { + usize => try std.fmt.parseInt(usize, arg, 10), + i32 => try std.fmt.parseInt(i32, arg, 10), + f32 => try std.fmt.parseFloat(f32, arg), + []const u8 => try self.allocator.dupe(u8, arg), + else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), + }; - // TODO: crash when no arguments are left but we still need - // arguments... - const arg = tok_it.next().?; - const argument_value = switch (cmd_field.field_type) { - usize => try std.fmt.parseInt(usize, arg, 10), - i32 => try std.fmt.parseInt(i32, arg, 10), - f32 => try std.fmt.parseFloat(f32, arg), - []const u8 => try self.allocator.dupe(u8, arg), - else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), - }; + std.debug.warn("parsing {}, arg of type {} => {}\n", .{ + @typeName(command_struct), + @typeName(@TypeOf(argument_value)), + argument_value, + }); - std.debug.warn("parsing {}, arg of type {} => {}\n", .{ @typeName(command_struct), @typeName(@TypeOf(argument_value)), argument_value }); - - @field(cmd, cmd_field.name) = argument_value; + @field(cmd.params, cmd_field.name) = argument_value; + } } cmd.base.tag = command_struct.base_tag; From dd1b493da24f56055f6df6284ce6d88af2999a3f Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:11:17 -0300 Subject: [PATCH 16/69] fix typo --- src/lang.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index fbc5bf7..d855a47 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -59,13 +59,13 @@ pub const NewCommandType = enum { fn LV2Command( comptime tag: NewCommand.Tag, - comptime lv2_url: []const u8, + comptime plugin_url: []const u8, comptime LV2Parameters: type, ) type { return struct { pub const base_tag = tag; pub const command_type = NewCommandType.lv2_command; - pub const lv2_url = lv2_url; + pub const lv2_url = plugin_url; base: NewCommand, split: usize, From b5512c45fb9362021104d71326fdeb0d6219ac84 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:11:26 -0300 Subject: [PATCH 17/69] fix fetching of lv2 params --- src/lang.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index d855a47..d13ef2f 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -378,7 +378,7 @@ pub const Lang = struct { cmd.split = try std.fmt.parseInt(usize, tok_it.next().?, 10); cmd.index = try std.fmt.parseInt(usize, tok_it.next().?, 10); - inline for (@typeInfo(@typeOf(command_struct.parameters)).Struct.fields) |cmd_field| { + inline for (@typeInfo(@TypeOf(cmd.parameters)).Struct.fields) |cmd_field| { const arg = tok_it.next().?; const argument_value = switch (cmd_field.field_type) { f32 => try std.fmt.parseFloat(f32, arg), @@ -391,7 +391,7 @@ pub const Lang = struct { argument_value, }); - @field(cmd.params, cmd_field.name) = argument_value; + @field(cmd.parameters, cmd_field.name) = argument_value; } } else { inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { From 5412934f277093214c99681c7a691ac4db638540 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:11:32 -0300 Subject: [PATCH 18/69] fix fetching of non-lv2 params --- src/lang.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index d13ef2f..44566e5 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -415,7 +415,7 @@ pub const Lang = struct { argument_value, }); - @field(cmd.params, cmd_field.name) = argument_value; + @field(cmd, cmd_field.name) = argument_value; } } From d09603c005794bd4e25e2edf130ec02f673a6512 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:11:40 -0300 Subject: [PATCH 19/69] add runner support for LV2Command() spec --- src/runner.zig | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index fe9db82..438ce0b 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -385,20 +385,10 @@ pub const Runner = struct { const typ = @TypeOf(command); - inline for (@typeInfo(typ).Struct.fields) |cmd_field| { - // ignore fields that can't be symbols for lv2 execution - comptime { - if (std.mem.eql(u8, cmd_field.name, "base") or - std.mem.eql(u8, cmd_field.name, "split") or - std.mem.eql(u8, cmd_field.name, "index")) - { - continue; - } - } - + inline for (@typeInfo(@TypeOf(command.parameters)).Struct.fields) |cmd_field| { try params.append(plugin.Param{ .sym = cmd_field.name, - .value = @field(command, cmd_field.name), + .value = @field(command.parameters, cmd_field.name), }); } From 8e0ebbe5e02ab5959e96af4bd743285abb49535c Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:16:57 -0300 Subject: [PATCH 20/69] remove old Command struct --- src/lang.zig | 146 +-------------------------------------------------- 1 file changed, 1 insertion(+), 145 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 44566e5..059e30b 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -9,49 +9,6 @@ pub const ParseError = error{ }; pub const CommandType = enum { - Noop, - Load, - Quicksave, - RunQS, - - Amp, - RFlanger, - Eq, - Phaser, - Mbeq, - Chorus, - PitchScaler, - Reverb, - Highpass, - Delay, - Vinyl, - RevDelay, - Gate, - Detune, - Overdrive, - Degrade, - RePsycho, - TalkBox, - DynComp, - ThruZero, - Foverdrive, - Gverb, - Invert, - TapeDelay, - ModDelay, - MultiChorus, - Saturator, - VintageDelay, - - Noise, - WildNoise, - Write, - Embed, - - Rotate, -}; - -pub const NewCommandType = enum { /// "LV2 Commands" are commands that receive split, index, and then receive /// any f64 arguments. lv2_command, @@ -64,7 +21,7 @@ fn LV2Command( ) type { return struct { pub const base_tag = tag; - pub const command_type = NewCommandType.lv2_command; + pub const command_type = CommandType.lv2_command; pub const lv2_url = plugin_url; base: NewCommand, @@ -226,107 +183,6 @@ pub const NewCommand = struct { ); }; -pub const Command = struct { - command: CommandType, - args: ArgList, - cur_idx: usize = 0, - - pub fn print(self: Command) void { - std.debug.warn("cmd:{}\n", .{self.command}); - } - - pub fn argAt(self: Command, idx: usize) ![]const u8 { - std.debug.warn("{} {}", .{ idx, self.args.items.len }); - - if (idx > (self.args.items.len - 1)) { - std.debug.warn("Expected argument at index {}\n", .{idx}); - return ParseError.ArgRequired; - } - - return self.args.items[idx]; - } - - pub fn usizeArgAt(self: Command, idx: usize) !usize { - var arg = try self.argAt(idx); - return try std.fmt.parseInt(usize, arg, 10); - } - - pub fn consumePosition(self: *Command) !plugin.Position { - self.cur_idx = 2; - return plugin.Position{ - .split = try self.usizeArgAt(0), - .index = try self.usizeArgAt(1), - }; - } - - pub fn intArgAt(self: Command, idx: usize) !i32 { - var arg = try self.argAt(idx); - return try std.fmt.parseInt(i32, arg, 10); - } - - pub fn floatArgAt(self: Command, idx: usize) !f32 { - var arg = try self.argAt(idx); - return try std.fmt.parseFloat(f32, arg); - } - - pub fn floatArgMany( - self: Command, - allocator: *std.mem.Allocator, - start_index: usize, - elements: usize, - default: f32, - ) ![]const f32 { - var i: usize = start_index; - var arr = std.ArrayList(f32).init(allocator); - - while (i < elements) : (i += 1) { - var value: f32 = self.floatArgAt(i) catch |err| blk: { - std.debug.warn("\tdoing default on arg {}\n", .{i}); - break :blk default; - }; - - try arr.append(value); - } - - return arr.items; - } - - pub fn appendParam( - self: *Command, - params: *plugin.ParamList, - symbol: []const u8, - ) !void { - var val = try self.floatArgAt(self.cur_idx); - self.cur_idx += 1; - - try params.append(plugin.Param{ - .sym = symbol, - .value = val, - }); - } - - pub fn appendParamMap( - self: *Command, - map: *plugin.ParamMap, - symbol: []const u8, - ) !void { - var val = try self.floatArgAt(self.cur_idx); - self.cur_idx += 1; - _ = try map.put(symbol, val); - } - - pub fn copy(self: Command, allocator: *std.mem.Allocator) !*Command { - var cmd = try allocator.create(Command); - cmd.* = Command{ - .command = self.command, - .args = self.args, - .cur_idx = self.cur_idx, - }; - - return cmd; - } -}; - pub const CommandList = std.ArrayList(*NewCommand); pub const ArgList = std.ArrayList([]const u8); From c6c31f5a60606cd519dd81421cb0352f63837bf1 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:18:36 -0300 Subject: [PATCH 21/69] rename NewCommand to Command --- src/lang.zig | 18 +++++++++--------- src/runner.zig | 11 +++++------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 059e30b..8b1e16e 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -15,7 +15,7 @@ pub const CommandType = enum { }; fn LV2Command( - comptime tag: NewCommand.Tag, + comptime tag: Command.Tag, comptime plugin_url: []const u8, comptime LV2Parameters: type, ) type { @@ -24,14 +24,14 @@ fn LV2Command( pub const command_type = CommandType.lv2_command; pub const lv2_url = plugin_url; - base: NewCommand, + base: Command, split: usize, index: usize, parameters: LV2Parameters, }; } -pub const NewCommand = struct { +pub const Command = struct { tag: Tag, pub const Tag = enum { @@ -130,24 +130,24 @@ pub const NewCommand = struct { pub const Noop = struct { pub const base_tag = Tag.noop; - base: NewCommand, + base: Command, }; pub const Load = struct { pub const base_tag = Tag.load; - base: NewCommand, + base: Command, path: []const u8, }; pub const Quicksave = struct { pub const base_tag = Tag.quicksave; - base: NewCommand, + base: Command, }; pub const RunQS = struct { pub const base_tag = Tag.runqs; program: []const u8, - base: NewCommand, + base: Command, }; pub const Amp = LV2Command( @@ -183,7 +183,7 @@ pub const NewCommand = struct { ); }; -pub const CommandList = std.ArrayList(*NewCommand); +pub const CommandList = std.ArrayList(*Command); pub const ArgList = std.ArrayList([]const u8); pub const KeywordMap = std.StringHashMap(CommandType); @@ -306,7 +306,7 @@ pub const Lang = struct { var found: bool = false; - inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| { + inline for (@typeInfo(Command).Struct.decls) |cmd_struct_decl| { switch (cmd_struct_decl.data) { .Type => |typ| switch (@typeInfo(typ)) { .Struct => {}, diff --git a/src/runner.zig b/src/runner.zig index 438ce0b..962cfcc 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -398,10 +398,10 @@ pub const Runner = struct { fn newRunCommandSingle( self: *@This(), - cmd: lang.NewCommand, - comptime tag: lang.NewCommand.Tag, + cmd: lang.Command, + comptime tag: lang.Command.Tag, ) !void { - comptime const typ = lang.NewCommand.tagToType(tag); + comptime const typ = lang.Command.tagToType(tag); const command = cmd.cast(typ).?; inline for (@typeInfo(typ).Struct.decls) |decl| { comptime { @@ -418,11 +418,10 @@ pub const Runner = struct { } } - fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void { - // .load => try self.newRunCommandSingle(cmd, .load), + fn newRunCommand(self: *@This(), cmd: lang.Command) !void { switch (cmd.tag) { .load => { - const command = cmd.cast(lang.NewCommand.Load).?; + const command = cmd.cast(lang.Command.Load).?; try self.loadCmd(command.path); }, .quicksave => { From 3a7009f9bf651947b2c25dd6c415927c931d8489 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:53:33 -0300 Subject: [PATCH 22/69] convert more commands to new form --- src/lang.zig | 196 +++++++++++++++++++++++++++++++++++++---- src/runner.zig | 234 ++++--------------------------------------------- 2 files changed, 197 insertions(+), 233 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 8b1e16e..4fb3fb4 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -88,23 +88,23 @@ pub const Command = struct { .rflanger => RFlanger, .eq => Eq, .phaser => Phaser, - // .mbeq => Mbeq, - // .chorus => Chorus, - // .pitchscaler => Pitchscaler, - // .reverb => Reverb, - // .highpass => Highpass, - // .delay => Delay, - // .vinyl => Vinyl, - // .revdelay => Revdelay, - // .gate => Gate, - // .detune => Detune, - // .overdrive => Overdrive, - // .degrade => Degrade, - // .repsycho => Repsycho, - // .talkbox => Talkbox, - // .dyncomp => Dyncomp, - // .thruzero => Thruzero, - // .foverdrive => Foverdrive, + .mbeq => Mbeq, + .chorus => Chorus, + .pitchscaler => Pitchscaler, + .reverb => Reverb, + .highpass => Highpass, + .delay => Delay, + .vinyl => Vinyl, + .revdelay => Revdelay, + .gate => Gate, + .detune => Detune, + .overdrive => Overdrive, + .degrade => Degrade, + .repsycho => Repsycho, + .talkbox => Talkbox, + .dyncomp => Dyncomp, + .thruzero => Thruzero, + .foverdrive => Foverdrive, // .gverb => Gverb, // .invert => Invert, // .tapedelay => Tapedelay, @@ -175,12 +175,172 @@ pub const Command = struct { ); pub const Phaser = LV2Command( - .rflanger, + .phaser, "http://plugin.org.uk/swh-plugins/lfoPhaser", struct { lfo_rate: f32, lfo_depth: f32, fb: f32, spread: f32 }, ); + + pub const Mbeq = LV2Command( + .mbeq, + "http://plugin.org.uk/swh-plugins/mbeq", + struct { + band_1: f32, + band_2: f32, + band_3: f32, + band_4: f32, + band_5: f32, + band_6: f32, + band_7: f32, + band_8: f32, + band_9: f32, + band_10: f32, + band_11: f32, + band_12: f32, + band_13: f32, + band_14: f32, + band_15: f32, + }, + ); + + pub const Chorus = LV2Command( + .chorus, + "http://plugin.org.uk/swh-plugins/multivoiceChorus", + struct { + voices: f32, + delay_base: f32, + voice_spread: f32, + detune: f32, + law_freq: f32, + attendb: f32, + }, + ); + + pub const Pitchscaler = LV2Command( + .pitchscaler, + "http://plugin.org.uk/swh-plugins/pitchScaleHQ", + struct { mult: f32 }, + ); + + pub const Reverb = LV2Command( + .reverb, + "http://invadarecords.com/plugins/lv2/erreverb/mono", + struct { + roomLength: f32, + roomWidth: f32, + roomHeight: f32, + sourceLR: f32, + sourceFB: f32, + listLR: f32, + listFB: f32, + hpf: f32, + warmth: f32, + diffusion: f32, + }, + ); + + pub const Highpass = LV2Command(.highpass, "http://invadarecords.com/plugins/lv2/filter/hpf/mono", struct { + freq: f32, + gain: f32, + noClip: f32, + }); + + pub const Delay = LV2Command(.delay, "http://plugin.org.uk/swh-plugins/delayorama", struct { + seed: f32, + gain: f32, + feedback_pc: f32, + tap_count: f32, + first_delay: f32, + delay_range: f32, + delay_scale: f32, + delay_rand_pc: f32, + gain_scale: f32, + wet: f32, + }); + + pub const Vinyl = LV2Command(.vinyl, "http://plugin.org.uk/swh-plugins/vynil", struct { + year: f32, + rpm: f32, + warp: f32, + click: f32, + wear: f32, + }); + + pub const Revdelay = LV2Command(.revdelay, "http://plugin.org.uk/swh-plugins/revdelay", struct { + delay_time: f32, + dry_level: f32, + wet_level: f32, + feedback: f32, + xfade_samp: f32, + }); + // pub const Noise= LV2Command(.,,struct{}); + pub const Gate = LV2Command(.gate, "http://hippie.lt/lv2/gate", struct { + @"switch": f32, + threshold: f32, + attack: f32, + hold: f32, + decay: f32, + gaterange: f32, + }); + pub const Detune = LV2Command(.detune, "http://drobilla.net/plugins/mda/Detune", struct { + @"switch": f32, + threshold: f32, + attack: f32, + hold: f32, + decay: f32, + gaterange: f32, + detune: f32, + mix: f32, + output: f32, + latency: f32, + }); + pub const Overdrive = LV2Command(.overdrive, "http://drobilla.net/plugins/mda/Overdrive", struct { + drive: f32, + muffle: f32, + output: f32, + }); + pub const Degrade = LV2Command(.degrade, "http://drobilla.net/plugins/mda/Degrade", struct { + headroom: f32, + quant: f32, + rate: f32, + post_filt: f32, + non_lin: f32, + output: f32, + }); + pub const Repsycho = LV2Command(.repsycho, "http://drobilla.net/plugins/mda/RePsycho", struct { + tune: f32, + fine: f32, + decay: f32, + thresh: f32, + hold: f32, + mix: f32, + quality: f32, + }); + pub const Talkbox = LV2Command(.talkbox, "http://drobilla.net/plugins/mda/TalkBox", struct { + wet: f32, + dry: f32, + carrier: f32, + quality: f32, + }); + pub const Dyncomp = LV2Command(.dyncomp, "http://gareus.org/oss/lv2/darc#mono", struct { + enable: f32, + hold: f32, + inputgain: f32, + threshold: f32, + ratio: f32, + attack: f32, + release: f32, + gain_min: f32, + gain_max: f32, + rms: f32, + }); + pub const Foverdrive = LV2Command(.foverdrive, "http://plugin.org.uk/swh-plugins/foverdrive", struct { + drive: f32, + }); + pub const Thruzero = LV2Command(.thruzero, "http://drobilla.net/plugins/mda/ThruZero", struct { + rate: f32, mix: f32, feedback: f32, depth_mod: f32 + }); }; pub const CommandList = std.ArrayList(*Command); diff --git a/src/runner.zig b/src/runner.zig index 962cfcc..b4bf4af 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -190,58 +190,6 @@ pub const Runner = struct { _ = try proc.spawnAndWait(); } - /// Run the http://lv2plug.in/plugins/eg-amp plugin over the file. - fn ampCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://lv2plug.in/plugins/eg-amp", pos, params); - } - - fn rFlangerCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/retroFlange", pos, params); - } - - fn eqCmd(self: *Runner, position: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/dj_eq_mono", position, params); - } - - fn phaserCmd(self: *Runner, position: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/lfoPhaser", position, params); - } - - fn mbeqCmd(self: *Runner, position: Position, bands: []const f32) !void { - var image = try self.getImage(); - var params = ParamList.init(self.allocator); - defer params.deinit(); - - for (bands) |band_value, idx| { - var sym = try std.fmt.allocPrint(self.allocator, "band_{}", .{idx + 1}); - try params.append(plugin.Param{ - .sym = sym, - .value = band_value, - }); - } - - try image.runPlugin("http://plugin.org.uk/swh-plugins/mbeq", position, params); - } - - fn chorusCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/multivoiceChorus", pos, params); - } - - fn pitchScalerCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/pitchScaleHQ", pos, params); - } - - fn reverbCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://invadarecords.com/plugins/lv2/erreverb/mono", pos, params); - } - fn highpassCmd(self: *Runner, pos: Position, params: ParamList) !void { var image = try self.getImage(); try image.runPlugin("http://invadarecords.com/plugins/lv2/filter/hpf/mono", pos, params); @@ -432,23 +380,23 @@ pub const Runner = struct { .rflanger => try self.newRunCommandSingle(cmd, .rflanger), .eq => try self.newRunCommandSingle(cmd, .eq), .phaser => try self.newRunCommandSingle(cmd, .phaser), - // .mbeq => try self.newRunCommandSingle(cmd, .mbeq), - // .chorus => try self.newRunCommandSingle(cmd, .chorus), - // .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), - // .reverb => try self.newRunCommandSingle(cmd, .reverb), - // .highpass => try self.newRunCommandSingle(cmd, .highpass), - // .delay => try self.newRunCommandSingle(cmd, .delay), - // .vinyl => try self.newRunCommandSingle(cmd, .vinyl), - // .revdelay => try self.newRunCommandSingle(cmd, .revdelay), - // .gate => try self.newRunCommandSingle(cmd, .gate), - // .detune => try self.newRunCommandSingle(cmd, .detune), - // .overdrive => try self.newRunCommandSingle(cmd, .overdrive), - // .degrade => try self.newRunCommandSingle(cmd, .degrade), - // .repsycho => try self.newRunCommandSingle(cmd, .repsycho), - // .talkbox => try self.newRunCommandSingle(cmd, .talkbox), - // .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), - // .thruzero => try self.newRunCommandSingle(cmd, .thruzero), - // .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), + .mbeq => try self.newRunCommandSingle(cmd, .mbeq), + .chorus => try self.newRunCommandSingle(cmd, .chorus), + .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), + .reverb => try self.newRunCommandSingle(cmd, .reverb), + .highpass => try self.newRunCommandSingle(cmd, .highpass), + .delay => try self.newRunCommandSingle(cmd, .delay), + .vinyl => try self.newRunCommandSingle(cmd, .vinyl), + .revdelay => try self.newRunCommandSingle(cmd, .revdelay), + .gate => try self.newRunCommandSingle(cmd, .gate), + .detune => try self.newRunCommandSingle(cmd, .detune), + .overdrive => try self.newRunCommandSingle(cmd, .overdrive), + .degrade => try self.newRunCommandSingle(cmd, .degrade), + .repsycho => try self.newRunCommandSingle(cmd, .repsycho), + .talkbox => try self.newRunCommandSingle(cmd, .talkbox), + .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), + .thruzero => try self.newRunCommandSingle(cmd, .thruzero), + .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), // .gverb => try self.newRunCommandSingle(cmd, .gverb), // .invert => try self.newRunCommandSingle(cmd, .invert), // .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), @@ -483,112 +431,6 @@ pub const Runner = struct { .Quicksave => try self.quicksaveCmd(), .RunQS => try self.runQSCmd(cmd.args.items[0]), - .Phaser => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "lfo_rate"); - try cmd.appendParam(¶ms, "lfo_depth"); - try cmd.appendParam(¶ms, "fb"); - try cmd.appendParam(¶ms, "spread"); - - try self.phaserCmd(pos, params); - }, - - .Mbeq => blk: { - const pos = try cmd.consumePosition(); - const bands = try cmd.floatArgMany(self.allocator, 2, 15, @as(f32, 0)); - defer self.allocator.free(bands); - - try self.mbeqCmd(pos, bands); - }, - - .Chorus => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "voices"); - try cmd.appendParam(¶ms, "delay_base"); - try cmd.appendParam(¶ms, "voice_spread"); - try cmd.appendParam(¶ms, "detune"); - try cmd.appendParam(¶ms, "law_freq"); - try cmd.appendParam(¶ms, "attendb"); - - try self.chorusCmd(pos, params); - }, - - .PitchScaler => blk: { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "mult"); - try self.pitchScalerCmd(pos, params); - }, - - .Reverb => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "roomLength"); - try cmd.appendParam(¶ms, "roomWidth"); - try cmd.appendParam(¶ms, "roomHeight"); - try cmd.appendParam(¶ms, "sourceLR"); - try cmd.appendParam(¶ms, "sourceFB"); - try cmd.appendParam(¶ms, "listLR"); - try cmd.appendParam(¶ms, "listFB"); - try cmd.appendParam(¶ms, "hpf"); - try cmd.appendParam(¶ms, "warmth"); - try cmd.appendParam(¶ms, "diffusion"); - - try self.reverbCmd(pos, params); - }, - - .Highpass => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "freq"); - try cmd.appendParam(¶ms, "gain"); - try cmd.appendParam(¶ms, "noClip"); - - try self.highpassCmd(pos, params); - }, - - .Delay => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "seed"); - try cmd.appendParam(¶ms, "gain"); - try cmd.appendParam(¶ms, "feedback_pc"); - try cmd.appendParam(¶ms, "tap_count"); - try cmd.appendParam(¶ms, "first_delay"); - try cmd.appendParam(¶ms, "delay_range"); - try cmd.appendParam(¶ms, "delay_scale"); - try cmd.appendParam(¶ms, "delay_rand_pc"); - try cmd.appendParam(¶ms, "gain_scale"); - try cmd.appendParam(¶ms, "wet"); - - try self.delayCmd(pos, params); - }, - - .Vinyl => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "year"); - try cmd.appendParam(¶ms, "rpm"); - try cmd.appendParam(¶ms, "warp"); - try cmd.appendParam(¶ms, "click"); - try cmd.appendParam(¶ms, "wear"); - - try self.vinylCmd(pos, params); - }, - - .RevDelay => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParam(¶ms, "delay_time"); - try cmd.appendParam(¶ms, "dry_level"); - try cmd.appendParam(¶ms, "wet_level"); - try cmd.appendParam(¶ms, "feedback"); - try cmd.appendParam(¶ms, "xfade_samp"); - - try self.revDelayCmd(pos, params); - }, - .Noise => blk: { const pos = try cmd.consumePosition(); @@ -627,76 +469,38 @@ pub const Runner = struct { .Gate => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "switch"); - try cmd.appendParam(¶ms, "threshold"); - try cmd.appendParam(¶ms, "attack"); - try cmd.appendParam(¶ms, "hold"); - try cmd.appendParam(¶ms, "decay"); - try cmd.appendParam(¶ms, "gaterange"); try self.gateCmd(pos, params); }, .Detune => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "detune"); - try cmd.appendParam(¶ms, "mix"); - try cmd.appendParam(¶ms, "output"); - try cmd.appendParam(¶ms, "latency"); try self.detuneCmd(pos, params); }, .Overdrive => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "drive"); - try cmd.appendParam(¶ms, "muffle"); - try cmd.appendParam(¶ms, "output"); try self.overdriveCmd(pos, params); }, .Degrade => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "headroom"); - try cmd.appendParam(¶ms, "quant"); - try cmd.appendParam(¶ms, "rate"); - try cmd.appendParam(¶ms, "post_filt"); - try cmd.appendParam(¶ms, "non_lin"); - try cmd.appendParam(¶ms, "output"); try self.degradeCmd(pos, params); }, .RePsycho => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "tune"); - try cmd.appendParam(¶ms, "fine"); - try cmd.appendParam(¶ms, "decay"); - try cmd.appendParam(¶ms, "thresh"); - try cmd.appendParam(¶ms, "hold"); - try cmd.appendParam(¶ms, "mix"); - try cmd.appendParam(¶ms, "quality"); try self.repsychoCmd(pos, params); }, .TalkBox => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "wet"); - try cmd.appendParam(¶ms, "dry"); - try cmd.appendParam(¶ms, "carrier"); - try cmd.appendParam(¶ms, "quality"); + try self.talkboxCmd(pos, params); }, .DynComp => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "enable"); - try cmd.appendParam(¶ms, "hold"); - try cmd.appendParam(¶ms, "inputgain"); - try cmd.appendParam(¶ms, "threshold"); - try cmd.appendParam(¶ms, "ratio"); - try cmd.appendParam(¶ms, "attack"); - try cmd.appendParam(¶ms, "release"); - try cmd.appendParam(¶ms, "gain_min"); - try cmd.appendParam(¶ms, "gain_max"); - try cmd.appendParam(¶ms, "rms"); + try self.dynCompCmd(pos, params); }, From 0de2d05fa396d94ece6ac4b45c087682873d899a Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 17:54:43 -0300 Subject: [PATCH 23/69] fix detune command definition --- src/lang.zig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 4fb3fb4..6d444c9 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -284,12 +284,6 @@ pub const Command = struct { gaterange: f32, }); pub const Detune = LV2Command(.detune, "http://drobilla.net/plugins/mda/Detune", struct { - @"switch": f32, - threshold: f32, - attack: f32, - hold: f32, - decay: f32, - gaterange: f32, detune: f32, mix: f32, output: f32, From 325e7b110286ebbb19d36d819109c8a06c3f8236 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 18:29:42 -0300 Subject: [PATCH 24/69] add support for the rest of lv2 commands --- src/lang.zig | 100 ++++++++++++++++++++++++++++++--- src/runner.zig | 149 +++---------------------------------------------- 2 files changed, 101 insertions(+), 148 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 6d444c9..a455a1f 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -105,13 +105,13 @@ pub const Command = struct { .dyncomp => Dyncomp, .thruzero => Thruzero, .foverdrive => Foverdrive, - // .gverb => Gverb, - // .invert => Invert, - // .tapedelay => Tapedelay, - // .moddelay => Moddelay, - // .multichorus => Multichorus, - // .saturator => Saturator, - // .vintagedelay => Vintagedelay, + .gverb => Gverb, + .invert => Invert, + .tapedelay => Tapedelay, + .moddelay => Moddelay, + .multichorus => Multichorus, + .saturator => Saturator, + .vintagedelay => Vintagedelay, else => @panic("TODO"), }; @@ -335,6 +335,92 @@ pub const Command = struct { pub const Thruzero = LV2Command(.thruzero, "http://drobilla.net/plugins/mda/ThruZero", struct { rate: f32, mix: f32, feedback: f32, depth_mod: f32 }); + + pub const Gverb = LV2Command(.gverb, "http://plugin.org.uk/swh-plugins/gverb", struct { + roomsize: f32, + revtime: f32, + damping: f32, + inputbandwidth: f32, + drylevel: f32, + earlylevel: f32, + taillevel: f32, + }); + pub const Invert = LV2Command(.invert, "http://plugin.org.uk/swh-plugins/inv", struct {}); + pub const Tapedelay = LV2Command(.tapedelay, "http://plugin.org.uk/swh-plugins/tapeDelay", struct { + speed: f32, + da_db: f32, + + t1d: f32, + t1a_db: f32, + + t2d: f32, + t2a_db: f32, + + t3d: f32, + t3a_db: f32, + + t4d: f32, + t4a_db: f32, + }); + pub const Moddelay = LV2Command(.moddelay, "http://plugin.org.uk/swh-plugins/modDelay", struct { + base: f32, + }); + + pub const Multichorus = LV2Command(.multichorus, "http://calf.sourceforge.net/plugins/MultiChorus", struct { + min_delay: f32, + mod_depth: f32, + mod_rate: f32, + stereo: f32, + voices: f32, + vphase: f32, + amount: f32, + dry: f32, + freq: f32, + freq2: f32, + q: f32, + overlap: f32, + level_in: f32, + level_out: f32, + lfo: f32, + }); + pub const Saturator = LV2Command(.saturator, "http://calf.sourceforge.net/plugins/Saturator", struct { + bypass: f32, + level_in: f32, + level_out: f32, + mix: f32, + drive: f32, + blend: f32, + lp_pre_freq: f32, + hp_pre_freq: f32, + lp_post_freq: f32, + hp_post_freq: f32, + p_freq: f32, + p_level: f32, + p_q: f32, + pre: f32, + post: f32, + }); + pub const Vintagedelay = LV2Command(.vintagedelay, "http://calf.sourceforge.net/plugins/VintageDelay", struct { + level_in: f32, + level_out: f32, + subdiv: f32, + time_l: f32, + time_r: f32, + feedback: f32, + amount: f32, + mix_mode: f32, + medium: f32, + dry: f32, + width: f32, + fragmentation: f32, + pbeats: f32, + pfrag: f32, + timing: f32, + bpm: f32, + ms: f32, + hz: f32, + bpm_host: f32, + }); }; pub const CommandList = std.ArrayList(*Command); diff --git a/src/runner.zig b/src/runner.zig index b4bf4af..7922c30 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -292,11 +292,6 @@ pub const Runner = struct { try image.runPlugin("http://plugin.org.uk/swh-plugins/gverb", pos, params); } - fn invertCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/inv", pos, params); - } - fn tapedelayCmd(self: *Runner, pos: Position, params: ParamList) !void { var image = try self.getImage(); try image.runPlugin("http://plugin.org.uk/swh-plugins/tapeDelay", pos, params); @@ -397,13 +392,13 @@ pub const Runner = struct { .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), .thruzero => try self.newRunCommandSingle(cmd, .thruzero), .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), - // .gverb => try self.newRunCommandSingle(cmd, .gverb), - // .invert => try self.newRunCommandSingle(cmd, .invert), - // .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), - // .moddelay => try self.newRunCommandSingle(cmd, .moddelay), - // .multichorus => try self.newRunCommandSingle(cmd, .multichorus), - // .saturator => try self.newRunCommandSingle(cmd, .saturator), - // .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), + .gverb => try self.newRunCommandSingle(cmd, .gverb), + .invert => try self.newRunCommandSingle(cmd, .invert), + .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), + .moddelay => try self.newRunCommandSingle(cmd, .moddelay), + .multichorus => try self.newRunCommandSingle(cmd, .multichorus), + .saturator => try self.newRunCommandSingle(cmd, .saturator), + .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); @@ -467,67 +462,8 @@ pub const Runner = struct { try self.rotateCmd(deg, bgfill); }, - .Gate => { - const pos = try cmd.consumePosition(); - try self.gateCmd(pos, params); - }, - - .Detune => { - const pos = try cmd.consumePosition(); - try self.detuneCmd(pos, params); - }, - - .Overdrive => { - const pos = try cmd.consumePosition(); - try self.overdriveCmd(pos, params); - }, - - .Degrade => { - const pos = try cmd.consumePosition(); - try self.degradeCmd(pos, params); - }, - - .RePsycho => { - const pos = try cmd.consumePosition(); - try self.repsychoCmd(pos, params); - }, - - .TalkBox => { - const pos = try cmd.consumePosition(); - - try self.talkboxCmd(pos, params); - }, - - .DynComp => { - const pos = try cmd.consumePosition(); - - try self.dynCompCmd(pos, params); - }, - - .ThruZero => { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "rate"); - try cmd.appendParam(¶ms, "mix"); - try cmd.appendParam(¶ms, "feedback"); - try cmd.appendParam(¶ms, "depth_mod"); - try self.thruZeroCmd(pos, params); - }, - - .Foverdrive => { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "drive"); - try self.foverdriveCmd(pos, params); - }, - .Gverb => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "roomsize"); - try cmd.appendParam(¶ms, "revtime"); - try cmd.appendParam(¶ms, "damping"); - try cmd.appendParam(¶ms, "inputbandwidth"); - try cmd.appendParam(¶ms, "drylevel"); - try cmd.appendParam(¶ms, "earlylevel"); - try cmd.appendParam(¶ms, "taillevel"); try self.gverbCmd(pos, params); }, @@ -538,20 +474,6 @@ pub const Runner = struct { .TapeDelay => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "speed"); - try cmd.appendParam(¶ms, "da_db"); - - try cmd.appendParam(¶ms, "t1d"); - try cmd.appendParam(¶ms, "t1a_db"); - - try cmd.appendParam(¶ms, "t2d"); - try cmd.appendParam(¶ms, "t2a_db"); - - try cmd.appendParam(¶ms, "t3d"); - try cmd.appendParam(¶ms, "t3a_db"); - - try cmd.appendParam(¶ms, "t4d"); - try cmd.appendParam(¶ms, "t4a_db"); try self.tapedelayCmd(pos, params); }, @@ -564,73 +486,18 @@ pub const Runner = struct { .MultiChorus => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "min_delay"); - try cmd.appendParam(¶ms, "mod_depth"); - try cmd.appendParam(¶ms, "mod_rate"); - try cmd.appendParam(¶ms, "stereo"); - try cmd.appendParam(¶ms, "voices"); - try cmd.appendParam(¶ms, "vphase"); - try cmd.appendParam(¶ms, "amount"); - try cmd.appendParam(¶ms, "dry"); - try cmd.appendParam(¶ms, "freq"); - try cmd.appendParam(¶ms, "freq2"); - try cmd.appendParam(¶ms, "q"); - try cmd.appendParam(¶ms, "overlap"); - try cmd.appendParam(¶ms, "level_in"); - try cmd.appendParam(¶ms, "level_out"); - try cmd.appendParam(¶ms, "lfo"); + try self.multichorusCmd(pos, params); }, .Saturator => { const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "bypass"); - try cmd.appendParam(¶ms, "level_in"); - try cmd.appendParam(¶ms, "level_out"); - try cmd.appendParam(¶ms, "mix"); - try cmd.appendParam(¶ms, "drive"); - try cmd.appendParam(¶ms, "blend"); - try cmd.appendParam(¶ms, "lp_pre_freq"); - try cmd.appendParam(¶ms, "hp_pre_freq"); - try cmd.appendParam(¶ms, "lp_post_freq"); - try cmd.appendParam(¶ms, "hp_post_freq"); - try cmd.appendParam(¶ms, "p_freq"); - try cmd.appendParam(¶ms, "p_level"); - try cmd.appendParam(¶ms, "p_q"); - try cmd.appendParam(¶ms, "pre"); - try cmd.appendParam(¶ms, "post"); try self.saturatorCmd(pos, params); }, .VintageDelay => { const pos = try cmd.consumePosition(); - const PARAMS = [_][]const u8{ - "level_in", - "level_out", - "subdiv", - "time_l", - "time_r", - "feedback", - "amount", - "mix_mode", - "medium", - "dry", - "width", - "fragmentation", - "pbeats", - "pfrag", - "timing", - "bpm", - "ms", - "hz", - "bpm_host", - }; - - inline for (PARAMS) |param| { - try cmd.appendParam(¶ms, param); - } - try self.vintagedelayCmd(pos, params); }, From 7543ecafaa38e4ef7ba8d063162cc48a35fa34ac Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 18:30:39 -0300 Subject: [PATCH 25/69] remove unused blocks of code --- src/runner.zig | 134 ------------------------------------------------- 1 file changed, 134 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 7922c30..e65bac0 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -190,26 +190,6 @@ pub const Runner = struct { _ = try proc.spawnAndWait(); } - fn highpassCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://invadarecords.com/plugins/lv2/filter/hpf/mono", pos, params); - } - - fn delayCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/delayorama", pos, params); - } - - fn vinylCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/vynil", pos, params); - } - - fn revDelayCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/revdelay", pos, params); - } - fn noiseCmd(self: *Runner, pos: Position, map: *ParamMap) !void { var image = try self.getImage(); try image.runCustomPlugin(custom.RandomNoise, pos, *ParamMap, map); @@ -242,81 +222,6 @@ pub const Runner = struct { try magick.runRotate(image, deg, c_bgfill); } - fn gateCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://hippie.lt/lv2/gate", pos, params); - } - - fn detuneCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/Detune", pos, params); - } - - fn overdriveCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/Overdrive", pos, params); - } - - fn degradeCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/Degrade", pos, params); - } - - fn repsychoCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/RePsycho", pos, params); - } - - fn talkboxCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/TalkBox", pos, params); - } - - fn dynCompCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://gareus.org/oss/lv2/darc#mono", pos, params); - } - - fn foverdriveCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/foverdrive", pos, params); - } - - fn thruZeroCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://drobilla.net/plugins/mda/ThruZero", pos, params); - } - - fn gverbCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/gverb", pos, params); - } - - fn tapedelayCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/tapeDelay", pos, params); - } - - fn moddelayCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://plugin.org.uk/swh-plugins/modDelay", pos, params); - } - - fn multichorusCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://calf.sourceforge.net/plugins/MultiChorus", pos, params); - } - - fn saturatorCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://calf.sourceforge.net/plugins/Saturator", pos, params); - } - - fn vintagedelayCmd(self: *Runner, pos: Position, params: ParamList) !void { - var image = try self.getImage(); - try image.runPlugin("http://calf.sourceforge.net/plugins/VintageDelay", pos, params); - } - fn executeLV2Command(self: *@This(), command: var) !void { const pos = plugin.Position{ .split = command.split, @@ -462,45 +367,6 @@ pub const Runner = struct { try self.rotateCmd(deg, bgfill); }, - .Gverb => { - const pos = try cmd.consumePosition(); - try self.gverbCmd(pos, params); - }, - - .Invert => { - const pos = try cmd.consumePosition(); - try self.gverbCmd(pos, params); - }, - - .TapeDelay => { - const pos = try cmd.consumePosition(); - - try self.tapedelayCmd(pos, params); - }, - - .ModDelay => { - const pos = try cmd.consumePosition(); - try cmd.appendParam(¶ms, "base"); - try self.moddelayCmd(pos, params); - }, - - .MultiChorus => { - const pos = try cmd.consumePosition(); - - try self.multichorusCmd(pos, params); - }, - - .Saturator => { - const pos = try cmd.consumePosition(); - - try self.saturatorCmd(pos, params); - }, - - .VintageDelay => { - const pos = try cmd.consumePosition(); - try self.vintagedelayCmd(pos, params); - }, - else => blk: { std.debug.warn("Unsupported command: {}\n", .{cmd.command}); break :blk RunError.UnknownCommand; From 8ce844ceed75fb41abda0cecf2e461c8cff2f9dc Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:10:43 -0300 Subject: [PATCH 26/69] add validation for split/index args --- src/lang.zig | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index a455a1f..89ed749 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -362,9 +362,14 @@ pub const Command = struct { t4d: f32, t4a_db: f32, }); - pub const Moddelay = LV2Command(.moddelay, "http://plugin.org.uk/swh-plugins/modDelay", struct { - base: f32, - }); + + pub const Moddelay = LV2Command( + .moddelay, + "http://plugin.org.uk/swh-plugins/modDelay", + struct { + base: f32, + }, + ); pub const Multichorus = LV2Command(.multichorus, "http://calf.sourceforge.net/plugins/MultiChorus", struct { min_delay: f32, @@ -471,8 +476,20 @@ pub const Lang = struct { // arguments... if (is_lv2_command) { - cmd.split = try std.fmt.parseInt(usize, tok_it.next().?, 10); - cmd.index = try std.fmt.parseInt(usize, tok_it.next().?, 10); + const split = tok_it.next(); + if (split == null) { + self.doError("Expected split parameter, got EOL", .{}); + return; + } + + const index = tok_it.next(); + if (index == null) { + self.doError("Expected index parameter, got EOL", .{}); + return; + } + + cmd.split = try std.fmt.parseInt(usize, split.?, 10); + cmd.index = try std.fmt.parseInt(usize, index.?, 10); inline for (@typeInfo(@TypeOf(cmd.parameters)).Struct.fields) |cmd_field| { const arg = tok_it.next().?; From d9358ed79408a4b4a0a096a9922d2b01860fc92c Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:25:25 -0300 Subject: [PATCH 27/69] add lv2 parameter validation --- src/lang.zig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 89ed749..4db0cb7 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -453,7 +453,7 @@ pub const Lang = struct { self.line = 0; } fn doError(self: *Lang, comptime fmt: []const u8, args: var) void { - std.debug.warn("error at line {}: ", .{self.line}); + std.debug.warn("ERROR! at line {}: ", .{self.line}); std.debug.warn(fmt, args); std.debug.warn("\n", .{}); self.has_error = true; @@ -491,19 +491,21 @@ pub const Lang = struct { cmd.split = try std.fmt.parseInt(usize, split.?, 10); cmd.index = try std.fmt.parseInt(usize, index.?, 10); + // All parameters for LV2 plugins are f32. inline for (@typeInfo(@TypeOf(cmd.parameters)).Struct.fields) |cmd_field| { - const arg = tok_it.next().?; + const maybe_arg = tok_it.next(); + if (maybe_arg == null) { + self.doError("Expected parameter for {}, got nothing", .{cmd_field.name}); + return; + } + + const arg = maybe_arg.?; + const argument_value = switch (cmd_field.field_type) { f32 => try std.fmt.parseFloat(f32, arg), else => @compileError("LV2 parameter struct can only have f32 fields"), }; - std.debug.warn("parsing {}, arg of type {} => {}\n", .{ - @typeName(command_struct), - @typeName(@TypeOf(argument_value)), - argument_value, - }); - @field(cmd.parameters, cmd_field.name) = argument_value; } } else { From 82dc99d7d57e74e329799030bc5c95d7090ea7bc Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:26:27 -0300 Subject: [PATCH 28/69] remove unecessary switch --- src/lang.zig | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 4db0cb7..73ece6a 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -500,13 +500,10 @@ pub const Lang = struct { } const arg = maybe_arg.?; + if (cmd_field.field_type != f32) + @compileError("LV2 parameter struct can only have f32 fields"); - const argument_value = switch (cmd_field.field_type) { - f32 => try std.fmt.parseFloat(f32, arg), - else => @compileError("LV2 parameter struct can only have f32 fields"), - }; - - @field(cmd.parameters, cmd_field.name) = argument_value; + @field(cmd.parameters, cmd_field.name) = try std.fmt.parseFloat(f32, arg); } } else { inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { From ca751e58f7ea2aeb5b83be38154ca5dcb3791a86 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:33:19 -0300 Subject: [PATCH 29/69] add draft declarations for custom commands --- src/lang.zig | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index 73ece6a..824a3bb 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -113,6 +113,13 @@ pub const Command = struct { .saturator => Saturator, .vintagedelay => Vintagedelay, + .noise => Noise, + .wildnoise => Wildnoise, + .write => Write, + .embed => Embed, + + .rotate => Rotate, + else => @panic("TODO"), }; } @@ -146,8 +153,37 @@ pub const Command = struct { pub const RunQS = struct { pub const base_tag = Tag.runqs; - program: []const u8, base: Command, + program: []const u8, + }; + + pub const Noise = CustomCommand(Tag.noise, custom.RandomNoise, struct { + seed: f32, + fill_bytes: f32, + }); + + pub const Wildnoise = CustomCommand(Tag.wildnoise, custom.WildNoise, struct { + seed: f32, + fill_bytes: f32, + }); + + pub const Write = CustomCommand(Tag.write, custom.Write, struct { + data: f32, + }); + + pub const Embed = struct { + pub const base_tag = Tag.embed; + base: Command, + split: usize, + index: usize, + path: []const u8, + }; + + pub const Rotate = struct { + pub const base_tag = Tag.rotate; + base: Command, + deg: usize, + bgfill: []const u8, }; pub const Amp = LV2Command( From e669b74ffb0b5444f2b77dc157c536bb524d5c8d Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:34:49 -0300 Subject: [PATCH 30/69] add CustomCommand function --- src/lang.zig | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index 824a3bb..03a6c52 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -31,6 +31,23 @@ fn LV2Command( }; } +fn CustomCommand( + comptime tag: Command.tag, + comptime plugin: type, + comptime parameters: type, +) type { + return struct { + pub const base_tag = tag; + pub const command_type = CommandType.plugin_command; + pub const plugin_type = plugin; + + base: Command, + split: usize, + index: usize, + parameters: LV2Parameters, + }; +} + pub const Command = struct { tag: Tag, @@ -182,7 +199,7 @@ pub const Command = struct { pub const Rotate = struct { pub const base_tag = Tag.rotate; base: Command, - deg: usize, + deg: f32, bgfill: []const u8, }; From e8808c501bcf1136f98f2b777e03ffde4ef49ff8 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:38:18 -0300 Subject: [PATCH 31/69] make Embed follow existing custom plugin structure --- src/custom.zig | 4 ++-- src/lang.zig | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/custom.zig b/src/custom.zig index f346fa0..4f9bbc2 100644 --- a/src/custom.zig +++ b/src/custom.zig @@ -140,10 +140,10 @@ pub const Embed = struct { sndfile: *c.SNDFILE = undefined, buf: []f32 = undefined, - pub fn init(allocator: *std.mem.Allocator, filepath: []const u8) @This() { + pub fn init(allocator: *std.mem.Allocator, params: *plugins.ParmaMap) @This() { return Embed{ .allocator = allocator, - .filepath = filepath, + .filepath = params.get("path").?, }; } diff --git a/src/lang.zig b/src/lang.zig index 03a6c52..ef886b9 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -1,6 +1,7 @@ const std = @import("std"); const plugin = @import("plugin.zig"); +const custom = @import("custom.zig"); pub const ParseError = error{ OutOfMemory, @@ -188,13 +189,9 @@ pub const Command = struct { data: f32, }); - pub const Embed = struct { - pub const base_tag = Tag.embed; - base: Command, - split: usize, - index: usize, + pub const Embed = CustomCommand(Tag.write, custom.Embed, struct { path: []const u8, - }; + }); pub const Rotate = struct { pub const base_tag = Tag.rotate; From 1fac8c73128821630dad4c3c5e911e254a51c157 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:40:31 -0300 Subject: [PATCH 32/69] fix putting KV on a string --- src/custom.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/custom.zig b/src/custom.zig index 4f9bbc2..a91bdd2 100644 --- a/src/custom.zig +++ b/src/custom.zig @@ -120,9 +120,8 @@ pub const Write = struct { allocator: *std.mem.Allocator, params: *plugins.ParamMap, ) Write { - const data = params.get("data").?; return Write{ - .data = data.value, + .data = params.get("data").?.value, }; } @@ -143,7 +142,7 @@ pub const Embed = struct { pub fn init(allocator: *std.mem.Allocator, params: *plugins.ParmaMap) @This() { return Embed{ .allocator = allocator, - .filepath = params.get("path").?, + .filepath = params.get("path").?.value, }; } From 1c1e525b1daf6cc32d5c62901bca4eb59414908f Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:47:31 -0300 Subject: [PATCH 33/69] add support for plugin command types --- src/runner.zig | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index e65bac0..a1bed65 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -190,26 +190,6 @@ pub const Runner = struct { _ = try proc.spawnAndWait(); } - fn noiseCmd(self: *Runner, pos: Position, map: *ParamMap) !void { - var image = try self.getImage(); - try image.runCustomPlugin(custom.RandomNoise, pos, *ParamMap, map); - } - - fn wildNoiseCmd(self: *Runner, pos: Position, map: *ParamMap) !void { - var image = try self.getImage(); - try image.runCustomPlugin(custom.WildNoise, pos, *ParamMap, map); - } - - fn writeCmd(self: *Runner, pos: Position, map: *ParamMap) !void { - var image = try self.getImage(); - try image.runCustomPlugin(custom.Write, pos, *ParamMap, map); - } - - fn embedCmd(self: *Runner, pos: Position, path: []const u8) !void { - var image = try self.getImage(); - try image.runCustomPlugin(custom.Embed, pos, []const u8, path); - } - fn rotateCmd( self: *Runner, deg: f32, @@ -244,6 +224,26 @@ pub const Runner = struct { try image.runPlugin(typ.lv2_url, pos, params); } + fn executePlugin(self: *@This(), command: var) !void { + const pos = plugin.Position{ + .split = command.split, + .index = command.index, + }; + + var params = ParamMap.init(self.allocator); + defer params.deinit(); + + inline for (@typeInfo(@TypeOf(command.parameters)).Struct.fields) |cmd_field| { + try params.put( + cmd_field.name, + @field(command.parameters, cmd_field.name), + ); + } + + var image = try self.getImage(); + try image.runCustomPlugin(typ.plugin_type, pos, map); + } + fn newRunCommandSingle( self: *@This(), cmd: lang.Command, @@ -261,6 +261,7 @@ pub const Runner = struct { const ctype = typ.command_type; switch (ctype) { .lv2_command => try self.executeLV2Command(command.*), + .plugin_command => try self.executePlugin(command.*), else => @panic("TODO support command type"), } } @@ -305,6 +306,8 @@ pub const Runner = struct { .saturator => try self.newRunCommandSingle(cmd, .saturator), .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), + .noise, .wildnoise, .write, .embed => |tag| try self.newRunCommandSingle(cmd, tag), + else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); @panic("TODO support tag"); From 303a40758df71dfda00c37808ac5c4c613f60b6c Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:55:03 -0300 Subject: [PATCH 34/69] make custom plugins always receive ParamMap --- src/image.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/image.zig b/src/image.zig index 7f8deb4..d677afa 100644 --- a/src/image.zig +++ b/src/image.zig @@ -422,8 +422,7 @@ pub const Image = struct { self: *Image, comptime Plugin: type, position: plugins.Position, - comptime ExtraType: type, - extra: ExtraType, + extra: *ParamMap, ) !void { var plugin_opt: ?Plugin = Plugin.init(self.allocator, extra); if (plugin_opt == null) { From 10b2c69605bf3be961579ee5fa8cfe24ca4d80c7 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:55:22 -0300 Subject: [PATCH 35/69] fix typos --- src/lang.zig | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index ef886b9..04195f5 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -13,6 +13,8 @@ pub const CommandType = enum { /// "LV2 Commands" are commands that receive split, index, and then receive /// any f64 arguments. lv2_command, + + custom_command, }; fn LV2Command( @@ -33,19 +35,19 @@ fn LV2Command( } fn CustomCommand( - comptime tag: Command.tag, - comptime plugin: type, - comptime parameters: type, + comptime tag: Command.Tag, + comptime Plugin: type, + comptime PluginParameters: type, ) type { return struct { pub const base_tag = tag; - pub const command_type = CommandType.plugin_command; - pub const plugin_type = plugin; + pub const command_type = CommandType.custom_command; + pub const plugin_type = Plugin; base: Command, split: usize, index: usize, - parameters: LV2Parameters, + parameters: PluginParameters, }; } From 83996b889fba82dc24f716203f2450b59fa622dc Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:55:27 -0300 Subject: [PATCH 36/69] make rotate not be a typed command --- src/lang.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index 04195f5..cc8d58a 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -520,7 +520,7 @@ pub const Lang = struct { // Based on the command struct fields, we can parse the arguments. var cmd = try self.allocator.create(command_struct); const is_lv2_command = switch (command_struct.base_tag) { - .noop, .load, .quicksave, .runqs => false, + .noop, .load, .quicksave, .runqs, .rotate => false, else => command_struct.command_type == .lv2_command, }; From 2b4f4288903a0952f44bdc916b68c07a3227c92c Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:55:44 -0300 Subject: [PATCH 37/69] fix typo --- src/runner.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index a1bed65..efaf568 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -234,14 +234,14 @@ pub const Runner = struct { defer params.deinit(); inline for (@typeInfo(@TypeOf(command.parameters)).Struct.fields) |cmd_field| { - try params.put( + _ = try params.put( cmd_field.name, @field(command.parameters, cmd_field.name), ); } var image = try self.getImage(); - try image.runCustomPlugin(typ.plugin_type, pos, map); + try image.runCustomPlugin(@TypeOf(command).plugin_type, pos, ¶ms); } fn newRunCommandSingle( @@ -261,7 +261,7 @@ pub const Runner = struct { const ctype = typ.command_type; switch (ctype) { .lv2_command => try self.executeLV2Command(command.*), - .plugin_command => try self.executePlugin(command.*), + .custom_command => try self.executePlugin(command.*), else => @panic("TODO support command type"), } } From 9801e303c0fbeaf8617a1cccd8b90f934c8777cd Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 21:55:48 -0300 Subject: [PATCH 38/69] flatten switch values --- src/runner.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runner.zig b/src/runner.zig index efaf568..db40493 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -306,7 +306,10 @@ pub const Runner = struct { .saturator => try self.newRunCommandSingle(cmd, .saturator), .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), - .noise, .wildnoise, .write, .embed => |tag| try self.newRunCommandSingle(cmd, tag), + .noise => try self.newRunCommandSingle(cmd, .noise), + .wildnoise => try self.newRunCommandSingle(cmd, .wildnoise), + .write => try self.newRunCommandSingle(cmd, .write), + .embed => try self.newRunCommandSingle(cmd, .embed), else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); From 89afa8af106dfce777ce83817aecc3507a63de43 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 22:27:11 -0300 Subject: [PATCH 39/69] convert from ParamMap to ducktyped param struct --- src/custom.zig | 30 ++++++++++++------------------ src/image.zig | 2 +- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/custom.zig b/src/custom.zig index a91bdd2..0420bd3 100644 --- a/src/custom.zig +++ b/src/custom.zig @@ -16,15 +16,12 @@ pub const RandomNoise = struct { pub fn init( allocator: *std.mem.Allocator, - params: *plugins.ParamMap, + params: var, ) ?RandomNoise { - const seed = @floatToInt(u64, params.get("seed").?.value); - const fillbytes = @floatToInt(usize, params.get("fill_bytes").?.value); + var r = std.rand.DefaultPrng.init(params.seed); - var r = std.rand.DefaultPrng.init(seed); - - if (fillbytes > 0) { - var rand_buf = allocator.alloc(f32, fillbytes) catch return null; + if (params.fill_bytes > 0) { + var rand_buf = allocator.alloc(f32, params.fill_bytes) catch return null; for (rand_buf) |_, idx| { rand_buf[idx] = r.random.float(f32); @@ -67,15 +64,12 @@ pub const WildNoise = struct { pub fn init( allocator: *std.mem.Allocator, - params: *plugins.ParamMap, + params: var, ) ?WildNoise { - const seed = @floatToInt(u64, params.get("seed").?.value); - const fillbytes = @floatToInt(usize, params.get("fill_bytes").?.value); + var r = std.rand.DefaultPrng.init(params.seed); - var r = std.rand.DefaultPrng.init(seed); - - if (fillbytes > 0) { - var rand_buf = allocator.alloc(f32, fillbytes) catch return null; + if (params.fill_bytes > 0) { + var rand_buf = allocator.alloc(f32, params.fill_bytes) catch return null; for (rand_buf) |_, idx| { rand_buf[idx] = @intToFloat(f32, r.random.int(u1)); @@ -118,10 +112,10 @@ pub const Write = struct { pub fn init( allocator: *std.mem.Allocator, - params: *plugins.ParamMap, + params: var, ) Write { return Write{ - .data = params.get("data").?.value, + .data = params.data, }; } @@ -139,10 +133,10 @@ pub const Embed = struct { sndfile: *c.SNDFILE = undefined, buf: []f32 = undefined, - pub fn init(allocator: *std.mem.Allocator, params: *plugins.ParmaMap) @This() { + pub fn init(allocator: *std.mem.Allocator, params: var) @This() { return Embed{ .allocator = allocator, - .filepath = params.get("path").?.value, + .filepath = params.path, }; } diff --git a/src/image.zig b/src/image.zig index d677afa..b9202ef 100644 --- a/src/image.zig +++ b/src/image.zig @@ -422,7 +422,7 @@ pub const Image = struct { self: *Image, comptime Plugin: type, position: plugins.Position, - extra: *ParamMap, + extra: var, ) !void { var plugin_opt: ?Plugin = Plugin.init(self.allocator, extra); if (plugin_opt == null) { From 30da41293a074b990320816fbdf56a05d1d337bf Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 22:27:24 -0300 Subject: [PATCH 40/69] fix type defs for noise cmds --- src/lang.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index cc8d58a..05f631f 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -178,13 +178,13 @@ pub const Command = struct { }; pub const Noise = CustomCommand(Tag.noise, custom.RandomNoise, struct { - seed: f32, - fill_bytes: f32, + seed: u64, + fill_bytes: usize, }); pub const Wildnoise = CustomCommand(Tag.wildnoise, custom.WildNoise, struct { - seed: f32, - fill_bytes: f32, + seed: u64, + fill_bytes: usize, }); pub const Write = CustomCommand(Tag.write, custom.Write, struct { From 690ab89cfddbc1d513776eee2e388a64f5894fb1 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 22:27:38 -0300 Subject: [PATCH 41/69] allow any typed command to use lv2 param parse logic --- src/lang.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 05f631f..329aa7e 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -521,7 +521,7 @@ pub const Lang = struct { var cmd = try self.allocator.create(command_struct); const is_lv2_command = switch (command_struct.base_tag) { .noop, .load, .quicksave, .runqs, .rotate => false, - else => command_struct.command_type == .lv2_command, + else => true, }; // TODO: crash when no arguments are left but we still need @@ -543,7 +543,6 @@ pub const Lang = struct { cmd.split = try std.fmt.parseInt(usize, split.?, 10); cmd.index = try std.fmt.parseInt(usize, index.?, 10); - // All parameters for LV2 plugins are f32. inline for (@typeInfo(@TypeOf(cmd.parameters)).Struct.fields) |cmd_field| { const maybe_arg = tok_it.next(); if (maybe_arg == null) { From 72379e63ee5a6a64fcdbbba58d0d34f16d489227 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 22:27:56 -0300 Subject: [PATCH 42/69] add support for more types on lv2 parameter structs --- src/lang.zig | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 329aa7e..3b7a542 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -551,10 +551,15 @@ pub const Lang = struct { } const arg = maybe_arg.?; - if (cmd_field.field_type != f32) - @compileError("LV2 parameter struct can only have f32 fields"); + const arg_value = switch (cmd_field.field_type) { + f32 => try std.fmt.parseFloat(f32, arg), + u64 => try std.fmt.parseInt(u64, arg, 10), + usize => try std.fmt.parseInt(usize, arg, 10), + []const u8 => try self.allocator.dupe(u8, arg), + else => @compileError("parameter struct has unsupported type " ++ @typeName(cmd_field.field_type)), + }; - @field(cmd.parameters, cmd_field.name) = try std.fmt.parseFloat(f32, arg); + @field(cmd.parameters, cmd_field.name) = arg_value; } } else { inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| { @@ -569,7 +574,7 @@ pub const Lang = struct { i32 => try std.fmt.parseInt(i32, arg, 10), f32 => try std.fmt.parseFloat(f32, arg), []const u8 => try self.allocator.dupe(u8, arg), - else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), + else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), }; std.debug.warn("parsing {}, arg of type {} => {}\n", .{ From 36937a5fdeee43e0b64e35059274f0b21e68a649 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2020 22:28:10 -0300 Subject: [PATCH 43/69] remove ParamMap creation from runner --- src/runner.zig | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index db40493..dd5fcd2 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -230,18 +230,8 @@ pub const Runner = struct { .index = command.index, }; - var params = ParamMap.init(self.allocator); - defer params.deinit(); - - inline for (@typeInfo(@TypeOf(command.parameters)).Struct.fields) |cmd_field| { - _ = try params.put( - cmd_field.name, - @field(command.parameters, cmd_field.name), - ); - } - var image = try self.getImage(); - try image.runCustomPlugin(@TypeOf(command).plugin_type, pos, ¶ms); + try image.runCustomPlugin(@TypeOf(command).plugin_type, pos, command.parameters); } fn newRunCommandSingle( From b238517b3399ed634f15b9206782bb565ef0d8d5 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 21:41:10 -0300 Subject: [PATCH 44/69] update symbols for Dyncomp --- src/lang.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index 3b7a542..2a506c2 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -374,7 +374,7 @@ pub const Command = struct { hold: f32, inputgain: f32, threshold: f32, - ratio: f32, + Ratio: f32, attack: f32, release: f32, gain_min: f32, From 76b353e5934d406f634fb7bfac6811072d9a019f Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 21:51:51 -0300 Subject: [PATCH 45/69] remove code for old runner commands --- src/runner.zig | 63 -------------------------------------------------- 1 file changed, 63 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index dd5fcd2..def019d 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -307,69 +307,6 @@ pub const Runner = struct { }, } } - - fn runCommand(self: *Runner, cmd: *lang.Command) !void { - var params = ParamList.init(self.allocator); - defer params.deinit(); - - var map = ParamMap.init(self.allocator); - defer map.deinit(); - - return switch (cmd.command) { - .Noop => {}, - .Load => blk: { - var path = cmd.args.items[0]; - try self.loadCmd(path); - - // TODO is this needed? - break :blk; - }, - .Quicksave => try self.quicksaveCmd(), - .RunQS => try self.runQSCmd(cmd.args.items[0]), - - .Noise => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParamMap(&map, "seed"); - try cmd.appendParamMap(&map, "fill_bytes"); - - try self.noiseCmd(pos, &map); - }, - - .WildNoise => blk: { - const pos = try cmd.consumePosition(); - - try cmd.appendParamMap(&map, "seed"); - try cmd.appendParamMap(&map, "fill_bytes"); - - try self.wildNoiseCmd(pos, &map); - }, - - .Write => blk: { - const pos = try cmd.consumePosition(); - try cmd.appendParamMap(&map, "data"); - try self.writeCmd(pos, &map); - }, - - .Embed => blk: { - const pos = try cmd.consumePosition(); - const path = cmd.args.items[2]; - try self.embedCmd(pos, path); - }, - - .Rotate => blk: { - const deg = try cmd.floatArgAt(0); - const bgfill = try cmd.argAt(1); - try self.rotateCmd(deg, bgfill); - }, - - else => blk: { - std.debug.warn("Unsupported command: {}\n", .{cmd.command}); - break :blk RunError.UnknownCommand; - }, - }; - } - /// Run a list of commands. pub fn runCommands( self: *Runner, From 54919110a5c63b951bdf83d5b98f5dfb8593be0b Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 21:54:10 -0300 Subject: [PATCH 46/69] refactor: remove 'new' prefix from functions --- src/runner.zig | 74 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index def019d..c4b916d 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -224,7 +224,7 @@ pub const Runner = struct { try image.runPlugin(typ.lv2_url, pos, params); } - fn executePlugin(self: *@This(), command: var) !void { + fn executeCustomCommand(self: *@This(), command: var) !void { const pos = plugin.Position{ .split = command.split, .index = command.index, @@ -234,7 +234,7 @@ pub const Runner = struct { try image.runCustomPlugin(@TypeOf(command).plugin_type, pos, command.parameters); } - fn newRunCommandSingle( + fn runSingleCommand( self: *@This(), cmd: lang.Command, comptime tag: lang.Command.Tag, @@ -251,13 +251,13 @@ pub const Runner = struct { const ctype = typ.command_type; switch (ctype) { .lv2_command => try self.executeLV2Command(command.*), - .custom_command => try self.executePlugin(command.*), + .custom_command => try self.executeCustomCommand(command.*), else => @panic("TODO support command type"), } } } - fn newRunCommand(self: *@This(), cmd: lang.Command) !void { + fn runCommand(self: *@This(), cmd: lang.Command) !void { switch (cmd.tag) { .load => { const command = cmd.cast(lang.Command.Load).?; @@ -266,40 +266,40 @@ pub const Runner = struct { .quicksave => { try self.quicksaveCmd(); }, - .amp => try self.newRunCommandSingle(cmd, .amp), + .amp => try self.runSingleCommand(cmd, .amp), - .rflanger => try self.newRunCommandSingle(cmd, .rflanger), - .eq => try self.newRunCommandSingle(cmd, .eq), - .phaser => try self.newRunCommandSingle(cmd, .phaser), - .mbeq => try self.newRunCommandSingle(cmd, .mbeq), - .chorus => try self.newRunCommandSingle(cmd, .chorus), - .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), - .reverb => try self.newRunCommandSingle(cmd, .reverb), - .highpass => try self.newRunCommandSingle(cmd, .highpass), - .delay => try self.newRunCommandSingle(cmd, .delay), - .vinyl => try self.newRunCommandSingle(cmd, .vinyl), - .revdelay => try self.newRunCommandSingle(cmd, .revdelay), - .gate => try self.newRunCommandSingle(cmd, .gate), - .detune => try self.newRunCommandSingle(cmd, .detune), - .overdrive => try self.newRunCommandSingle(cmd, .overdrive), - .degrade => try self.newRunCommandSingle(cmd, .degrade), - .repsycho => try self.newRunCommandSingle(cmd, .repsycho), - .talkbox => try self.newRunCommandSingle(cmd, .talkbox), - .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), - .thruzero => try self.newRunCommandSingle(cmd, .thruzero), - .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), - .gverb => try self.newRunCommandSingle(cmd, .gverb), - .invert => try self.newRunCommandSingle(cmd, .invert), - .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), - .moddelay => try self.newRunCommandSingle(cmd, .moddelay), - .multichorus => try self.newRunCommandSingle(cmd, .multichorus), - .saturator => try self.newRunCommandSingle(cmd, .saturator), - .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), + .rflanger => try self.runSingleCommand(cmd, .rflanger), + .eq => try self.runSingleCommand(cmd, .eq), + .phaser => try self.runSingleCommand(cmd, .phaser), + .mbeq => try self.runSingleCommand(cmd, .mbeq), + .chorus => try self.runSingleCommand(cmd, .chorus), + .pitchscaler => try self.runSingleCommand(cmd, .pitchscaler), + .reverb => try self.runSingleCommand(cmd, .reverb), + .highpass => try self.runSingleCommand(cmd, .highpass), + .delay => try self.runSingleCommand(cmd, .delay), + .vinyl => try self.runSingleCommand(cmd, .vinyl), + .revdelay => try self.runSingleCommand(cmd, .revdelay), + .gate => try self.runSingleCommand(cmd, .gate), + .detune => try self.runSingleCommand(cmd, .detune), + .overdrive => try self.runSingleCommand(cmd, .overdrive), + .degrade => try self.runSingleCommand(cmd, .degrade), + .repsycho => try self.runSingleCommand(cmd, .repsycho), + .talkbox => try self.runSingleCommand(cmd, .talkbox), + .dyncomp => try self.runSingleCommand(cmd, .dyncomp), + .thruzero => try self.runSingleCommand(cmd, .thruzero), + .foverdrive => try self.runSingleCommand(cmd, .foverdrive), + .gverb => try self.runSingleCommand(cmd, .gverb), + .invert => try self.runSingleCommand(cmd, .invert), + .tapedelay => try self.runSingleCommand(cmd, .tapedelay), + .moddelay => try self.runSingleCommand(cmd, .moddelay), + .multichorus => try self.runSingleCommand(cmd, .multichorus), + .saturator => try self.runSingleCommand(cmd, .saturator), + .vintagedelay => try self.runSingleCommand(cmd, .vintagedelay), - .noise => try self.newRunCommandSingle(cmd, .noise), - .wildnoise => try self.newRunCommandSingle(cmd, .wildnoise), - .write => try self.newRunCommandSingle(cmd, .write), - .embed => try self.newRunCommandSingle(cmd, .embed), + .noise => try self.runSingleCommand(cmd, .noise), + .wildnoise => try self.runSingleCommand(cmd, .wildnoise), + .write => try self.runSingleCommand(cmd, .write), + .embed => try self.runSingleCommand(cmd, .embed), else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); @@ -315,7 +315,7 @@ pub const Runner = struct { ) !void { for (cmds.items) |cmd| { cmd.print(); - try self.newRunCommand(cmd.*); + try self.runCommand(cmd.*); } } }; From b0525f23862d98900799be4d0c1c031eb3a5ff9b Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:06:15 -0300 Subject: [PATCH 47/69] add proper support on rotateCmd for lang.Command.Rotate --- src/runner.zig | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index c4b916d..445c391 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -190,16 +190,14 @@ pub const Runner = struct { _ = try proc.spawnAndWait(); } - fn rotateCmd( - self: *Runner, - deg: f32, - bgfill: []const u8, - ) !void { + fn rotateCmd(self: *Runner, cmd: lang.Command) !void { + const rotate_cmd = cmd.cast(lang.Command.Rotate).?; + var image = try self.getImage(); - var c_bgfill = try std.cstr.addNullByte(self.allocator, bgfill); + var c_bgfill = try std.cstr.addNullByte(self.allocator, rotate_cmd.bgfill); defer self.allocator.free(c_bgfill); - try magick.runRotate(image, deg, c_bgfill); + try magick.runRotate(image, rotate_cmd.deg, c_bgfill); } fn executeLV2Command(self: *@This(), command: var) !void { @@ -263,11 +261,10 @@ pub const Runner = struct { const command = cmd.cast(lang.Command.Load).?; try self.loadCmd(command.path); }, - .quicksave => { - try self.quicksaveCmd(); - }, - .amp => try self.runSingleCommand(cmd, .amp), + .quicksave => try self.quicksaveCmd(), + .rotate => try self.rotateCmd(cmd), + .amp => try self.runSingleCommand(cmd, .amp), .rflanger => try self.runSingleCommand(cmd, .rflanger), .eq => try self.runSingleCommand(cmd, .eq), .phaser => try self.runSingleCommand(cmd, .phaser), From 0b816a512e3513d256717d030c831602fd2e452d Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:08:01 -0300 Subject: [PATCH 48/69] lang: remove unused declarations --- src/lang.zig | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 2a506c2..b8f5a85 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -3,11 +3,7 @@ const std = @import("std"); const plugin = @import("plugin.zig"); const custom = @import("custom.zig"); -pub const ParseError = error{ - OutOfMemory, - ArgRequired, - ParseFail, -}; +pub const ParseError = error{ParseFail}; pub const CommandType = enum { /// "LV2 Commands" are commands that receive split, index, and then receive @@ -481,9 +477,6 @@ pub const Command = struct { }; pub const CommandList = std.ArrayList(*Command); -pub const ArgList = std.ArrayList([]const u8); - -pub const KeywordMap = std.StringHashMap(CommandType); /// A parser. pub const Lang = struct { @@ -653,8 +646,6 @@ pub const Lang = struct { self.doError("Unknown command '{}' ({})", .{ command_string, command_string.len }); continue; } - - // try cmds.append(cmd); } if (self.has_error) return ParseError.ParseFail; From b00ab8e839967612cbc813e144398db9ae0bff94 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:14:12 -0300 Subject: [PATCH 49/69] remove the big switch when printing commands --- src/printer.zig | 44 +------------------------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/src/printer.zig b/src/printer.zig index ea91ec2..b7592db 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -2,49 +2,7 @@ const langs = @import("lang.zig"); pub fn printList(list: langs.CommandList, stream: var) !void { for (list.items) |cmd| { - var command = switch (cmd.command) { - .Noop => "noop", - .Load => "load", - .Quicksave => "quicksave", - .RunQS => "runqs", - - .Amp => "amp", - .RFlanger => "rflanger", - .Eq => "eq", - .Phaser => "phaser", - .Mbeq => "mbeq", - .Chorus => "chorus", - .PitchScaler => "pitchscaler", - .Reverb => "reverb", - .Highpass => "highpass", - .Delay => "delay", - .Vinyl => "vinyl", - .RevDelay => "revdelay", - .Gate => "gate", - .Detune => "detune", - .Overdrive => "overdrive", - .Degrade => "Degrade", - .RePsycho => "repsycho", - .TalkBox => "talkbox", - .DynComp => "dyncomp", - .ThruZero => "thruzero", - .Foverdrive => "foverdrive", - .Gverb => "gverb", - .Invert => "invert", - .TapeDelay => "tapedelay", - .ModDelay => "moddelay", - .MultiChorus => "multichorus", - .Saturator => "saturator", - .VintageDelay => "vintagedelay", - - .Noise => "noise", - .WildNoise => "wildnoise", - .Write => "write", - .Embed => "embed", - - .Rotate => "rotate", - }; - + const command = @tagName(cmd.tag); try stream.print("{}", .{command}); for (cmd.args.items) |arg| { From 9cb82e3180b2325ab95170f81e60c415f41fee36 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:34:48 -0300 Subject: [PATCH 50/69] remove unecessary code --- src/runner.zig | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 445c391..036975d 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -239,19 +239,11 @@ pub const Runner = struct { ) !void { comptime const typ = lang.Command.tagToType(tag); const command = cmd.cast(typ).?; - inline for (@typeInfo(typ).Struct.decls) |decl| { - comptime { - if (!std.mem.eql(u8, decl.name, "command_type")) { - continue; - } - } - - const ctype = typ.command_type; - switch (ctype) { - .lv2_command => try self.executeLV2Command(command.*), - .custom_command => try self.executeCustomCommand(command.*), - else => @panic("TODO support command type"), - } + const ctype = typ.command_type; + switch (ctype) { + .lv2_command => try self.executeLV2Command(command.*), + .custom_command => try self.executeCustomCommand(command.*), + else => @panic("TODO support command type"), } } @@ -297,11 +289,6 @@ pub const Runner = struct { .wildnoise => try self.runSingleCommand(cmd, .wildnoise), .write => try self.runSingleCommand(cmd, .write), .embed => try self.runSingleCommand(cmd, .embed), - - else => { - std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); - @panic("TODO support tag"); - }, } } /// Run a list of commands. From e71eba583e2a92928d72821e2444c35ced987979 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:34:56 -0300 Subject: [PATCH 51/69] make load command own its path memory --- src/lang.zig | 3 ++- src/main.zig | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index b8f5a85..305eb4a 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -159,7 +159,7 @@ pub const Command = struct { pub const Load = struct { pub const base_tag = Tag.load; base: Command, - path: []const u8, + path: []u8, }; pub const Quicksave = struct { @@ -566,6 +566,7 @@ pub const Lang = struct { usize => try std.fmt.parseInt(usize, arg, 10), i32 => try std.fmt.parseInt(i32, arg, 10), f32 => try std.fmt.parseFloat(f32, arg), + []u8 => try self.allocator.dupe(u8, arg), []const u8 => try self.allocator.dupe(u8, arg), else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."), }; diff --git a/src/main.zig b/src/main.zig index 9971f24..1553aff 100644 --- a/src/main.zig +++ b/src/main.zig @@ -57,13 +57,16 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { } else { // if there isn't any commands on the file, we load our default // 'load :0' command - var loadargs = langs.ArgList.init(allocator); - try loadargs.append(":0"); - try cmds.append(langs.Command{ - .command = .Load, - .args = loadargs, - }); + // TODO: deliberate memleak here. we only allocate this + // command once, for the start of the file, so. + var load_cmd = try allocator.create(langs.Command.Load); + std.mem.copy(u8, load_cmd.path, ":0"); + load_cmd.base.tag = langs.Command.Tag.load; + + // taking address is fine, because load_cmd lives in the lifetime + // of the allocator. + try cmds.append(&load_cmd.base); } if (file_read_opt) |file_read| { From 128f58c5022104937c7d08cbefd1ffb83acfe737 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:35:07 -0300 Subject: [PATCH 52/69] re-enable repl --- src/main.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.zig b/src/main.zig index 1553aff..541ba53 100644 --- a/src/main.zig +++ b/src/main.zig @@ -188,8 +188,7 @@ pub fn main() !void { const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path or 'repl'")); if (std.mem.eql(u8, scri_path, "repl")) { - @panic("TODO bring repl back"); - // return try doRepl(allocator, &args_it); + return try doRepl(allocator, &args_it); } var file = try std.fs.cwd().openFile(scri_path, .{}); From f973d6807daa3d34cb1d14c47b3010419962d61b Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:35:16 -0300 Subject: [PATCH 53/69] add basics of printing under new command structure --- src/printer.zig | 66 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/printer.zig b/src/printer.zig index b7592db..73a0e8a 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -1,12 +1,74 @@ const langs = @import("lang.zig"); +pub fn printCommand(cmd: langs.Command, comptime tag: langs.Command.Tag) !void { + const CommandStruct = langs.Command.tagToType(tag); + const casted = cmd.cast(CommandStruct).?; + + // TODO move this to Tag method? + const is_typed = switch (tag) { + .noop, .load, .quicksave, .runqs, .rotate => false, + else => true, + }; + + const ctype = typ.command_type; + switch (ctype) { + .lv2_command => try printLV2Command(casted), + .custom_command => try printCustomCommand(casted), + else => @panic("TODO support command type"), + } +} + pub fn printList(list: langs.CommandList, stream: var) !void { for (list.items) |cmd| { const command = @tagName(cmd.tag); try stream.print("{}", .{command}); - for (cmd.args.items) |arg| { - try stream.print(" {}", .{arg}); + switch (cmd.tag) { + .load => { + const load = command.cast(langs.Command.Load).?; + try stream.print("{}", .{load.path}); + }, + .quicksave => {}, + .rotate => { + const rotate = command.cast(langs.Command.Rotate).?; + try stream.print("{} {}", .{ rotate.deg, rotate.bgfill }); + }, + + .amp => try printCommand(cmd, .amp), + .rflanger => try printCommand(cmd, .rflanger), + .eq => try printCommand(cmd, .eq), + .phaser => try printCommand(cmd, .phaser), + .mbeq => try printCommand(cmd, .mbeq), + .chorus => try printCommand(cmd, .chorus), + .pitchscaler => try printCommand(cmd, .pitchscaler), + .reverb => try printCommand(cmd, .reverb), + .highpass => try printCommand(cmd, .highpass), + .delay => try printCommand(cmd, .delay), + .vinyl => try printCommand(cmd, .vinyl), + .revdelay => try printCommand(cmd, .revdelay), + .gate => try printCommand(cmd, .gate), + .detune => try printCommand(cmd, .detune), + .overdrive => try printCommand(cmd, .overdrive), + .degrade => try printCommand(cmd, .degrade), + .repsycho => try printCommand(cmd, .repsycho), + .talkbox => try printCommand(cmd, .talkbox), + .dyncomp => try printCommand(cmd, .dyncomp), + .thruzero => try printCommand(cmd, .thruzero), + .foverdrive => try printCommand(cmd, .foverdrive), + .gverb => try printCommand(cmd, .gverb), + .invert => try printCommand(cmd, .invert), + .tapedelay => try printCommand(cmd, .tapedelay), + .moddelay => try printCommand(cmd, .moddelay), + .multichorus => try printCommand(cmd, .multichorus), + .saturator => try printCommand(cmd, .saturator), + .vintagedelay => try printCommand(cmd, .vintagedelay), + + .noise => try printCommand(cmd, .noise), + .wildnoise => try printCommand(cmd, .wildnoise), + .write => try printCommand(cmd, .write), + .embed => try printCommand(cmd, .embed), + + else => @compileError("unhandled command"), } _ = try stream.write(";\n"); From b06bab9ec56bc10f5eddcd89398b5dbee311c944 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:35:29 -0300 Subject: [PATCH 54/69] remove unecessary compileError call --- src/printer.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/printer.zig b/src/printer.zig index 73a0e8a..3efdde7 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -67,8 +67,6 @@ pub fn printList(list: langs.CommandList, stream: var) !void { .wildnoise => try printCommand(cmd, .wildnoise), .write => try printCommand(cmd, .write), .embed => try printCommand(cmd, .embed), - - else => @compileError("unhandled command"), } _ = try stream.write(";\n"); From 7f008db540eb554e89ec8eb63429edd9184506d0 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:45:35 -0300 Subject: [PATCH 55/69] part 2 of printing commands --- src/printer.zig | 93 +++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/src/printer.zig b/src/printer.zig index 3efdde7..0cf8e85 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -1,6 +1,13 @@ const langs = @import("lang.zig"); -pub fn printCommand(cmd: langs.Command, comptime tag: langs.Command.Tag) !void { +fn printCommandWithParams(stream: var, command: var) !void { + const Parameters = @TypeOf(command.parameters); + inline for (@typeInfo(Parameters).Struct.fields) |field| { + try stream.print(" {}", .{@field(command.parameters, field.name)}); + } +} + +fn printCommand(stream: var, cmd: *langs.Command, comptime tag: langs.Command.Tag) !void { const CommandStruct = langs.Command.tagToType(tag); const casted = cmd.cast(CommandStruct).?; @@ -10,10 +17,10 @@ pub fn printCommand(cmd: langs.Command, comptime tag: langs.Command.Tag) !void { else => true, }; - const ctype = typ.command_type; + const ctype = CommandStruct.command_type; switch (ctype) { - .lv2_command => try printLV2Command(casted), - .custom_command => try printCustomCommand(casted), + .lv2_command => try printCommandWithParams(stream, casted), + .custom_command => try printCommandWithParams(stream, casted), else => @panic("TODO support command type"), } } @@ -25,48 +32,52 @@ pub fn printList(list: langs.CommandList, stream: var) !void { switch (cmd.tag) { .load => { - const load = command.cast(langs.Command.Load).?; - try stream.print("{}", .{load.path}); + const load = cmd.cast(langs.Command.Load).?; + try stream.print(" {}", .{load.path}); }, - .quicksave => {}, + .runqs => { + const runqs = cmd.cast(langs.Command.RunQS).?; + try stream.print(" {}", .{runqs.program}); + }, + .noop, .quicksave => {}, .rotate => { - const rotate = command.cast(langs.Command.Rotate).?; - try stream.print("{} {}", .{ rotate.deg, rotate.bgfill }); + const rotate = cmd.cast(langs.Command.Rotate).?; + try stream.print(" {} {}", .{ rotate.deg, rotate.bgfill }); }, - .amp => try printCommand(cmd, .amp), - .rflanger => try printCommand(cmd, .rflanger), - .eq => try printCommand(cmd, .eq), - .phaser => try printCommand(cmd, .phaser), - .mbeq => try printCommand(cmd, .mbeq), - .chorus => try printCommand(cmd, .chorus), - .pitchscaler => try printCommand(cmd, .pitchscaler), - .reverb => try printCommand(cmd, .reverb), - .highpass => try printCommand(cmd, .highpass), - .delay => try printCommand(cmd, .delay), - .vinyl => try printCommand(cmd, .vinyl), - .revdelay => try printCommand(cmd, .revdelay), - .gate => try printCommand(cmd, .gate), - .detune => try printCommand(cmd, .detune), - .overdrive => try printCommand(cmd, .overdrive), - .degrade => try printCommand(cmd, .degrade), - .repsycho => try printCommand(cmd, .repsycho), - .talkbox => try printCommand(cmd, .talkbox), - .dyncomp => try printCommand(cmd, .dyncomp), - .thruzero => try printCommand(cmd, .thruzero), - .foverdrive => try printCommand(cmd, .foverdrive), - .gverb => try printCommand(cmd, .gverb), - .invert => try printCommand(cmd, .invert), - .tapedelay => try printCommand(cmd, .tapedelay), - .moddelay => try printCommand(cmd, .moddelay), - .multichorus => try printCommand(cmd, .multichorus), - .saturator => try printCommand(cmd, .saturator), - .vintagedelay => try printCommand(cmd, .vintagedelay), + .amp => try printCommand(stream, cmd, .amp), + .rflanger => try printCommand(stream, cmd, .rflanger), + .eq => try printCommand(stream, cmd, .eq), + .phaser => try printCommand(stream, cmd, .phaser), + .mbeq => try printCommand(stream, cmd, .mbeq), + .chorus => try printCommand(stream, cmd, .chorus), + .pitchscaler => try printCommand(stream, cmd, .pitchscaler), + .reverb => try printCommand(stream, cmd, .reverb), + .highpass => try printCommand(stream, cmd, .highpass), + .delay => try printCommand(stream, cmd, .delay), + .vinyl => try printCommand(stream, cmd, .vinyl), + .revdelay => try printCommand(stream, cmd, .revdelay), + .gate => try printCommand(stream, cmd, .gate), + .detune => try printCommand(stream, cmd, .detune), + .overdrive => try printCommand(stream, cmd, .overdrive), + .degrade => try printCommand(stream, cmd, .degrade), + .repsycho => try printCommand(stream, cmd, .repsycho), + .talkbox => try printCommand(stream, cmd, .talkbox), + .dyncomp => try printCommand(stream, cmd, .dyncomp), + .thruzero => try printCommand(stream, cmd, .thruzero), + .foverdrive => try printCommand(stream, cmd, .foverdrive), + .gverb => try printCommand(stream, cmd, .gverb), + .invert => try printCommand(stream, cmd, .invert), + .tapedelay => try printCommand(stream, cmd, .tapedelay), + .moddelay => try printCommand(stream, cmd, .moddelay), + .multichorus => try printCommand(stream, cmd, .multichorus), + .saturator => try printCommand(stream, cmd, .saturator), + .vintagedelay => try printCommand(stream, cmd, .vintagedelay), - .noise => try printCommand(cmd, .noise), - .wildnoise => try printCommand(cmd, .wildnoise), - .write => try printCommand(cmd, .write), - .embed => try printCommand(cmd, .embed), + .noise => try printCommand(stream, cmd, .noise), + .wildnoise => try printCommand(stream, cmd, .wildnoise), + .write => try printCommand(stream, cmd, .write), + .embed => try printCommand(stream, cmd, .embed), } _ = try stream.write(";\n"); From 0453f3730556c178ca50a9e5ae82569e329fd736 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 22:47:21 -0300 Subject: [PATCH 56/69] add noop, runqs support to runner --- src/runner.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 036975d..6b9f478 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -175,18 +175,19 @@ pub const Runner = struct { try image.saveTo(out_path); } - fn runQSCmd(self: *Runner, program: []const u8) !void { + fn runQSCmd(self: *Runner, cmd: lang.Command) !void { + const runqs = cmd.cast(lang.Command.RunQS).?; var image = try self.getImage(); const out_path = try self.makeGlitchedPath(); try image.saveTo(out_path); var proc = try std.ChildProcess.init( - &[_][]const u8{ program, out_path }, + &[_][]const u8{ runqs.program, out_path }, self.allocator, ); defer proc.deinit(); - std.debug.warn("running '{} {}'\n", .{ program, out_path }); + std.debug.warn("running '{} {}'\n", .{ runqs.program, out_path }); _ = try proc.spawnAndWait(); } @@ -249,12 +250,14 @@ pub const Runner = struct { fn runCommand(self: *@This(), cmd: lang.Command) !void { switch (cmd.tag) { + .noop => {}, .load => { const command = cmd.cast(lang.Command.Load).?; try self.loadCmd(command.path); }, .quicksave => try self.quicksaveCmd(), .rotate => try self.rotateCmd(cmd), + .runqs => try self.runQSCmd(cmd), .amp => try self.runSingleCommand(cmd, .amp), .rflanger => try self.runSingleCommand(cmd, .rflanger), From ee7ffd1be7d8f5f5f58f193b924445a548261b28 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 23:10:30 -0300 Subject: [PATCH 57/69] move repl commands to the heap --- src/main.zig | 78 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/src/main.zig b/src/main.zig index 541ba53..a2716d7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,12 +16,26 @@ const readline = @cImport({ @cInclude("readline/history.h"); }); -fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: langs.Command) !langs.CommandList { +fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: *langs.Command) !langs.CommandList { var cmds = langs.CommandList.init(allocator); try cmds.append(cmd); return cmds; } +fn copyCommandToHeap(allocator: *std.mem.Allocator, command: langs.Command, comptime tag: langs.Command.Tag) !*langs.Command { + const CommandStruct = langs.Command.tagToType(tag); + const casted = command.cast(CommandStruct).?; + var heap_cmd = try allocator.create(CommandStruct); + + @memcpy( + @ptrCast([*]u8, &heap_cmd), + @ptrCast([*]const u8, &casted), + @sizeOf(CommandStruct), + ); + + return &heap_cmd.base; +} + pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var stdout_file = std.io.getStdOut(); const stdout = &stdout_file.outStream(); @@ -104,11 +118,12 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // run the load command try runner.runCommands(cmds, true); - var runqs_args = langs.ArgList.init(allocator); - defer runqs_args.deinit(); - const wanted_runner: []const u8 = std.os.getenv("SCRITCHER_RUNNER") orelse "ristretto"; - try runqs_args.append(wanted_runner); + + var runqs_cmd = langs.Command.RunQS{ + .base = langs.Command{ .tag = langs.Command.Tag.runqs }, + .program = wanted_runner, + }; while (true) { lang.reset(); @@ -124,11 +139,51 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var line = rd_line[0..std.mem.len(rd_line)]; if (std.mem.eql(u8, line, "push")) { - try cmds.append(current); + const heap_cmd = switch (current.tag) { + .noop => try copyCommandToHeap(allocator, current, .noop), + .load => try copyCommandToHeap(allocator, current, .load), + .quicksave => try copyCommandToHeap(allocator, current, .quicksave), + .runqs => try copyCommandToHeap(allocator, current, .runqs), + .amp => try copyCommandToHeap(allocator, current, .amp), + .rflanger => try copyCommandToHeap(allocator, current, .rflanger), + .eq => try copyCommandToHeap(allocator, current, .eq), + .phaser => try copyCommandToHeap(allocator, current, .phaser), + .mbeq => try copyCommandToHeap(allocator, current, .mbeq), + .chorus => try copyCommandToHeap(allocator, current, .chorus), + .pitchscaler => try copyCommandToHeap(allocator, current, .pitchscaler), + .reverb => try copyCommandToHeap(allocator, current, .reverb), + .highpass => try copyCommandToHeap(allocator, current, .highpass), + .delay => try copyCommandToHeap(allocator, current, .delay), + .vinyl => try copyCommandToHeap(allocator, current, .vinyl), + .revdelay => try copyCommandToHeap(allocator, current, .revdelay), + .gate => try copyCommandToHeap(allocator, current, .gate), + .detune => try copyCommandToHeap(allocator, current, .detune), + .overdrive => try copyCommandToHeap(allocator, current, .overdrive), + .degrade => try copyCommandToHeap(allocator, current, .degrade), + .repsycho => try copyCommandToHeap(allocator, current, .repsycho), + .talkbox => try copyCommandToHeap(allocator, current, .talkbox), + .dyncomp => try copyCommandToHeap(allocator, current, .dyncomp), + .thruzero => try copyCommandToHeap(allocator, current, .thruzero), + .foverdrive => try copyCommandToHeap(allocator, current, .foverdrive), + .gverb => try copyCommandToHeap(allocator, current, .gverb), + .invert => try copyCommandToHeap(allocator, current, .invert), + .tapedelay => try copyCommandToHeap(allocator, current, .tapedelay), + .moddelay => try copyCommandToHeap(allocator, current, .moddelay), + .multichorus => try copyCommandToHeap(allocator, current, .multichorus), + .saturator => try copyCommandToHeap(allocator, current, .saturator), + .vintagedelay => try copyCommandToHeap(allocator, current, .vintagedelay), + .noise => try copyCommandToHeap(allocator, current, .noise), + .wildnoise => try copyCommandToHeap(allocator, current, .wildnoise), + .write => try copyCommandToHeap(allocator, current, .write), + .embed => try copyCommandToHeap(allocator, current, .embed), + .rotate => try copyCommandToHeap(allocator, current, .rotate), + }; + + try cmds.append(heap_cmd); // run the current added command to main cmds list // with the main parent runner - var cmds_wrapped = try wrapInCmdList(allocator, current); + var cmds_wrapped = try wrapInCmdList(allocator, heap_cmd); defer cmds_wrapped.deinit(); try runner.runCommands(cmds_wrapped, true); @@ -153,7 +208,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { std.debug.warn("repl: error while parsing: {}\n", .{err}); continue; }; - current = cmds_parsed.items[0]; + current = cmds_parsed.items[0].*; // by cloning the parent runner, we can iteratively write // whatever command we want and only commit the good results @@ -161,10 +216,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var runner_clone = try runner.clone(); defer runner_clone.deinit(); - try cmds_parsed.append(langs.Command{ - .command = .RunQS, - .args = runqs_args, - }); + // taking address is fine, because runqs_cmd lives in the lifetime + // of this function. + try cmds.append(&runqs_cmd.base); try runner_clone.runCommands(cmds_parsed, true); _ = try stdout.write("\n"); From 5235482ab4631b3c112038f2d73c849772dea1ae Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 1 Jun 2020 23:58:56 -0300 Subject: [PATCH 58/69] print float parameters with decimal notation --- src/printer.zig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/printer.zig b/src/printer.zig index 0cf8e85..2302cfc 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -1,9 +1,14 @@ +const std = @import("std"); const langs = @import("lang.zig"); fn printCommandWithParams(stream: var, command: var) !void { const Parameters = @TypeOf(command.parameters); inline for (@typeInfo(Parameters).Struct.fields) |field| { - try stream.print(" {}", .{@field(command.parameters, field.name)}); + if (field.field_type == f32 or field.field_type == f64) { + try stream.print(" {d}", .{@field(command.parameters, field.name)}); + } else { + try stream.print(" {}", .{@field(command.parameters, field.name)}); + } } } @@ -42,7 +47,7 @@ pub fn printList(list: langs.CommandList, stream: var) !void { .noop, .quicksave => {}, .rotate => { const rotate = cmd.cast(langs.Command.Rotate).?; - try stream.print(" {} {}", .{ rotate.deg, rotate.bgfill }); + try stream.print(" {d} {}", .{ rotate.deg, rotate.bgfill }); }, .amp => try printCommand(stream, cmd, .amp), From d6c92c0231aeb8db3f756616180f50c8438dc002 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:00:54 -0300 Subject: [PATCH 59/69] add split and index when printing custom/lv2 cmds --- src/printer.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/printer.zig b/src/printer.zig index 2302cfc..bf32f76 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -3,6 +3,7 @@ const langs = @import("lang.zig"); fn printCommandWithParams(stream: var, command: var) !void { const Parameters = @TypeOf(command.parameters); + try stream.print(" {} {}", .{ command.split, command.index }); inline for (@typeInfo(Parameters).Struct.fields) |field| { if (field.field_type == f32 or field.field_type == f64) { try stream.print(" {d}", .{@field(command.parameters, field.name)}); From 0240b10a3c4d934644ffaf04e1ecc65d97caa4bf Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:11:30 -0300 Subject: [PATCH 60/69] close handles while making temporary paths --- src/image.zig | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/image.zig b/src/image.zig index b9202ef..ef27b7a 100644 --- a/src/image.zig +++ b/src/image.zig @@ -95,12 +95,16 @@ pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 { } // if we fail to access it, we assume it doesn't exist and return it. - - _ = std.fs.cwd().openFile(nam, .{ .read = true, .write = false }) catch |err| { - if (err == error.FileNotFound) { - return nam; - } + var tmp_file: std.fs.File = std.fs.cwd().openFile( + nam, + .{ .read = true, .write = false }, + ) catch |err| blk: { + if (err == error.FileNotFound) return nam else continue; }; + + // if we actually found someone, close the handle so that we don't + // get EMFILE later on. + tmp_file.close(); } return error.TempGenFail; From c7eb70a06f083cfafb0c23feeaf6d25992ab481e Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:16:43 -0300 Subject: [PATCH 61/69] ignore lines without commands --- src/main.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.zig b/src/main.zig index a2716d7..4a65230 100644 --- a/src/main.zig +++ b/src/main.zig @@ -208,6 +208,10 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { std.debug.warn("repl: error while parsing: {}\n", .{err}); continue; }; + + // no command? ignore! + if (cmds_parsed.items.len == 0) continue; + current = cmds_parsed.items[0].*; // by cloning the parent runner, we can iteratively write From 542ba75b01638751b9ddb2ea6fd94c287fbd3de5 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:16:49 -0300 Subject: [PATCH 62/69] make repl cloned runner run the runqs cmd --- src/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 4a65230..7d6cc00 100644 --- a/src/main.zig +++ b/src/main.zig @@ -224,7 +224,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // of this function. try cmds.append(&runqs_cmd.base); - try runner_clone.runCommands(cmds_parsed, true); + try runner_clone.runCommands(cmds, true); _ = try stdout.write("\n"); } } From aeb76fe6c0b97f342566a05a3c2e807518e298de Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:35:42 -0300 Subject: [PATCH 63/69] add more possibilities on temporary file paths --- src/image.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/image.zig b/src/image.zig index ef27b7a..c43f88e 100644 --- a/src/image.zig +++ b/src/image.zig @@ -75,7 +75,7 @@ pub fn sseek(file: *c.SNDFILE, offset: usize) void { /// Caller owns the returned memory. pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 { const template_start = "/temp/temp_"; - const template = "/tmp/temp_XXXXXXXXXXX"; + const template = "/tmp/temp_XXXXXXXXXXXXXXXXXXXXX"; var nam = try allocator.alloc(u8, template.len); std.mem.copy(u8, nam, template); @@ -86,7 +86,6 @@ pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 { var i: usize = 0; while (i < 100) : (i += 1) { - // generate a random uppercase letter, that is, 65 + random number. for (fill) |_, f_idx| { var idx = @intCast(u8, r.random.uintLessThan(u5, 24)); From dc98c7a22fd8825db25d8bf913c03a4ae08529b0 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:59:36 -0300 Subject: [PATCH 64/69] use better seed --- src/image.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/image.zig b/src/image.zig index c43f88e..e0fea67 100644 --- a/src/image.zig +++ b/src/image.zig @@ -79,7 +79,7 @@ pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 { var nam = try allocator.alloc(u8, template.len); std.mem.copy(u8, nam, template); - const seed = @bitCast(u64, std.time.timestamp()); + const seed = @truncate(u64, @bitCast(u128, std.time.nanoTimestamp())); var r = std.rand.DefaultPrng.init(seed); var fill = nam[template_start.len..nam.len]; From c78ca9dd5b81e23bfbeebd7c25e3732d16532236 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 16:59:53 -0300 Subject: [PATCH 65/69] refactor argument fetching for load cmd --- src/runner.zig | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 6b9f478..234e59e 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -49,20 +49,22 @@ pub const Runner = struct { // parse the index from 1 to end var index = try std.fmt.parseInt(usize, load_path[1..], 10); - // don't care about the 'repl' being prepended when we're in repl - if (self.repl) index += 1; + // if it isn't in the repl, args look like this: + // 'scritcher ./script ./image' + // if it is, it looks like this + // 'scritcher repl ./script ./image' - var args_it = std.process.args(); - _ = args_it.skip(); + // ':0' should ALWAYS point to the image. + if (self.repl) index += 3 else index += 2; - var i: usize = 0; - while (i <= index) : (i += 1) { - _ = args_it.skip(); + var args = try std.process.argsAlloc(self.allocator); + defer std.process.argsFree(self.allocator, args); + std.debug.warn("ARGS!! {} \n", .{args.len}); + for (args) |arg, idx| { + std.debug.warn("arg{} = {}\n", .{ idx, arg }); } - - const arg = try (args_it.next(self.allocator) orelse @panic("expected argument")); - - return arg; + std.debug.warn("fetch arg idx={}, val={}\n", .{ index, args[index] }); + return args[index]; } else { return load_path; } @@ -90,7 +92,7 @@ pub const Runner = struct { // krita/gimp and make it export a bmp and while in the program you can // apply filters, etc. if (!std.mem.endsWith(u8, load_path, ".bmp") and !std.mem.endsWith(u8, load_path, ".ppm")) { - std.debug.warn("Only BMP files are allowed to be loaded.\n", .{}); + std.debug.warn("Only BMP files are allowed to be loaded. Got path '{}'\n", .{load_path}); return RunError.NoBMP; } From a2ea8fb53ea5cce02744a7dd0a5beeea6c79cd24 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 17:12:34 -0300 Subject: [PATCH 66/69] make args live through lifetime of runner we just assign cloned runners the args of the parent runner and don't free the parent's, maintaining okay memory usage. --- src/runner.zig | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 234e59e..3ca9bc9 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -26,10 +26,13 @@ pub const Runner = struct { /// If the runner is in REPL mode repl: bool = false, + args: [][]u8, + pub fn init(allocator: *std.mem.Allocator, repl: bool) Runner { return Runner{ .allocator = allocator, .repl = repl, + .args = std.process.argsAlloc(allocator) catch unreachable, }; } @@ -41,7 +44,11 @@ pub const Runner = struct { pub fn clone(self: *Runner) !Runner { var cloned_image = if (self.image) |image| try image.clone() else null; - return Runner{ .allocator = self.allocator, .image = cloned_image }; + return Runner{ + .allocator = self.allocator, + .image = cloned_image, + .args = self.args, + }; } fn resolveArg(self: *Runner, load_path: []const u8) ![]const u8 { @@ -57,14 +64,12 @@ pub const Runner = struct { // ':0' should ALWAYS point to the image. if (self.repl) index += 3 else index += 2; - var args = try std.process.argsAlloc(self.allocator); - defer std.process.argsFree(self.allocator, args); - std.debug.warn("ARGS!! {} \n", .{args.len}); - for (args) |arg, idx| { + std.debug.warn("ARGS!! {} \n", .{self.args.len}); + for (self.args) |arg, idx| { std.debug.warn("arg{} = {}\n", .{ idx, arg }); } - std.debug.warn("fetch arg idx={}, val={}\n", .{ index, args[index] }); - return args[index]; + std.debug.warn("fetch arg idx={}, val={}\n", .{ index, self.args[index] }); + return self.args[index]; } else { return load_path; } From 1b59705eae99d84f9c189a35f87114d7c4fe7f55 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 17:15:50 -0300 Subject: [PATCH 67/69] cloned runners inherit repl flag from parent --- src/runner.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runner.zig b/src/runner.zig index 3ca9bc9..66a77c8 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -47,6 +47,7 @@ pub const Runner = struct { return Runner{ .allocator = self.allocator, .image = cloned_image, + .repl = self.repl, .args = self.args, }; } From af0ea574e1d8c08e788b72ab8a2584b85e32fc68 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 17:16:02 -0300 Subject: [PATCH 68/69] remove default value for Runner.repl field --- src/runner.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner.zig b/src/runner.zig index 66a77c8..a089a67 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -24,7 +24,7 @@ pub const Runner = struct { image: ?*Image = null, /// If the runner is in REPL mode - repl: bool = false, + repl: bool, args: [][]u8, From 6d8614e6784cc4987771323f8b520bb4922e7481 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 2 Jun 2020 17:25:03 -0300 Subject: [PATCH 69/69] revert cloned runner using parsed cmd list --- src/main.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.zig b/src/main.zig index 7d6cc00..be1b672 100644 --- a/src/main.zig +++ b/src/main.zig @@ -222,9 +222,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // taking address is fine, because runqs_cmd lives in the lifetime // of this function. - try cmds.append(&runqs_cmd.base); + try cmds_parsed.append(&runqs_cmd.base); - try runner_clone.runCommands(cmds, true); + try runner_clone.runCommands(cmds_parsed, true); _ = try stdout.write("\n"); } }