mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-05-17 06:23:50 +02:00
159 lines
4.5 KiB
Zig
159 lines
4.5 KiB
Zig
const std = @import("std");
|
|
const xinerama = @import("xinerama.zig");
|
|
const Walker = @import("Walker.zig");
|
|
|
|
pub const std_options = std.Options{
|
|
.log_level = .debug,
|
|
.logFn = @import("common").logFn,
|
|
};
|
|
|
|
pub fn main() !u8 {
|
|
const alloc = std.heap.c_allocator;
|
|
const home_s = std.os.getenv("HOME") orelse return error.HomeNotSet;
|
|
const runtime_dir = std.os.getenv("XDG_RUNTIME_DIR") orelse return error.MissingRuntimeDir;
|
|
|
|
var walker = Walker.init(alloc);
|
|
defer walker.deinit();
|
|
|
|
try walker.walk(
|
|
try std.fs.openDirAbsolute(
|
|
"/usr/share/backgrounds/",
|
|
.{ .iterate = true },
|
|
),
|
|
);
|
|
|
|
try walkLocalWps(&walker, home_s);
|
|
|
|
const swww_socket_path = try std.fs.path.join(alloc, &.{ runtime_dir, "swww.socket" });
|
|
defer alloc.free(swww_socket_path);
|
|
|
|
const has_swww = if (std.fs.cwd().statFile(swww_socket_path)) |_| true else |e| switch (e) {
|
|
error.FileNotFound => false,
|
|
else => return e,
|
|
};
|
|
|
|
if (has_swww) {
|
|
std.log.info("found running swww daemon, using swww backend", .{});
|
|
return try setWallpapersSwww(alloc, walker.files.items);
|
|
} else {
|
|
std.log.info("using X/feh backend", .{});
|
|
return try setWallpapersX(alloc, walker.files.items);
|
|
}
|
|
}
|
|
|
|
fn walkLocalWps(walker: *Walker, home_s: []const u8) !void {
|
|
const wp_path = try std.fs.path.join(walker.files.allocator, &.{ home_s, ".local/share/backgrounds" });
|
|
defer walker.files.allocator.free(wp_path);
|
|
|
|
var local_wp = std.fs.cwd().openDir(wp_path, .{ .iterate = true }) catch |e| switch (e) {
|
|
error.FileNotFound => {
|
|
std.log.warn(
|
|
"No local wallpaper directory @ {s}, skipping local wallpapers",
|
|
.{wp_path},
|
|
);
|
|
return;
|
|
},
|
|
else => return e,
|
|
};
|
|
defer local_wp.close();
|
|
|
|
try walker.walk(local_wp);
|
|
}
|
|
|
|
fn setWallpapersSwww(alloc: std.mem.Allocator, wps: []const []const u8) !u8 {
|
|
const exec_res = try std.process.Child.run(.{
|
|
.allocator = alloc,
|
|
.argv = &.{ "swww", "query" },
|
|
});
|
|
defer alloc.free(exec_res.stdout);
|
|
defer alloc.free(exec_res.stderr);
|
|
|
|
if (!std.meta.eql(exec_res.term, .{ .Exited = 0 }))
|
|
return error.SwwwQuery;
|
|
|
|
var prng = std.rand.DefaultPrng.init(std.crypto.random.int(u64));
|
|
const rand = prng.random();
|
|
|
|
var output_iter = std.mem.tokenizeScalar(u8, exec_res.stdout, '\n');
|
|
while (output_iter.next()) |line| {
|
|
if (line.len == 0) continue;
|
|
const output = std.mem.sliceTo(line, ':');
|
|
|
|
const argv = [_][]const u8{
|
|
"swww",
|
|
"img",
|
|
wps[rand.uintAtMost(usize, wps.len - 1)],
|
|
"--outputs",
|
|
output,
|
|
"--transition-type",
|
|
"wipe",
|
|
"--transition-angle",
|
|
"30",
|
|
"--transition-bezier",
|
|
"0.8,0.0,0.2,1.0",
|
|
"--transition-fps",
|
|
"60",
|
|
"--transition-duration",
|
|
"2",
|
|
};
|
|
|
|
var child = std.process.Child.init(&argv, alloc);
|
|
const term = try child.spawnAndWait();
|
|
const code = switch (term) {
|
|
.Exited => |n| n,
|
|
.Signal,
|
|
.Stopped,
|
|
.Unknown,
|
|
=> |n| b: {
|
|
std.log.err("Child borked with code {}", .{n});
|
|
break :b 1;
|
|
},
|
|
};
|
|
|
|
if (code != 0) return code;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
fn setWallpapersX(alloc: std.mem.Allocator, wps: []const []const u8) !u8 {
|
|
const screens = try xinerama.getHeadCount();
|
|
|
|
const feh_baseargs = [_][]const u8{
|
|
"feh",
|
|
"--no-fehbg",
|
|
"--bg-fill",
|
|
};
|
|
|
|
var feh_argv = try alloc.alloc(
|
|
[]const u8,
|
|
feh_baseargs.len + @as(usize, @intCast(screens)),
|
|
);
|
|
defer alloc.free(feh_argv);
|
|
@memcpy(feh_argv[0..feh_baseargs.len], &feh_baseargs);
|
|
|
|
var prng = std.rand.DefaultPrng.init(std.crypto.random.int(u64));
|
|
const rand = prng.random();
|
|
|
|
var i: u31 = 0;
|
|
while (i < screens) : (i += 1) {
|
|
const idx = rand.uintAtMost(usize, wps.len - 1);
|
|
feh_argv[feh_baseargs.len + i] = wps[idx];
|
|
}
|
|
|
|
std.log.info("feh argv: {s}", .{feh_argv});
|
|
var child = std.process.Child.init(feh_argv, alloc);
|
|
const term = try child.spawnAndWait();
|
|
|
|
return switch (term) {
|
|
.Exited => |n| n,
|
|
.Signal,
|
|
.Stopped,
|
|
.Unknown,
|
|
=> |n| b: {
|
|
std.log.err("Child borked with code {}", .{n});
|
|
break :b 1;
|
|
},
|
|
};
|
|
}
|