diff --git a/src/lang.zig b/src/lang.zig index 8b1e16e..44566e5 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -9,29 +9,72 @@ 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, }; fn LV2Command( - comptime tag: Command.Tag, + comptime tag: NewCommand.Tag, comptime plugin_url: []const u8, comptime LV2Parameters: type, ) type { return struct { pub const base_tag = tag; - pub const command_type = CommandType.lv2_command; + pub const command_type = NewCommandType.lv2_command; pub const lv2_url = plugin_url; - base: Command, + base: NewCommand, split: usize, index: usize, parameters: LV2Parameters, }; } -pub const Command = struct { +pub const NewCommand = struct { tag: Tag, pub const Tag = enum { @@ -130,24 +173,24 @@ pub const Command = struct { pub const Noop = struct { pub const base_tag = Tag.noop; - base: Command, + base: NewCommand, }; pub const Load = struct { pub const base_tag = Tag.load; - base: Command, + base: NewCommand, path: []const u8, }; pub const Quicksave = struct { pub const base_tag = Tag.quicksave; - base: Command, + base: NewCommand, }; pub const RunQS = struct { pub const base_tag = Tag.runqs; program: []const u8, - base: Command, + base: NewCommand, }; pub const Amp = LV2Command( @@ -183,7 +226,108 @@ pub const Command = struct { ); }; -pub const CommandList = std.ArrayList(*Command); +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); pub const KeywordMap = std.StringHashMap(CommandType); @@ -306,7 +450,7 @@ pub const Lang = struct { var found: bool = false; - inline for (@typeInfo(Command).Struct.decls) |cmd_struct_decl| { + inline for (@typeInfo(NewCommand).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 962cfcc..438ce0b 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -398,10 +398,10 @@ pub const Runner = struct { fn newRunCommandSingle( self: *@This(), - cmd: lang.Command, - comptime tag: lang.Command.Tag, + cmd: lang.NewCommand, + comptime tag: lang.NewCommand.Tag, ) !void { - comptime const typ = lang.Command.tagToType(tag); + comptime const typ = lang.NewCommand.tagToType(tag); const command = cmd.cast(typ).?; inline for (@typeInfo(typ).Struct.decls) |decl| { comptime { @@ -418,10 +418,11 @@ pub const Runner = struct { } } - fn newRunCommand(self: *@This(), cmd: lang.Command) !void { + fn newRunCommand(self: *@This(), cmd: lang.NewCommand) !void { + // .load => try self.newRunCommandSingle(cmd, .load), switch (cmd.tag) { .load => { - const command = cmd.cast(lang.Command.Load).?; + const command = cmd.cast(lang.NewCommand.Load).?; try self.loadCmd(command.path); }, .quicksave => {