srctree

Gregory Mullen parent cfe516cd 5570595e
refactor obs parts into their own lib like tree

ev/null added: 228, removed: 208, total 20
@@ -1,145 +0,0 @@
const std = @import("std");
 
pub const obs = @cImport({
@cInclude("obs/util/darray.h");
 
@cInclude("obs/util/base.h");
@cInclude("obs/obs-module.h");
@cInclude("obs/obs-config.h");
@cInclude("obs/obs-data.h");
@cInclude("obs/obs-properties.h");
@cInclude("obs/obs-service.h");
});
 
const obs_src_array = extern struct {
array: [*]?*obs.obs_source_t,
num: usize = 0,
capacity: usize = 0,
};
 
const obs_frontend_source_list = extern struct {
sources: extern union {
da: obs.darray,
src: obs_src_array,
},
};
 
const obs_frontend_cb = *const fn (?*anyopaque) callconv(.C) void;
extern "obs-frontend-api" fn obs_frontend_add_tools_menu_item(name: [*:0]const u8, cb: obs_frontend_cb, ?*anyopaque) void;
 
extern "obs-frontend-api" fn obs_frontend_get_current_scene() ?*obs.obs_source_t;
extern "obs-frontend-api" fn obs_frontend_set_current_scene(*obs.obs_source_t) callconv(.C) void;
extern "obs-frontend-api" fn obs_frontend_get_scene_names() callconv(.C) [*:null]?[*c]u8;
extern "obs-frontend-api" fn obs_frontend_get_scenes(?*obs_frontend_source_list) callconv(.C) void;
 
extern "obs-frontend-api" fn obs_frontend_preview_program_trigger_transition() callconv(.C) void;
//extern "obs-frontend-api" fn obs_frontend_source_list_free(?*obs_frontend_source_list) callconv(.C) void;
 
pub const OBSScene = struct {
var last: i64 = 0;
var on_build = false;
 
pub fn findScenes() void {
var scenes: obs_frontend_source_list = std.mem.zeroes(obs_frontend_source_list);
 
obs_frontend_get_scenes(&scenes);
// TODO write a c compat header for this
//defer obs_frontend_source_list_free(&scenes);
std.debug.print("source data {any}\n", .{scenes.sources.src});
 
const array: [*]?*obs.obs_source_t = @ptrCast(scenes.sources.src.array);
for (array[0..scenes.sources.src.num]) |src| {
//const scene: ?*obs.obs_scene_t = obs.obs_scene_from_source(src);
const name: [*c]const u8 = obs.obs_source_get_name(src);
//const uuid: [*c]const u8 = obs.obs_source_get_uuid(@ptrCast(scene));
std.debug.print("scene {s} \n", .{name});
}
}
 
pub fn requestBuild() void {
//std.debug.print("request build\n", .{});
if (!on_build) swapPreview();
on_build = true;
last = std.time.milliTimestamp();
}
 
pub fn requestCode() void {
//std.debug.print("request code\n", .{});
if (last < std.time.milliTimestamp() - 1500 and on_build) {
swapPreview();
}
on_build = false;
last = std.time.milliTimestamp();
}
 
pub fn swapPreview() void {
//std.debug.print("swaping\n", .{});
obs_frontend_preview_program_trigger_transition();
}
 
pub fn currentScene() ?[:0]const u8 {
_ = obs_frontend_get_current_scene() orelse return null;
 
//const t = @as(?*obs.obs_source_info, @ptrCast(scene));
 
//if (t.?.get_name) |_gn| {
// const name: ?[*c]const u8 = _gn(scene);
// if (name) |n| return std.mem.span(n);
//}
return null;
}
 
pub fn setCurrentScene(scene: ?*obs.obs_source_t) void {
obs_frontend_set_current_scene(scene);
}
 
pub fn getSceneNames() [:null]?[*c]const u8 {
return std.mem.span(obs_frontend_get_scene_names());
}
};
 
pub fn init() void {
propertiesInit();
//obs.obs_register_service(&focus_service);
}
 
