From 5e091df8781e7a4b0deddde1ce165f0743887f3f Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Sat, 16 Mar 2024 19:04:56 +0100 Subject: [PATCH] port playvid to zig finally done with that one... --- scripts/playvid.ros | 39 --------------- scripts/playvid/.gitignore | 3 ++ scripts/playvid/build.zig | 24 +++++++++ scripts/playvid/src/main.zig | 80 ++++++++++++++++++++++++++++++ setup/commands/install-scripts.rkt | 2 +- 5 files changed, 108 insertions(+), 40 deletions(-) delete mode 100755 scripts/playvid.ros create mode 100644 scripts/playvid/.gitignore create mode 100644 scripts/playvid/build.zig create mode 100644 scripts/playvid/src/main.zig diff --git a/scripts/playvid.ros b/scripts/playvid.ros deleted file mode 100755 index c349934..0000000 --- a/scripts/playvid.ros +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env -S ros -Q -- -#|-*- mode:lisp -*-|# -#| -exec ros -Q -- $0 "$@" -|# -(progn ;;init forms - (ros:ensure-asdf) - #+quicklisp(ql:quickload '(uiop) :silent t)) - -(defpackage :playvid - (:use :cl)) -(in-package :playvid) - -(defun main (&rest argv) - (let* ((vidfile (or (uiop:parse-native-namestring (car argv)) - (let ((dir (uiop:directory-files "."))) - (nth (random (length dir) (make-random-state t)) dir)))) - (basename (pathname-name vidfile))) - (format t "playing video: ~a~%" basename) - (uiop:run-program (list "mpv" (uiop:native-namestring vidfile)) - :input :interactive - :error-output :interactive - :output :interactive - :ignore-error-status t) - - (let ((confirm (uiop:run-program (list - "rofi" - "-dmenu" - "-theme" - (format nil "~a/.local/share/rofi/applets/confirm.rasi" - (user-homedir-pathname)) - "-mesg" - (format nil "delete `~a`?" basename)) - :input (lambda (s) (format s "No~CYes" #\newline)) - :ignore-error-status t - :output :string))) - (when (string-equal (format nil "Yes~C" #\newline) confirm) - (format t "deleting file `~a`~%" basename) - (delete-file vidfile))))) diff --git a/scripts/playvid/.gitignore b/scripts/playvid/.gitignore new file mode 100644 index 0000000..5da67ec --- /dev/null +++ b/scripts/playvid/.gitignore @@ -0,0 +1,3 @@ +zig-cache/ +zig-out/ +flake.lock diff --git a/scripts/playvid/build.zig b/scripts/playvid/build.zig new file mode 100644 index 0000000..499b233 --- /dev/null +++ b/scripts/playvid/build.zig @@ -0,0 +1,24 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "playvid", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + b.installArtifact(exe); + + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/scripts/playvid/src/main.zig b/scripts/playvid/src/main.zig new file mode 100644 index 0000000..4c8aa02 --- /dev/null +++ b/scripts/playvid/src/main.zig @@ -0,0 +1,80 @@ +const std = @import("std"); + +pub fn main() !u8 { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const alloc = gpa.allocator(); + + var file_buf: [std.os.PATH_MAX]u8 = undefined; + const file = try findVideoFile(alloc, &file_buf); + + try std.io.getStdOut().writer().print("playing: `{s}`\n", .{file}); + + var child = std.process.Child.init(&.{ "mpv", file }, alloc); + const term = try child.spawnAndWait(); + if (!std.meta.eql(term, .{ .Exited = 0 })) return 1; + + if (try promtForDeletion(file)) { + try std.io.getStdOut().writer().print("deleting: `{s}`\n", .{file}); + try std.fs.cwd().deleteFile(file); + } + + return 0; +} + +fn findVideoFile(alloc: std.mem.Allocator, out_buf: []u8) ![]const u8 { + var basedir: []const u8 = "."; + if (std.os.argv.len >= 2) { + const arg = std.mem.span(std.os.argv[1]); + if ((try std.fs.cwd().statFile(arg)).kind == .directory) { + basedir = arg; + } else { + if (arg.len > out_buf.len) return error.OutOfMemory; + @memcpy(out_buf[0..arg.len], arg); + return out_buf[0..arg.len]; + } + } + + var fname_arena = std.heap.ArenaAllocator.init(alloc); + defer fname_arena.deinit(); + + var cwd_iter = try std.fs.cwd().openDir(basedir, .{ .iterate = true }); + defer cwd_iter.close(); + var iter = cwd_iter.iterate(); + var files = std.ArrayList([]const u8).init(alloc); + defer files.deinit(); + + while (try iter.next()) |entry| { + switch (entry.kind) { + .file => { + try files.append(try fname_arena.allocator().dupe(u8, entry.name)); + }, + else => {}, + } + } + + if (files.items.len == 0) return error.DirectoryEmpty; + const idx = std.crypto.random.uintLessThan(usize, files.items.len); + if (files.items[idx].len > out_buf.len) return error.OutOfMemory; + @memcpy(out_buf[0..files.items[idx].len], files.items[idx]); + return out_buf[0..files.items[idx].len]; +} + +fn promtForDeletion(file: []const u8) !bool { + try std.io.getStdOut().writer().print("delete file `{s}`? [Y/N] ", .{file}); + + const old_termios = try std.os.tcgetattr(std.os.STDIN_FILENO); + var new_termios = old_termios; + new_termios.lflag.ICANON = false; // No line buffering + try std.os.tcsetattr(std.os.STDIN_FILENO, .NOW, new_termios); + defer std.os.tcsetattr(std.os.STDIN_FILENO, .NOW, old_termios) catch {}; + + const answer = try std.io.getStdIn().reader().readByte(); + const ret = switch (answer) { + 'y', 'Y' => true, + else => false, + }; + + try std.io.getStdOut().writeAll("\n"); + return ret; +} diff --git a/setup/commands/install-scripts.rkt b/setup/commands/install-scripts.rkt index a4eb155..814e5a2 100644 --- a/setup/commands/install-scripts.rkt +++ b/setup/commands/install-scripts.rkt @@ -24,6 +24,7 @@ (install-zig "scripts/mzteriver") (install-zig "scripts/openbrowser") (install-zig "scripts/playtwitch") + (install-zig "scripts/playvid") (install-zig "scripts/prompt") (install-zig "scripts/randomwallpaper") (install-zig "scripts/vinput") @@ -31,5 +32,4 @@ (install-zig "scripts/wlbg") (install-roswell "scripts/launchmenu.ros") - (install-roswell "scripts/playvid.ros") null)