diff --git a/src/custom.zig b/src/custom.zig index 3f57a4b..7d3eb23 100644 --- a/src/custom.zig +++ b/src/custom.zig @@ -2,6 +2,7 @@ const std = @import("std"); const lv2 = @import("lv2_helpers.zig"); const plugins = @import("plugin.zig"); +const image = @import("image.zig"); const c = lv2.c; @@ -131,3 +132,44 @@ pub const Write = struct { bufs.out[0] = self.data; } }; + +pub const Embed = struct { + allocator: *std.mem.Allocator, + filepath: []const u8, + + sndfile: *c.SNDFILE = undefined, + + // TODO add its own read buffers from snd file + + pub fn init(allocator: *std.mem.Allocator, filepath: []const u8) @This() { + return Embed{ + .allocator = allocator, + .filepath = filepath, + }; + } + + pub fn setup(self: *@This()) !void { + var in_fmt = c.SF_INFO{ + .frames = c_int(0), + .samplerate = c_int(0), + .channels = c_int(0), + .format = c_int(0), + .sections = c_int(0), + .seekable = c_int(0), + }; + self.sndfile = try image.sopen( + self.allocator, + self.filepath, + c.SFM_READ, + &in_fmt, + ); + + // TODO allocate 1 or 2 in read buffer, but only use 1 + } + + pub fn deinit(self: *@This()) void {} + + pub fn run(self: *@This(), bufs: *RunBuffers) void { + bufs.out[0] = 0; + } +}; diff --git a/src/image.zig b/src/image.zig index 2b2a38a..3badd58 100644 --- a/src/image.zig +++ b/src/image.zig @@ -1,7 +1,6 @@ const std = @import("std"); const lv2 = @import("lv2_helpers.zig"); const c = lv2.c; -const custom = @import("custom.zig"); const bmp = @import("bmp_valid.zig"); const plugins = @import("plugin.zig"); @@ -23,7 +22,7 @@ pub const ImageError = error{ }; /// Low level integration function with libsndfile. -fn sopen( +pub fn sopen( allocator: *std.mem.Allocator, path: []const u8, mode: i32, @@ -57,7 +56,7 @@ fn sopen( return file.?; } -fn swrite(file: *c.SNDFILE, buf: [*]f32, frames: i64) !void { +pub fn swrite(file: *c.SNDFILE, buf: [*]f32, frames: i64) !void { const count = c.sf_writef_float(file, buf, frames); if (count != frames) { @@ -109,7 +108,7 @@ pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 { return error.TempGenFail; } -fn mkSfInfo() c.SF_INFO { +pub fn mkSfInfo() c.SF_INFO { return c.SF_INFO{ .frames = c_int(0), .samplerate = c_int(44100), @@ -422,9 +421,10 @@ pub const Image = struct { self: *Image, comptime Plugin: type, position: plugins.Position, - params: *plugins.ParamMap, + comptime ExtraType: type, + extra: ExtraType, ) !void { - var plugin_opt: ?Plugin = Plugin.init(self.allocator, params); + var plugin_opt: ?Plugin = Plugin.init(self.allocator, extra); if (plugin_opt == null) { return ImageError.PluginLoadFail; } @@ -432,6 +432,13 @@ pub const Image = struct { var plugin = plugin_opt.?; defer plugin.deinit(); + const decls = comptime std.meta.declarations(Plugin); + inline for (decls) |decl| { + if (comptime std.mem.eql(u8, decl.name, "setup")) { + try plugin.setup(); + } + } + // the code here is a copypaste of runPlugin() without the specific // lilv things. var tmpnam = try temporaryName(self.allocator); diff --git a/src/lang.zig b/src/lang.zig index d926d77..02dbf3b 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -227,6 +227,7 @@ pub const Lang = struct { "noise", "wildnoise", "write", + "embed", "rotate", }; @@ -252,6 +253,7 @@ pub const Lang = struct { .Noise, .WildNoise, .Write, + .Embed, .Rotate, }; @@ -314,6 +316,7 @@ pub const Lang = struct { .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), } } diff --git a/src/printer.zig b/src/printer.zig index 2a30f8e..f198579 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -24,6 +24,7 @@ pub fn printList(list: langs.CommandList, stream: var) !void { .Noise => "noise", .WildNoise => "wildnoise", .Write => "write", + .Embed => "embed", .Rotate => "rotate", }; diff --git a/src/runner.zig b/src/runner.zig index ede7b3b..5ae666c 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -266,17 +266,22 @@ pub const Runner = struct { fn noiseCmd(self: *Runner, pos: Position, map: *ParamMap) !void { var image = try self.getImage(); - try image.runCustomPlugin(custom.RandomNoise, pos, map); + 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, map); + 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, map); + 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( @@ -303,6 +308,8 @@ pub const Runner = struct { .Load => blk: { var path = cmd.args.at(0); try self.loadCmd(path); + + // TODO is this needed? break :blk; }, .Quicksave => try self.quicksaveCmd(), @@ -460,6 +467,12 @@ pub const Runner = struct { try self.writeCmd(pos, &map); }, + .Embed => blk: { + const pos = try cmd.consumePosition(); + const path = cmd.args.at(2); + try self.embedCmd(pos, path); + }, + .Rotate => blk: { const deg = try cmd.floatArgAt(0); const bgfill = try cmd.argAt(1);