fn propertiesInit() void {
obs_frontend_add_tools_menu_item("click".ptr, clicked, null);
 
const props: ?*obs.obs_properties_t = obs.obs_properties_create();
_ = obs.obs_properties_add_bool(props, "blerg", "description");
 
//
//
const data: ?*obs.obs_data_t = obs.obs_data_create();
obs.obs_data_set_string(data, "set string", "this");
}
 
fn clicked(_: ?*anyopaque) callconv(.C) void {
obs.blog(obs.LOG_INFO, "clicked");
}
 
//fn createService(_: ?*obs.struct_obs_data, _: ?*obs.struct_obs_service) callconv(.C) ?*anyopaque {
// return null;
//}
//
//fn destroyService(_: ?*anyopaque) callconv(.C) void {}
//
//fn getName(_: ?*anyopaque) callconv(.C) [*:0]const u8 {
// return "Service Name";
//}
//
//fn getProperties(_: ?*anyopaque) callconv(.C) ?*obs.obs_properties_t {
// const ppts: ?*obs.obs_properties_t = obs.obs_properties_create();
//
// _ = obs.obs_properties_add_bool(ppts, "my_bool", obs.obs_module_text("MyBool"));
// return ppts;
//}
 
//const focus_service: obs.obs_service_info = obs.obs_service_info{
// .id = "focus_service",
// .create = createService,
// .destroy = destroyService,
// .get_name = getName,
// .get_properties = getProperties,
//};
 
filename was Deleted added: 228, removed: 208, total 20
@@ -0,0 +1,108 @@
const std = @import("std");
const root = @import("root");
const bufPrintZ = std.fmt.bufPrintZ;
 
pub const OBS = @cImport({
@cInclude("obs/util/base.h");
@cInclude("obs/obs-module.h");
@cInclude("obs/obs-config.h");
@cInclude("obs/obs-data.h");
@cInclude("obs/obs-properties.h");
@cInclude("obs/obs-service.h");
});
 
pub const Scene = @import("obs/frontend.zig").OBSScene;
 
/// Define a module_defaults in you root project file
const module_defaults: ModuleDefaults = if (@hasDecl(root, "module_defaults")) root.module_defaults else .{};
 
pub const ModuleDefaults = struct {
/// Name of the OBS plugin
name: [:0]const u8 = "Unnamed Module",
/// Current version of this plugin
version: [:0]const u8 = "0.0.0",
/// Author of the this plugin
author: [:0]const u8 = "Anonymous Authors",
/// Description for this plugin
description: [:0]const u8 = "Default Description for an unnamed module.",
 
/// Optional function that will be called when the plugin is loaded by OBS
/// this function does not require callconv(.C) but other call backs
/// provided may require it.
on_load_fn: *const fn () bool = empty_on_load,
/// Optional function that will be called when the plugin is unloaded by OBS
/// usually at program exit, but there are other events that could unload a
/// plugin.
on_unload_fn: *const fn () void = empty_on_unload,
};
 
/// call exportOBS in comptime to ensure Zig is able to see the required
/// funtions obs needs to export.
pub inline fn exportOBS() void {
inline for (comptime std.meta.declarations(@This())) |decl| {
_ = &@field(@This(), decl.name);
}
}
 
var obs_module_pointer: ?*OBS.obs_module_t = null;
 
export fn obs_module_set_pointer(module: ?*OBS.obs_module_t) void {
obs_module_pointer = module;
}
 
export fn obs_current_module() ?*OBS.obs_module_t {
return obs_module_pointer;
}
 
export fn obs_module_name() [*:0]const u8 {
return module_defaults.name;
}
 
export fn obs_module_ver() u32 {
return OBS.LIBOBS_API_VER;
}
 
export fn obs_module_author() [*:0]const u8 {
return module_defaults.author;
}
 
export fn obs_module_description() [*:0]const u8 {
return module_defaults.description;
}
 
export fn obs_module_load() bool {
if (module_defaults.on_load_fn()) {
logFmt(
"{s} plugin loaded successfully (version: {s})",
.{ module_defaults.name, module_defaults.version },
);
return true;
}
 
logFmt(
"{s} plugin failed to load (version: {s})",
.{ module_defaults.name, module_defaults.version },
);
return false;
}
 
