add basic lilv instantiation support

This commit is contained in:
Luna 2019-07-09 15:15:02 -03:00
parent fc69a3f62f
commit 25bef23933
3 changed files with 72 additions and 10 deletions

View file

@ -9,6 +9,7 @@ pub const ImageError = error{
InvalidPlugin, InvalidPlugin,
UnknownPlugin, UnknownPlugin,
InvalidSymbol, InvalidSymbol,
InstantiateFail,
}; };
/// Low level integration function with libsndfile. /// Low level integration function with libsndfile.
@ -68,14 +69,8 @@ fn temporaryName(allocator: *std.mem.Allocator) ![]u8 {
return error.TempGenFail; return error.TempGenFail;
} }
pub const Image = struct { fn mkSfInfo() c.SF_INFO {
allocator: *std.mem.Allocator, return c.SF_INFO{
sndfile: *c.SNDFILE,
path: []const u8,
/// Open a BMP file.
pub fn open(allocator: *std.mem.Allocator, path: []const u8) !*Image {
var in_fmt = c.SF_INFO{
.frames = c_int(0), .frames = c_int(0),
.samplerate = c_int(44100), .samplerate = c_int(44100),
.channels = c_int(1), .channels = c_int(1),
@ -83,6 +78,16 @@ pub const Image = struct {
.sections = c_int(0), .sections = c_int(0),
.seekable = c_int(0), .seekable = c_int(0),
}; };
}
pub const Image = struct {
allocator: *std.mem.Allocator,
sndfile: *c.SNDFILE,
path: []const u8,
/// Open a BMP file.
pub fn open(allocator: *std.mem.Allocator, path: []const u8) !*Image {
var in_fmt = mkSfInfo();
var sndfile = try sopen(allocator, path, c.SFM_READ, &in_fmt); var sndfile = try sopen(allocator, path, c.SFM_READ, &in_fmt);
var image = try allocator.create(Image); var image = try allocator.create(Image);
@ -174,5 +179,12 @@ pub const Image = struct {
// running the plugin on that file // running the plugin on that file
var tmpnam = try temporaryName(self.allocator); var tmpnam = try temporaryName(self.allocator);
std.debug.warn("temporary name: {}\n", tmpnam); std.debug.warn("temporary name: {}\n", tmpnam);
var out_fmt = mkSfInfo();
var out_file = try sopen(self.allocator, tmpnam, c.SFM_WRITE, &out_fmt);
var rctx = try plugins.RunContext.init(self.allocator, ctx.plugin);
rctx.connectPorts(ports);
lv2.lilv_instance_activate(rctx.instance);
} }
}; };

View file

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const c = @import("lv2_helpers.zig").c; const lv2 = @import("lv2_helpers.zig");
const c = lv2.c;
const ImageError = @import("image.zig").ImageError; const ImageError = @import("image.zig").ImageError;
@ -26,13 +27,59 @@ pub const Position = struct {
pub const Context = struct { pub const Context = struct {
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
world: *c.LilvWorld, world: *c.LilvWorld,
plugin: ?*const c.LilvPlugin, plugin: *const c.LilvPlugin,
// they should both be 1. // they should both be 1.
n_audio_in: usize = 0, n_audio_in: usize = 0,
n_audio_out: usize = 0, n_audio_out: usize = 0,
}; };
/// Represents the specific run context of plugin instantation.
pub const RunContext = struct {
in_buf: []f32,
out_buf: []f32,
instance: *c.LilvInstance,
pub fn init(
allocator: *std.mem.Allocator,
plugin: *const c.LilvPlugin,
) !RunContext {
var instance = c.lilv_plugin_instantiate(plugin, f64(44100), null);
if (instance == null) {
return ImageError.InstantiateFail;
}
return RunContext{
.in_buf = try allocator.alloc(f32, 1),
.out_buf = try allocator.alloc(f32, 1),
.instance = instance.?,
};
}
pub fn connectPorts(self: *RunContext, ports: []*lv2.Port) void {
var i: usize = 0;
var o: usize = 0;
for (ports) |port, p_idx| {
var p = @intCast(u32, p_idx);
switch (port.ptype) {
.Control => lv2.lilv_instance_connect_port(self.instance, p, &port.value),
.Audio => blk: {
if (port.is_input) {
lv2.lilv_instance_connect_port(self.instance, p, &self.in_buf[i]);
i += 1;
} else {
lv2.lilv_instance_connect_port(self.instance, p, &self.out_buf[o]);
o += 1;
}
},
else => lv2.lilv_instance_connect_port(self.instance, p, null),
}
}
}
};
pub fn makeContext(allocator: *std.mem.Allocator, plugin_uri: []const u8) !Context { pub fn makeContext(allocator: *std.mem.Allocator, plugin_uri: []const u8) !Context {
const cstr_plugin_uri = try std.cstr.addNullByte(allocator, plugin_uri); const cstr_plugin_uri = try std.cstr.addNullByte(allocator, plugin_uri);
var world = c.lilv_world_new().?; var world = c.lilv_world_new().?;

View file

@ -148,6 +148,9 @@ pub const Runner = struct {
try params.append(plugin.Param{ .sym = "gain", .value = gain }); try params.append(plugin.Param{ .sym = "gain", .value = gain });
defer params.deinit(); defer params.deinit();
// TODO if we could detect that the next command is a quicksave then
// we don't need the temporary file in runPlugin and instead we
// dump it all on the output image for it.
try image.runPlugin( try image.runPlugin(
"http://lv2plug.in/plugins/eg-amp", "http://lv2plug.in/plugins/eg-amp",
plugin.Position{ .split = split, .index = index }, plugin.Position{ .split = split, .index = index },