2019-07-09 01:40:52 +00:00
|
|
|
const std = @import("std");
|
|
|
|
|
2019-07-09 18:15:02 +00:00
|
|
|
const lv2 = @import("lv2_helpers.zig");
|
|
|
|
const c = lv2.c;
|
2019-07-09 03:04:01 +00:00
|
|
|
|
|
|
|
const ImageError = @import("image.zig").ImageError;
|
|
|
|
|
2019-07-09 01:40:52 +00:00
|
|
|
/// Control port
|
|
|
|
pub const Param = struct {
|
|
|
|
/// Port symbol
|
|
|
|
sym: []const u8,
|
|
|
|
|
|
|
|
/// Control value
|
|
|
|
value: f32,
|
|
|
|
};
|
|
|
|
|
2019-07-09 03:04:01 +00:00
|
|
|
/// List of parameters to be set to control ports.
|
2019-07-09 01:40:52 +00:00
|
|
|
pub const ParamList = std.ArrayList(Param);
|
2019-09-03 15:45:17 +00:00
|
|
|
pub const ParamMap = std.StringHashMap(f32);
|
2019-07-09 01:40:52 +00:00
|
|
|
|
2019-07-09 19:52:46 +00:00
|
|
|
/// Represents an absolute position in the image.
|
|
|
|
pub const SeekPos = struct {
|
|
|
|
start: usize,
|
|
|
|
end: usize,
|
2019-07-09 21:34:05 +00:00
|
|
|
|
|
|
|
pub fn contains(self: SeekPos, idx: usize) bool {
|
|
|
|
return (self.start <= idx) and (idx <= self.end);
|
|
|
|
}
|
2019-07-09 19:52:46 +00:00
|
|
|
};
|
|
|
|
|
2019-07-09 03:04:01 +00:00
|
|
|
/// Represents a relative position in the image
|
2019-07-09 01:40:52 +00:00
|
|
|
pub const Position = struct {
|
|
|
|
split: usize,
|
|
|
|
index: usize,
|
2019-07-09 19:52:46 +00:00
|
|
|
|
|
|
|
pub fn seekPos(self: Position, total_size: usize) SeekPos {
|
2019-10-06 00:42:16 +00:00
|
|
|
std.debug.assert(self.index <= self.split);
|
2019-07-09 19:52:46 +00:00
|
|
|
var tot = total_size / self.split;
|
|
|
|
|
|
|
|
return SeekPos{
|
|
|
|
.start = self.index * tot,
|
|
|
|
.end = (self.index + 1) * tot,
|
|
|
|
};
|
|
|
|
}
|
2019-07-09 01:40:52 +00:00
|
|
|
};
|
2019-07-09 03:04:01 +00:00
|
|
|
|
|
|
|
/// Represents the starting context for a single plugin run.
|
|
|
|
pub const Context = struct {
|
2019-07-09 16:21:07 +00:00
|
|
|
allocator: *std.mem.Allocator,
|
2019-07-09 03:04:01 +00:00
|
|
|
world: *c.LilvWorld,
|
2019-07-09 18:15:02 +00:00
|
|
|
plugin: *const c.LilvPlugin,
|
2019-07-09 16:21:07 +00:00
|
|
|
|
|
|
|
// they should both be 1.
|
|
|
|
n_audio_in: usize = 0,
|
|
|
|
n_audio_out: usize = 0,
|
2019-07-10 14:47:35 +00:00
|
|
|
|
|
|
|
pub fn deinit(self: *Context) void {
|
|
|
|
c.lilv_world_free(self.world);
|
|
|
|
}
|
2019-07-09 03:04:01 +00:00
|
|
|
};
|
|
|
|
|
2019-07-13 20:42:46 +00:00
|
|
|
/// Specific run context for non-plugins.
|
|
|
|
pub const RunBuffers = struct {
|
|
|
|
allocator: *std.mem.Allocator,
|
|
|
|
|
|
|
|
in: []f32,
|
|
|
|
out: []f32,
|
|
|
|
|
|
|
|
pub fn init(allocator: *std.mem.Allocator) !RunBuffers {
|
|
|
|
// we allocate []f32 with size 2 to account for stereo plugins, however
|
|
|
|
// we only use &in_buf[0] and &out_buf[0], and don't use the
|
|
|
|
// (supposedly) right side of neither input or output.
|
|
|
|
var in_buf = try allocator.alloc(f32, 2);
|
|
|
|
std.mem.secureZero(f32, in_buf);
|
|
|
|
|
|
|
|
return RunBuffers{
|
|
|
|
.allocator = allocator,
|
|
|
|
.in = in_buf,
|
|
|
|
.out = try allocator.alloc(f32, 2),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn deinit(self: *RunBuffers) void {
|
|
|
|
self.allocator.free(self.in);
|
|
|
|
self.allocator.free(self.out);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-09 18:15:02 +00:00
|
|
|
/// Represents the specific run context of plugin instantation.
|
|
|
|
pub const RunContext = struct {
|
2019-07-13 20:42:46 +00:00
|
|
|
buffers: RunBuffers,
|
2019-07-09 18:15:02 +00:00
|
|
|
instance: *c.LilvInstance,
|
|
|
|
|
|
|
|
pub fn init(
|
|
|
|
allocator: *std.mem.Allocator,
|
|
|
|
plugin: *const c.LilvPlugin,
|
|
|
|
) !RunContext {
|
2019-11-10 16:37:59 +00:00
|
|
|
var instance = c.lilv_plugin_instantiate(plugin, @as(f64, 44100), null);
|
2019-08-09 16:55:40 +00:00
|
|
|
errdefer c.lilv_instance_free(instance);
|
|
|
|
|
2019-07-09 18:15:02 +00:00
|
|
|
if (instance == null) {
|
|
|
|
return ImageError.InstantiateFail;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RunContext{
|
2019-07-13 20:42:46 +00:00
|
|
|
.buffers = try RunBuffers.init(allocator),
|
2019-07-09 18:15:02 +00:00
|
|
|
.instance = instance.?,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-07-10 14:47:35 +00:00
|
|
|
pub fn deinit(self: *RunContext) void {
|
|
|
|
c.lilv_instance_free(self.instance);
|
2019-07-13 20:42:46 +00:00
|
|
|
self.buffers.deinit();
|
2019-07-10 14:47:35 +00:00
|
|
|
}
|
|
|
|
|
2019-08-15 01:35:22 +00:00
|
|
|
pub fn connectPorts(self: *RunContext, ports: []lv2.Port) void {
|
2019-07-09 18:15:02 +00:00
|
|
|
var i: usize = 0;
|
|
|
|
var o: usize = 0;
|
|
|
|
|
2019-07-13 20:42:46 +00:00
|
|
|
var in_buf = self.buffers.in;
|
|
|
|
var out_buf = self.buffers.out;
|
|
|
|
|
2019-08-15 01:35:22 +00:00
|
|
|
for (ports) |_, p_idx| {
|
2019-07-09 18:15:02 +00:00
|
|
|
var p = @intCast(u32, p_idx);
|
2019-08-15 01:35:22 +00:00
|
|
|
var port: *lv2.Port = &ports[p_idx];
|
2019-07-09 18:15:02 +00:00
|
|
|
|
|
|
|
switch (port.ptype) {
|
|
|
|
.Control => lv2.lilv_instance_connect_port(self.instance, p, &port.value),
|
|
|
|
.Audio => blk: {
|
|
|
|
if (port.is_input) {
|
2019-07-13 20:42:46 +00:00
|
|
|
lv2.lilv_instance_connect_port(self.instance, p, &in_buf[i]);
|
2019-07-09 18:15:02 +00:00
|
|
|
i += 1;
|
|
|
|
} else {
|
2019-07-13 20:42:46 +00:00
|
|
|
lv2.lilv_instance_connect_port(self.instance, p, &out_buf[o]);
|
2019-07-09 18:15:02 +00:00
|
|
|
o += 1;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
else => lv2.lilv_instance_connect_port(self.instance, p, null),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-09 03:04:01 +00:00
|
|
|
pub fn makeContext(allocator: *std.mem.Allocator, plugin_uri: []const u8) !Context {
|
|
|
|
const cstr_plugin_uri = try std.cstr.addNullByte(allocator, plugin_uri);
|
2019-08-14 12:10:09 +00:00
|
|
|
defer allocator.free(cstr_plugin_uri);
|
2019-08-09 16:55:40 +00:00
|
|
|
|
|
|
|
var world: *c.LilvWorld = c.lilv_world_new().?;
|
|
|
|
errdefer c.lilv_world_free(world);
|
2019-07-09 03:04:01 +00:00
|
|
|
|
|
|
|
c.lilv_world_load_all(world);
|
2019-08-09 16:55:40 +00:00
|
|
|
|
2019-07-09 03:04:01 +00:00
|
|
|
var uri: *c.LilvNode = c.lilv_new_uri(world, cstr_plugin_uri.ptr) orelse blk: {
|
|
|
|
std.debug.warn("Invalid plugin URI <{}>\n", plugin_uri);
|
|
|
|
return ImageError.InvalidPlugin;
|
|
|
|
};
|
2019-08-09 16:55:40 +00:00
|
|
|
defer c.lilv_node_free(uri);
|
2019-07-09 03:04:01 +00:00
|
|
|
|
|
|
|
const plugins: *const c.LilvPlugins = c.lilv_world_get_all_plugins(world);
|
|
|
|
|
|
|
|
var plugin: *const c.LilvPlugin = c.lilv_plugins_get_by_uri(plugins, uri) orelse blk: {
|
|
|
|
std.debug.warn("Plugin <{}> not found\n", plugin_uri);
|
|
|
|
return ImageError.UnknownPlugin;
|
|
|
|
};
|
|
|
|
|
2019-08-09 16:55:40 +00:00
|
|
|
return Context{
|
|
|
|
.allocator = allocator,
|
|
|
|
.world = world,
|
|
|
|
.plugin = plugin,
|
|
|
|
};
|
2019-07-09 03:04:01 +00:00
|
|
|
}
|