export fn obs_module_unload() void {
logFmt("{s} plugin shutdown", .{module_defaults.name});
return module_defaults.on_unload_fn();
}
 
fn empty_on_load() bool {
return true;
}
 
fn empty_on_unload() void {}
 
pub fn logFmt(comptime text: []const u8, vars: anytype) void {
var buf: [0xffff:0]u8 = undefined;
const txt = bufPrintZ(&buf, text, vars) catch unreachable;
log(txt);
}
 
pub fn log(text: [*:0]const u8) void {
OBS.blog(OBS.LOG_INFO, text);
}
 
filename was Deleted added: 228, removed: 208, total 20
@@ -0,0 +1,74 @@
const std = @import("std");
const OBS = @import("../obs.zig").OBS;
 
extern "obs-frontend-api" fn obs_frontend_add_tools_menu_item(
name: [*:0]const u8,
cb: obs_frontend_cb,
?*anyopaque,
) void;
extern "obs-frontend-api" fn obs_frontend_get_current_scene() ?*OBS.obs_source_t;
extern "obs-frontend-api" fn obs_frontend_set_current_scene(*OBS.obs_source_t) callconv(.C) void;
extern "obs-frontend-api" fn obs_frontend_get_scene_names() callconv(.C) [*:null]?[*c]u8;
extern "obs-frontend-api" fn obs_frontend_get_scenes(?*obs_frontend_source_list) callconv(.C) void;
extern "obs-frontend-api" fn obs_frontend_preview_program_trigger_transition() callconv(.C) void;
//extern "obs-frontend-api" fn obs_frontend_source_list_free(?*obs_frontend_source_list) callconv(.C) void;
 
const obs_frontend_cb = *const fn (?*anyopaque) callconv(.C) void;
 
const obs_src_array = extern struct {
array: [*]?*OBS.obs_source_t,
num: usize = 0,
capacity: usize = 0,
};
 
const obs_frontend_source_list = extern struct {
sources: extern union {
da: OBS.darray,
src: obs_src_array,
},
};
 
pub const OBSScene = struct {
pub fn findScenes() void {
var scenes: obs_frontend_source_list = std.mem.zeroes(obs_frontend_source_list);
 
obs_frontend_get_scenes(&scenes);
// TODO write a c compat header for this
// it's an inline and zig doesn't like C++
// defer obs_frontend_source_list_free(&scenes);
std.debug.print("source data {any}\n", .{scenes.sources.src});
 
const array: [*]?*OBS.obs_source_t = @ptrCast(scenes.sources.src.array);
for (array[0..scenes.sources.src.num]) |src| {
//const scene: ?*OBS.obs_scene_t = OBS.obs_scene_from_source(src);
const name: [*c]const u8 = OBS.obs_source_get_name(src);
//const uuid: [*c]const u8 = OBS.obs_source_get_uuid(@ptrCast(scene));
std.debug.print("scene {s} \n", .{name});
}
}
 
pub fn swapPreview() void {
//std.debug.print("swaping\n", .{});
obs_frontend_preview_program_trigger_transition();
}
 
pub fn currentScene() ?[:0]const u8 {
_ = obs_frontend_get_current_scene() orelse return null;
 
//const t = @as(?*OBS.obs_source_info, @ptrCast(scene));
 
//if (t.?.get_name) |_gn| {
// const name: ?[*c]const u8 = _gn(scene);
// if (name) |n| return std.mem.span(n);
//}
return null;
}
 
pub fn setCurrentScene(scene: ?*OBS.obs_source_t) void {
obs_frontend_set_current_scene(scene);
}
 
pub fn getSceneNames() [:null]?[*c]const u8 {
return std.mem.span(obs_frontend_get_scene_names());
}
};
 
src/root.zig added: 228, removed: 208, total 20
@@ -2,111 +2,94 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
 
const sway_ipc = @import("sway-ipc.zig");
const gui = @import("gui.zig");
const obs = @import("obs.zig");
 
