Compare commits
3 Commits
45bda5b588
...
73f5a690bb
Author | SHA1 | Date | |
---|---|---|---|
73f5a690bb | |||
54db751e23 | |||
85299b65dc |
@ -15,10 +15,21 @@ let
|
|||||||
url = "https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad";
|
url = "https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad";
|
||||||
hash = "sha256-HX1DvlAeZ9kn5BXguPPinDvzMHXoWXIYFvZSpSbKx3E=";
|
hash = "sha256-HX1DvlAeZ9kn5BXguPPinDvzMHXoWXIYFvZSpSbKx3E=";
|
||||||
};
|
};
|
||||||
doomNcurses = pkgs.writeShellScript "doom-ncurses" ''
|
# doomNcurses = pkgs.writeShellScript "doom-ncurses" ''
|
||||||
SDL_AUDIODRIVER=null SDL_VIDEODRIVER=caca CACA_DRIVER=ncurses exec ${pkgs.chocolate-doom2xx}/bin/chocolate-doom -iwad ${doomWad}
|
# SDL_AUDIODRIVER=null SDL_VIDEODRIVER=caca CACA_DRIVER=ncurses exec ${pkgs.chocolate-doom2xx}/bin/chocolate-doom -iwad ${doomWad}
|
||||||
|
# '';
|
||||||
|
# lockCmd = "swaylock-plugin --command-each '${pkgs.windowtolayer}/bin/windowtolayer -- alacritty -e ${doomNcurses}'";
|
||||||
|
|
||||||
|
doomsaver = pkgs.runCommand "doomsaver" {
|
||||||
|
inherit (pkgs) windowtolayer;
|
||||||
|
chocoDoom = pkgs.chocolate-doom2xx;
|
||||||
|
python = pkgs.python3.withPackages (ps: [ ps.filelock ]);
|
||||||
|
inherit doomWad;
|
||||||
|
} ''
|
||||||
|
mkdir -p "$out"/bin
|
||||||
|
substituteAll ${./screensaver.py} "$out"/bin/doomsaver
|
||||||
|
chmod +x "$out"/bin/doomsaver
|
||||||
'';
|
'';
|
||||||
lockCmd = "swaylock-plugin --command-each '${pkgs.windowtolayer}/bin/windowtolayer -- alacritty -e ${doomNcurses}'";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.my.gui = {
|
options.my.gui = {
|
||||||
@ -45,7 +56,14 @@ in
|
|||||||
nil # nix language server
|
nil # nix language server
|
||||||
zls # zig language server
|
zls # zig language server
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
|
|
||||||
|
cowsay
|
||||||
|
fortune
|
||||||
|
terminaltexteffects
|
||||||
|
screenfetch
|
||||||
neofetch
|
neofetch
|
||||||
|
cmatrix
|
||||||
|
doomsaver
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,7 +216,7 @@ in
|
|||||||
in
|
in
|
||||||
lib.mkOptionDefault {
|
lib.mkOptionDefault {
|
||||||
"${mod}+d" = null;
|
"${mod}+d" = null;
|
||||||
"${mod}+l" = "exec ${lockCmd}";
|
"${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
|
||||||
"${mod}+x" = "exec ${cfg.menu}";
|
"${mod}+x" = "exec ${cfg.menu}";
|
||||||
"${mod}+Shift+x" = "exec rofi -show drun";
|
"${mod}+Shift+x" = "exec rofi -show drun";
|
||||||
"${mod}+q" = "kill";
|
"${mod}+q" = "kill";
|
||||||
|
199
home-manager/modules/gui/screensaver.py
Executable file
199
home-manager/modules/gui/screensaver.py
Executable file
@ -0,0 +1,199 @@
|
|||||||
|
#!@python@/bin/python
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import filelock
|
||||||
|
|
||||||
|
class Screensaver:
|
||||||
|
def __init__(self, cmd, env=None, weight=1):
|
||||||
|
self.cmd = cmd
|
||||||
|
self.weight = weight
|
||||||
|
|
||||||
|
if env is not None:
|
||||||
|
self.env = os.environ.copy()
|
||||||
|
for k, v in env.items():
|
||||||
|
self.env[k] = v
|
||||||
|
else:
|
||||||
|
self.env = None
|
||||||
|
self.proc = None
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
assert self.proc is None
|
||||||
|
self.proc = subprocess.Popen(self.cmd, env=self.env)
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
assert self.proc is not None
|
||||||
|
self.proc.wait()
|
||||||
|
|
||||||
|
def stop(self, kill=False):
|
||||||
|
assert self.proc is not None
|
||||||
|
if kill:
|
||||||
|
self.proc.kill()
|
||||||
|
else:
|
||||||
|
self.proc.terminate()
|
||||||
|
|
||||||
|
class DoomSaver(Screensaver):
|
||||||
|
wad = '@doomWad@'
|
||||||
|
|
||||||
|
def __init__(self, demo_index, weight=1.5):
|
||||||
|
super().__init__(
|
||||||
|
['@chocoDoom@/bin/chocolate-doom',
|
||||||
|
'-iwad', self.wad,
|
||||||
|
'-demoloopi', str(demo_index)],
|
||||||
|
env={
|
||||||
|
'SDL_AUDIODRIVER': 'null',
|
||||||
|
'SDL_VIDEODRIVER': 'caca',
|
||||||
|
'CACA_DRIVER': 'ncurses',
|
||||||
|
},
|
||||||
|
weight=weight,
|
||||||
|
)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
super().stop(kill=True)
|
||||||
|
|
||||||
|
class TTESaver(Screensaver):
|
||||||
|
effects = (
|
||||||
|
'beams,binarypath,blackhole,bouncyballs,bubbles,burn,colorshift,crumble,'
|
||||||
|
'decrypt,errorcorrect,expand,fireworks,middleout,orbittingvolley,overflow,'
|
||||||
|
'pour,print,rain,randomsequence,rings,scattered,slice,slide,spotlights,'
|
||||||
|
'spray,swarm,synthgrid,unstable,vhstape,waves,wipe'
|
||||||
|
).split(',')
|
||||||
|
|
||||||
|
def __init__(self, cmd, env=None, weight=1):
|
||||||
|
super().__init__(cmd, env=env, weight=weight)
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
while self.running:
|
||||||
|
effect_cmd = ['tte', random.choice(self.effects)]
|
||||||
|
print(f"$ {' '.join(self.cmd)} | {' '.join(effect_cmd)}")
|
||||||
|
content = subprocess.check_output(self.cmd, env=self.env, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
self.proc = subprocess.Popen(effect_cmd, stdin=subprocess.PIPE)
|
||||||
|
self.proc.stdin.write(content)
|
||||||
|
self.proc.stdin.close()
|
||||||
|
self.proc.wait()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.running = False
|
||||||
|
self.proc.terminate()
|
||||||
|
|
||||||
|
class MultiSaver:
|
||||||
|
savers = [
|
||||||
|
DoomSaver(0),
|
||||||
|
DoomSaver(1),
|
||||||
|
DoomSaver(2),
|
||||||
|
|
||||||
|
Screensaver(['cmatrix']),
|
||||||
|
|
||||||
|
TTESaver(['screenfetch', '-N']),
|
||||||
|
TTESaver(['fortune']),
|
||||||
|
TTESaver(['top', '-n1']),
|
||||||
|
TTESaver(['ss', '-nltu']),
|
||||||
|
TTESaver(['ss', '-ntu']),
|
||||||
|
]
|
||||||
|
state_filename = 'screensaver.json'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.state_path = os.path.join(f'/run/user/{os.geteuid()}', self.state_filename)
|
||||||
|
self.lock = filelock.FileLock(f'{self.state_path}.lock')
|
||||||
|
|
||||||
|
self.selected = None
|
||||||
|
self.cleaned_up = False
|
||||||
|
|
||||||
|
def select(self):
|
||||||
|
assert self.selected is None
|
||||||
|
with self.lock:
|
||||||
|
if not os.path.exists(self.state_path):
|
||||||
|
state = {'instances': []}
|
||||||
|
else:
|
||||||
|
with open(self.state_path) as f:
|
||||||
|
state = json.load(f)
|
||||||
|
|
||||||
|
available = set(range(len(self.savers)))
|
||||||
|
new_instances = []
|
||||||
|
for instance in state['instances']:
|
||||||
|
if not os.path.exists(f"/proc/{instance['pid']}"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_instances.append(instance)
|
||||||
|
i = instance['saver']
|
||||||
|
assert i in available
|
||||||
|
available.remove(i)
|
||||||
|
assert available, 'No screensavers left'
|
||||||
|
available = list(available)
|
||||||
|
|
||||||
|
weights = []
|
||||||
|
for i in available:
|
||||||
|
weights.append(self.savers[i].weight)
|
||||||
|
selected_i = random.choices(available, weights=weights)[0]
|
||||||
|
|
||||||
|
new_instances.append({'pid': os.getpid(), 'saver': selected_i})
|
||||||
|
state['instances'] = new_instances
|
||||||
|
|
||||||
|
with open(self.state_path, 'w') as f:
|
||||||
|
json.dump(state, f)
|
||||||
|
|
||||||
|
# print(f'Selected saver {selected_i}')
|
||||||
|
self.selected = self.savers[selected_i]
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
if self.cleaned_up:
|
||||||
|
return
|
||||||
|
self.cleaned_up = True
|
||||||
|
|
||||||
|
with self.lock:
|
||||||
|
with open(self.state_path) as f:
|
||||||
|
state = json.load(f)
|
||||||
|
|
||||||
|
for i, instance in enumerate(state['instances']):
|
||||||
|
if instance['pid'] == os.getpid():
|
||||||
|
del state['instances'][i]
|
||||||
|
|
||||||
|
with open(self.state_path, 'w') as f:
|
||||||
|
json.dump(state, f)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
assert self.selected is not None
|
||||||
|
self.selected.start()
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, self._sighandler)
|
||||||
|
signal.signal(signal.SIGTERM, self._sighandler)
|
||||||
|
signal.signal(signal.SIGHUP, self._sighandler)
|
||||||
|
self.selected.wait()
|
||||||
|
self.cleanup()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
assert self.selected is not None
|
||||||
|
print('Shutting down')
|
||||||
|
self.selected.stop()
|
||||||
|
self.cleanup()
|
||||||
|
def _sighandler(self, signum, frame):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Wayland terminal-based lock screen')
|
||||||
|
parser.add_argument('-t', '--terminal', default='alacritty', help='Terminal emulator to use')
|
||||||
|
parser.add_argument('-i', '--instance', action='store_true', help='Run as instance')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
if not args.instance:
|
||||||
|
subprocess.check_call([
|
||||||
|
'swaylock-plugin', '--command-each',
|
||||||
|
f'@windowtolayer@/bin/windowtolayer -- {args.terminal} -e {sys.argv[0]} --instance'])
|
||||||
|
return
|
||||||
|
|
||||||
|
ms = MultiSaver()
|
||||||
|
ms.select()
|
||||||
|
ms.run()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -12,4 +12,5 @@ in
|
|||||||
chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
|
chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
|
||||||
windowtolayer = callPackage ./windowtolayer.nix { };
|
windowtolayer = callPackage ./windowtolayer.nix { };
|
||||||
swaylock-plugin = callPackage ./swaylock-plugin.nix { };
|
swaylock-plugin = callPackage ./swaylock-plugin.nix { };
|
||||||
|
terminaltexteffects = callPackage ./terminaltexteffects.nix { };
|
||||||
}
|
}
|
||||||
|
19
pkgs/terminaltexteffects.nix
Normal file
19
pkgs/terminaltexteffects.nix
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{ lib
|
||||||
|
, python3Packages
|
||||||
|
, fetchPypi
|
||||||
|
}:
|
||||||
|
|
||||||
|
python3Packages.buildPythonApplication rec {
|
||||||
|
pname = "terminaltexteffects";
|
||||||
|
version = "0.10.1";
|
||||||
|
pyproject = true;
|
||||||
|
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-NyWPfdgLeXAxKPJOzB7j4aT+zjrURN59CGcv0Vt99y0=";
|
||||||
|
};
|
||||||
|
|
||||||
|
build-system = with python3Packages; [
|
||||||
|
poetry-core
|
||||||
|
];
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user