feat: add rofi-based power menu and power mode menu scripts with custom styles;
feat: enhance screen recorder with merge functionality and duration tracking; refactor: update swaync configuration with new power menu buttons and toggle actions; fix: remove desktop cache option since it screwed up my app history; refactor: update swaync styling with new button variables and border styles;
This commit is contained in:
@@ -16,5 +16,4 @@ ln -s $image /tmp/rofi-img.png
|
||||
rofi \
|
||||
-modes drun,run,calc \
|
||||
-show drun \
|
||||
-theme /tmp/rofi-theme.rasi \
|
||||
-drun-use-desktop-cache
|
||||
-theme /tmp/rofi-theme.rasi
|
||||
|
||||
24
rofi/scripts/dmenu_powermenu.sh
Executable file
24
rofi/scripts/dmenu_powermenu.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
mode=$(echo -e "\n⏻\n" | rofi \
|
||||
-modes drun,run,calc \
|
||||
-dmenu -p "Power menu" \
|
||||
-theme "$HOME/.config/rofi/styles/style-powermenu.rasi" \
|
||||
-markup-rows \
|
||||
-drun-use-desktop-cache \
|
||||
)
|
||||
|
||||
case "$mode" in
|
||||
"")
|
||||
systemctl suspend
|
||||
;;
|
||||
"⏻")
|
||||
systemctl poweroff
|
||||
;;
|
||||
"")
|
||||
systemctl reboot
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
24
rofi/scripts/dmenu_powermodemenu.sh
Executable file
24
rofi/scripts/dmenu_powermodemenu.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
mode=$(echo -e "\n\n" | rofi \
|
||||
-modes drun,run,calc \
|
||||
-dmenu -p "Power menu" \
|
||||
-theme "$HOME/.config/rofi/styles/style-powermodemenu.rasi" \
|
||||
-markup-rows \
|
||||
-drun-use-desktop-cache \
|
||||
)
|
||||
|
||||
case "$mode" in
|
||||
"")
|
||||
powerprofilesctl set power-saver
|
||||
;;
|
||||
"")
|
||||
powerprofilesctl set balanced
|
||||
;;
|
||||
"")
|
||||
powerprofilesctl set performance
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
@@ -1,9 +1,96 @@
|
||||
#!/bin/sh
|
||||
|
||||
mic_device="alsa_input.pci-0000_00_1f.3.analog-stereo"
|
||||
system_device="alsa_output.pci-0000_00_1f.3.analog-stereo.monitor"
|
||||
save_path="$HOME/Videos/rofi-recorder"
|
||||
datetime=$(date +"%d.%m.%Y %H:%M:%S")
|
||||
lockfile="/tmp/.rofi-recorder"
|
||||
|
||||
if [[ -z $lockfile ]]; then
|
||||
notify-send --hint int:transient:1 -t 1000 "Recorder" "Lockfile is present!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
check_total_time() {
|
||||
target_prefix=$1
|
||||
mkdir -p $save_path
|
||||
|
||||
( cd $save_path &&
|
||||
for f in $target_prefix*.mkv; do
|
||||
ffmpeg -i "$f" 2>&1 | grep "Duration" | awk '{print $2}' | tr -d ,;
|
||||
done | awk -F: '{ total += $1 * 3600 + $2 * 60 + $3 } END { print int(total/3600)":"int((total%3600)/60)":"int(total%60) }'
|
||||
)
|
||||
}
|
||||
|
||||
merge_videos() {
|
||||
target_prefix=$1
|
||||
result_prefix=$2
|
||||
touch $lockfile
|
||||
mkdir -p $save_path
|
||||
|
||||
local files=("$save_path"/$target_prefix*.mkv)
|
||||
if [[ ${#files[@]} -eq 0 ]] || [[ ! -f "${files[0]}" ]]; then
|
||||
notify-send "Error" "No MKV files found in $save_path"
|
||||
rm $lockfile
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create output filename with timestamp
|
||||
local output_file="$save_path/$result_prefix-$datetime.mkv"
|
||||
local file_list="$save_path/$target_prefix_list.txt"
|
||||
|
||||
# Create file list in creation order (oldest first)
|
||||
find "$save_path" -maxdepth 1 -name "*$target_prefix*.mkv" -not -name "$result_prefix*.mkv" -type f -printf "%T@ %p\n" | \
|
||||
sort -n | \
|
||||
cut -d' ' -f2- > "$file_list"
|
||||
|
||||
# Convert file paths to ffmpeg concat format
|
||||
sed -i 's/^/file /' "$file_list"
|
||||
# Escape single quotes and wrap paths in single quotes for ffmpeg
|
||||
sed -i "s|file \(.*\)|file '\1'|" "$file_list"
|
||||
|
||||
# Show ongoing notification
|
||||
notify-send -u low -i video-x-generic "Merging Videos" "Merging $(wc -l < "$file_list") video files..." &
|
||||
local notify_pid=$!
|
||||
|
||||
# Merge videos using ffmpeg concat demuxer
|
||||
if ffmpeg -f concat -safe 0 -i "$file_list" -c copy "$output_file" -y 2>/dev/null; then
|
||||
# Kill the ongoing notification
|
||||
kill $notify_pid 2>/dev/null
|
||||
|
||||
# Clean up temporary file
|
||||
rm -f "$file_list"
|
||||
|
||||
# Remove lockfile
|
||||
rm $lockfile
|
||||
|
||||
action=$(notify-send -A "Nice" -A "Delete clips" "Merge Complete" \
|
||||
"Videos merged successfully into $(basename "$output_file")")
|
||||
|
||||
if [[ "$action" == "1" ]]; then
|
||||
# Delete all original MKV files except the merged one
|
||||
find "$save_path" -maxdepth 1 -name "$target_prefix*.mkv" -not -name "$result_prefix*.mkv" -type f -exec gio trash {} +
|
||||
notify-send --hint int:transient:1 -t 1000 "Recorder" "Stopping"
|
||||
fi
|
||||
|
||||
else
|
||||
# Kill the ongoing notification
|
||||
kill $notify_pid 2>/dev/null
|
||||
|
||||
# Clean up on failure
|
||||
rm -f "$file_list"
|
||||
rm -f "$output_file"
|
||||
|
||||
notify-send -u critical "Merge Failed" "Failed to merge video files"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if wf-recorder is already running
|
||||
if pgrep -x "wf-recorder" > /dev/null; then
|
||||
current_file=$(ps -o args= -C wf-recorder | head -n1 | grep -oE '[^ ]+\.mp4' | tail -n1)
|
||||
|
||||
notify-send --hint int:transient:1 -t 1000 "Recorder" "Stopping"
|
||||
pkill -2 wf-recorder
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
@@ -11,13 +98,15 @@ if pgrep -x "wf-recorder" > /dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
datetime=$(date +"%d.%m.%Y %H:%M:%S")
|
||||
clips_total_duration=$(check_total_time clip)
|
||||
merges_total_duration=$(check_total_time merged)
|
||||
|
||||
mode=$(echo -e "動画のみ\nマイク\nシステムの音\n全面的" | rofi \
|
||||
# The modes are video only, +mic, +system audio, full.
|
||||
mode=$(echo -e "Video only\nMicrophone\nMerge clips" | rofi \
|
||||
-modes drun,run,calc \
|
||||
-dmenu -p "ビデオ録画モードを選択 " \
|
||||
-dmenu -p "Clips duration: $clips_total_duration / Merges duration: $merges_total_duration" \
|
||||
-theme "$HOME/.config/rofi/styles/style-recorder.rasi" \
|
||||
-markup-rows \
|
||||
-markup-rows \
|
||||
-drun-use-desktop-cache \
|
||||
)
|
||||
|
||||
@@ -26,5 +115,38 @@ if [[ -z "$mode" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wf-recorder -c libx264rgb -r 30 -a --audio-backend=pipewire -f "$HOME/Videos/$datetime.mkv"
|
||||
notify-send --hint int:transient:1 -t 1000 "Recorder" "Video saved as $datetime.mkv"
|
||||
case "$mode" in
|
||||
"Video only")
|
||||
# Video only - no audio
|
||||
wf-recorder -c libx264rgb -r 30 -f "$save_path/clip_$datetime.mkv" &
|
||||
;;
|
||||
"Microphone")
|
||||
# With mic only
|
||||
wf-recorder -c libx264rgb -r 30 -a "$mic_device" --audio-backend=pulse -f "$save_path/clip_$datetime.mkv" &
|
||||
;;
|
||||
"Merge clips")
|
||||
merge_videos clip merged
|
||||
;;
|
||||
*)
|
||||
notify-send --hint int:transient:1 -t 1000 "Recorder" "Invalid mode selected"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
recorder_pid=$!
|
||||
|
||||
sleep 1
|
||||
if ps -p $recorder_pid > /dev/null; then
|
||||
else
|
||||
notify-send --hint int:transient:1 -t 3000 "Recorder" "Failed to start recording"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for the recording process to finish
|
||||
wait $recorder_pid
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notify-send --hint int:transient:1 -t 3000 "Recorder" "Video saved $save_path/clip_$datetime.mkv"
|
||||
else
|
||||
notify-send --hint int:transient:1 -t 3000 "Recorder" "Recording failed or was interrupted"
|
||||
fi
|
||||
|
||||
100
rofi/styles/style-powermenu.rasi
Normal file
100
rofi/styles/style-powermenu.rasi
Normal file
@@ -0,0 +1,100 @@
|
||||
* {
|
||||
background: #1c1c1cc0;
|
||||
background-alt: #303030ff;
|
||||
button-shape-top: #505050ff;
|
||||
button-shape-bottom: #303030ff;
|
||||
background-button: #2e2d31ff;
|
||||
background-input: #1c1c1cc0;
|
||||
border: #48535Ccf;
|
||||
foreground: #FFe8EE;
|
||||
selected: #9E2238dd;
|
||||
selected-shine: #CE5268dd;
|
||||
active: #9E2238;
|
||||
urgent: #D14781;
|
||||
background-color: @background;
|
||||
border-color: White;
|
||||
text-color: @foreground;
|
||||
font: "JetBrains Mono Nerd Font 32";
|
||||
}
|
||||
window {
|
||||
anchor: center;
|
||||
location: center;
|
||||
width: 1000px;
|
||||
height: 250px;
|
||||
padding: 6px;
|
||||
children: [ mainbox ];
|
||||
border: 1px;
|
||||
border-radius: 15px;
|
||||
border-color: @border;
|
||||
background-color: @background;
|
||||
}
|
||||
|
||||
mainbox {
|
||||
orientation: vertical;
|
||||
spacing: 10px;
|
||||
children: [ listview ];
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
listview {
|
||||
enabled: true;
|
||||
columns: 1;
|
||||
lines: 3;
|
||||
cycle: true;
|
||||
dynamic: true;
|
||||
scrollbar: false;
|
||||
layout: horizontal;
|
||||
reverse: false;
|
||||
fixed-height: true;
|
||||
fixed-columns: true;
|
||||
height: 100px;
|
||||
spacing: 10px;
|
||||
background-color: transparent;
|
||||
text-color: @foreground;
|
||||
cursor: "default";
|
||||
font: "JetBrains Mono Nerd Font 10";
|
||||
}
|
||||
|
||||
/*****----- Elements -----*****/
|
||||
element {
|
||||
enabled: true;
|
||||
spacing: 15px;
|
||||
width: calc(100% / 3 - 12);
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
text-color: @foreground;
|
||||
cursor: pointer;
|
||||
background-color: @background-button;
|
||||
border-color: @button-shape-top;
|
||||
border: 1px 0 0 0;
|
||||
}
|
||||
|
||||
element selected.normal {
|
||||
background-color: @active;
|
||||
text-color: @foreground;
|
||||
border-color: @selected-shine;
|
||||
border: 1px 0 0 0;
|
||||
}
|
||||
|
||||
element-text {
|
||||
vertical-align: 0.5;
|
||||
horizontal-align: 0.5;
|
||||
padding: 80;
|
||||
}
|
||||
|
||||
prompt {
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
entry {
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
element selected {
|
||||
background-color: @selected;
|
||||
}
|
||||
|
||||
element-text, element-icon {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
}
|
||||
101
rofi/styles/style-powermodemenu.rasi
Normal file
101
rofi/styles/style-powermodemenu.rasi
Normal file
@@ -0,0 +1,101 @@
|
||||
* {
|
||||
background: #1c1c1cc0;
|
||||
background-alt: #303030ff;
|
||||
button-shape-top: #505050ff;
|
||||
button-shape-bottom: #303030ff;
|
||||
background-button: #2e2d31ff;
|
||||
background-input: #1c1c1cc0;
|
||||
border: #48535Ccf;
|
||||
foreground: #FFe8EE;
|
||||
selected: #9E2238dd;
|
||||
selected-shine: #CE5268dd;
|
||||
active: #9E2238;
|
||||
urgent: #D14781;
|
||||
background-color: @background;
|
||||
border-color: White;
|
||||
text-color: @foreground;
|
||||
font: "JetBrains Mono Nerd Font 32";
|
||||
}
|
||||
|
||||
window {
|
||||
anchor: center;
|
||||
location: center;
|
||||
width: 1000px;
|
||||
height: 250px;
|
||||
padding: 6px;
|
||||
children: [ mainbox ];
|
||||
border: 1px;
|
||||
border-radius: 15px;
|
||||
border-color: @border;
|
||||
background-color: @background;
|
||||
}
|
||||
|
||||
mainbox {
|
||||
orientation: vertical;
|
||||
spacing: 10px;
|
||||
children: [ listview ];
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
listview {
|
||||
enabled: true;
|
||||
columns: 1;
|
||||
lines: 3;
|
||||
cycle: true;
|
||||
dynamic: true;
|
||||
scrollbar: false;
|
||||
layout: horizontal;
|
||||
reverse: false;
|
||||
fixed-height: true;
|
||||
fixed-columns: true;
|
||||
height: 100px;
|
||||
spacing: 10px;
|
||||
background-color: transparent;
|
||||
text-color: @foreground;
|
||||
cursor: "default";
|
||||
font: "JetBrains Mono Nerd Font 10";
|
||||
}
|
||||
|
||||
/*****----- Elements -----*****/
|
||||
element {
|
||||
enabled: true;
|
||||
spacing: 15px;
|
||||
width: calc(100% / 3 - 12);
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
text-color: @foreground;
|
||||
cursor: pointer;
|
||||
background-color: @background-button;
|
||||
border-color: @button-shape-top;
|
||||
border: 1px 0 0 0;
|
||||
}
|
||||
|
||||
element selected.normal {
|
||||
background-color: @active;
|
||||
text-color: @foreground;
|
||||
border-color: @selected-shine;
|
||||
border: 1px 0 0 0;
|
||||
}
|
||||
|
||||
element-text {
|
||||
vertical-align: 0.5;
|
||||
horizontal-align: 0.5;
|
||||
padding: 80;
|
||||
}
|
||||
|
||||
prompt {
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
entry {
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
element selected {
|
||||
background-color: @selected;
|
||||
}
|
||||
|
||||
element-text, element-icon {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
}
|
||||
@@ -48,13 +48,14 @@ imagebox {
|
||||
border-radius: 100px;
|
||||
margin: 5px;
|
||||
background-color: @active;
|
||||
|
||||
border-color: @selected-shine;
|
||||
border: 1px 0 0 0;
|
||||
}
|
||||
|
||||
contentbox {
|
||||
orientation: horizontal;
|
||||
expand: true;
|
||||
children: [prompt, entry];
|
||||
children: [prompt];
|
||||
}
|
||||
|
||||
mode-switcher{
|
||||
@@ -67,7 +68,7 @@ mode-switcher{
|
||||
listview {
|
||||
enabled: true;
|
||||
columns: 1;
|
||||
lines: 4;
|
||||
lines: 3;
|
||||
cycle: true;
|
||||
dynamic: true;
|
||||
scrollbar: false;
|
||||
@@ -87,7 +88,7 @@ listview {
|
||||
element {
|
||||
enabled: true;
|
||||
spacing: 15px;
|
||||
width: 22.5%;
|
||||
width: 31%;
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
text-color: @foreground;
|
||||
|
||||
Reference in New Issue
Block a user