pub const obs = @cImport({
@cInclude("obs/util/base.h");
@cInclude("obs/obs-module.h");
@cInclude("obs/obs-config.h");
@cInclude("obs/obs-data.h");
@cInclude("obs/obs-properties.h");
@cInclude("obs/obs-service.h");
});
pub const module_defaults: obs.ModuleDefaults = .{
.name = "obs-sway-focus",
.version = "0.0.1",
.author = "grayhatter",
.description = "tracks focus of sway windows",
 
const PLUGIN_VERSION = "0.0.0";
var obs_module_pointer: ?*obs.obs_module_t = null;
export fn obs_module_set_pointer(module: ?*obs.obs_module_t) void {
obs_module_pointer = module;
}
.on_load_fn = on_load,
.on_unload_fn = on_unload,
};
 
export fn obs_current_module() ?*obs.obs_module_t {
return obs_module_pointer;
}
 
export fn obs_module_ver() u32 {
return obs.LIBOBS_API_VER;
}
 
export fn obs_module_author() [*:0]const u8 {
return "grayhatter";
}
 
export fn obs_module_name() [*:0]const u8 {
return "obs-sway-focus";
}
 
export fn obs_module_description() [*:0]const u8 {
return "it does stuff";
}
 
fn logFmt(comptime text: []const u8, vars: anytype) void {
var buf: [0xffff:0]u8 = undefined;
 
const txt = std.fmt.bufPrintZ(&buf, text, vars) catch unreachable;
log(txt);
}
 
fn log(text: [*:0]const u8) void {
obs.blog(obs.LOG_INFO, text);
comptime {
obs.exportOBS();
}
 
var arena: std.heap.ArenaAllocator = undefined;
var alloc: Allocator = undefined;
var running = true;
var threads: [1]std.Thread = undefined;
 
var last: i64 = 0;
var on_build = false;
 
fn requestBuild() void {
//std.debug.print("request build\n", .{});
if (!on_build) obs.Scene.swapPreview();
on_build = true;
last = std.time.milliTimestamp();
}
 
fn requestCode() void {
//std.debug.print("request code\n", .{});
if (last < std.time.milliTimestamp() - 1500 and on_build) {
obs.Scene.swapPreview();
}
on_build = false;
last = std.time.milliTimestamp();
}
 
fn watchSway(_: ?*anyopaque) void {
obs.blog(obs.LOG_INFO, "sway thread running");
obs.log("sway thread running");
var sway = sway_ipc.Connection.init(alloc) catch |err| {
logFmt("connection error {}", .{err});
obs.logFmt("connection error {}", .{err});
return;
};
sway.subscribe() catch {
log("crash trying to subscribe");
obs.log("crash trying to subscribe");
unreachable;
};
std.time.sleep(10_000_000_000);
gui.OBSScene.findScenes();
obs.Scene.findScenes();
while (running) {
const msg = sway.loop() catch {
log("unexpected read error");
obs.log("unexpected read error");
unreachable;
};
 
std.time.sleep(100_000_000);
switch (msg.toStruct(alloc) catch {
log("unable to build struct");
obs.log("unable to build struct");
continue;
}) {
.window => |w| {
for (w.container.marks) |mark| {
if (std.mem.eql(u8, mark, "build")) {
//std.debug.print("found {}\n", .{w.container});
gui.OBSScene.requestBuild();
requestBuild();
break;
}
} else {
gui.OBSScene.requestCode();
requestCode();
}
},
}
}
log("sway-focus thread exit");
obs.log("sway-focus thread exit");
}
 
var threads: [1]std.Thread = undefined;
 
export fn obs_module_load() bool {
fn on_load() bool {
arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
alloc = arena.allocator();
threads[0] = std.Thread.spawn(.{}, watchSway, .{null}) catch unreachable;
 
logFmt("sway-focus plugin loaded successfully {s}", .{PLUGIN_VERSION});
 
return true;
}
 
export fn obs_module_unload() void {
log("sway-focus plugin shutdown");
fn on_unload() void {
running = false;
std.Thread.join(threads[0]);
arena.deinit();