summaryrefslogtreecommitdiff
path: root/ar/.local
diff options
context:
space:
mode:
Diffstat (limited to 'ar/.local')
-rwxr-xr-xar/.local/bin/dmenudelmusic14
-rwxr-xr-xar/.local/bin/emojiupdate2
-rw-r--r--[-rwxr-xr-x]ar/.local/bin/qndl90
-rwxr-xr-xar/.local/bin/setmonitors2
-rwxr-xr-xar/.local/bin/v2m24
5 files changed, 41 insertions, 91 deletions
diff --git a/ar/.local/bin/dmenudelmusic b/ar/.local/bin/dmenudelmusic
index fce8db2..c28130a 100755
--- a/ar/.local/bin/dmenudelmusic
+++ b/ar/.local/bin/dmenudelmusic
@@ -8,7 +8,7 @@ playlist_dir="${XDG_CONFIG_HOME:-${HOME}/.config}/mpd/playlists"
# Select the relative path. Sort the list so "first match" semantics in dmenu
# are deterministic — otherwise filesystem order is unstable and typing a
-# substring (e.g. "성시경") can return whichever file find walked first.
+# substring can return whichever file find walked first.
# `-not -path '*/.*'` skips hidden files (.music.txt, etc.); name filter limits to audio.
selected_relpath=$(cd "$music_dir" && find . -type f -not -path '*/.*' \( -name '*.mp3' -o -name '*.m4a' -o -name '*.opus' -o -name '*.flac' -o -name '*.wav' -o -name '*.webm' \) | sed 's|^\./||' | LC_ALL=C.UTF-8 sort | dmenu -i -l 20 -p "Select a file to delete:") || exit 1
[ -n "$selected_relpath" ] || exit 1
@@ -45,12 +45,18 @@ remove_id_from() {
}
if remove_id_from "$music_txt" && remove_id_from "$music_titles"; then
- # Remove the relative path from playlists (-F avoids regex pitfalls with [], (), etc.)
+ # Remove the relative path from every playlist (entire.m3u + genre lists like
+ # jpop/kpop/pop). -F avoids regex pitfalls with [], (), etc.
+ # These .m3u files are symlinks into the dotfiles repo, so write the result
+ # back with `cat > "$playlist"` (which follows the symlink) instead of
+ # `mv`/`sed -i`, both of which would replace the symlink with a plain file.
for playlist in "$playlist_dir"/*.m3u; do
[ -e "$playlist" ] || continue
if grep -Fq "$selected_relpath" "$playlist"; then
- grep -Fv "$selected_relpath" "$playlist" > "${playlist}.tmp" && mv "${playlist}.tmp" "$playlist"
- sed -i '/^$/d' "$playlist"
+ _pl_tmp="$(mktemp)" || continue
+ grep -Fv "$selected_relpath" "$playlist" | sed '/^$/d' > "$_pl_tmp"
+ cat "$_pl_tmp" > "$playlist"
+ rm -f "$_pl_tmp"
fi
done
diff --git a/ar/.local/bin/emojiupdate b/ar/.local/bin/emojiupdate
index 666d7d2..59cad1c 100755
--- a/ar/.local/bin/emojiupdate
+++ b/ar/.local/bin/emojiupdate
@@ -29,7 +29,7 @@ awk '
{ print }
' "$input_file" >"$temp_file"
-# Extract + VS16 제거
+# Extract + strip VS16
awk -F'#' '
{
if (NF >= 2) {
diff --git a/ar/.local/bin/qndl b/ar/.local/bin/qndl
index 5cc8783..b9d8fa7 100755..100644
--- a/ar/.local/bin/qndl
+++ b/ar/.local/bin/qndl
@@ -31,6 +31,17 @@ normalize_url() {
printf '%s' "$1" | sed 's|\.sooplive\.com/|.sooplive.co.kr/|'
}
+to_music_url() {
+ # Route YouTube links through music.youtube.com. The YouTube Music frontend
+ # yields cleaner song metadata (album/track/artist) than the plain video
+ # page. Non-YouTube URLs and already-music.youtube.com links pass through
+ # untouched; youtu.be short links are expanded to a watch?v= form.
+ printf '%s' "$1" | sed -E '
+ s#^(https?://)?(www\.|m\.)?youtube\.com/#https://music.youtube.com/#
+ s#^(https?://)?youtu\.be/([A-Za-z0-9_-]+).*#https://music.youtube.com/watch?v=\2#
+ '
+}
+
get_url() {
for _arg in "$@"; do
case "$_arg" in
@@ -81,10 +92,6 @@ get_type() {
printf 'kill'
return 0
;;
- -d | --delete | d | delete)
- printf 'delete'
- return 0
- ;;
*)
printf '%s' "$_arg"
return 0
@@ -264,7 +271,7 @@ handle_playlist() {
# ---------------------------------------------------------------------------
download_music() {
- _url="$1"
+ _url="$(to_music_url "$1")"
_output_dir="${XDG_MUSIC_DIR:-$HOME/Music}"
_archive="${XDG_DOTFILES_DIR:-$HOME/.dotfiles}/global/Music/.music.txt"
_titles="${XDG_DOTFILES_DIR:-$HOME/.dotfiles}/global/Music/.music_titles.txt"
@@ -283,6 +290,7 @@ download_music() {
--extract-audio \
--audio-format mp3 \
--audio-quality 0 \
+ --parse-metadata "%(release_date,upload_date)s:%(meta_date)s" \
--download-archive "$_archive" \
--print-to-file "$_title_fmt" "$_titles" \
--output "$_fmt"
@@ -486,79 +494,18 @@ restore_archive() {
else
_t=""
fi
- enqueue "music" "https://www.youtube.com/watch?v=$_id" "${_t:-$_id}" \
+ enqueue "music" "https://music.youtube.com/watch?v=$_id" "${_t:-$_id}" \
--no-playlist \
--extract-audio \
--audio-format mp3 \
--audio-quality 0 \
+ --parse-metadata "%(release_date,upload_date)s:%(meta_date)s" \
--output "$_format"
done <"$_tmpfile"
rm -f "$_tmpfile"
notify "✅ All $_sel_total job(s) queued" "tsp will process them sequentially"
}
-delete_archive() {
- command -v fzf >/dev/null 2>&1 || die "⛔ fzf not installed" "Install fzf to use qndl -d."
-
- _archive="${XDG_DOTFILES_DIR:-$HOME/.dotfiles}/global/Music/.music.txt"
- _titles="${XDG_DOTFILES_DIR:-$HOME/.dotfiles}/global/Music/.music_titles.txt"
-
- [ ! -f "$_archive" ] && die "⛔ Archive not found" "$_archive"
-
- # fzf input: <id>\t<display>. --with-nth hides column 1, cut grabs it back.
- if [ -f "$_titles" ]; then
- _entries="$(awk '
- NR==FNR {
- tab = index($0, "\t")
- if (tab > 0) titles[substr($0, 1, tab-1)] = substr($0, tab+1)
- next
- }
- {
- sp = index($0, " ")
- if (sp == 0) next
- id = substr($0, sp+1)
- if (id == "") next
- if (id in titles) printf "%s\t%s [%s]\n", id, titles[id], id
- else printf "%s\t[%s]\n", id, id
- }
- ' "$_titles" "$_archive")"
- else
- _entries="$(awk '$2 != "" { printf "%s\t[%s]\n", $2, $2 }' "$_archive")"
- fi
-
- [ -z "$_entries" ] && die "⛔ Archive is empty" "Nothing to delete."
-
- _selected="$(printf '%s\n' "$_entries" |
- fzf -m \
- --with-nth=2.. \
- --delimiter='\t' \
- --prompt='Delete: ' \
- --header='TAB to mark multiple, Enter to confirm' |
- cut -f1)"
-
- [ -z "$_selected" ] && return 0
-
- _ids_file="$(mktemp)"
- printf '%s\n' "$_selected" >"$_ids_file"
-
- # YouTube IDs have no whitespace, so default FS works for both files.
- # Archive lines: "youtube <ID>" → drop where $2 matches.
- # Titles lines: "<ID>\t<title>" → drop where $1 matches.
- _new_archive="$(mktemp)"
- awk 'NR==FNR { drop[$1]=1; next } !($2 in drop)' "$_ids_file" "$_archive" >"$_new_archive" &&
- mv "$_new_archive" "$_archive"
-
- if [ -f "$_titles" ]; then
- _new_titles="$(mktemp)"
- awk 'NR==FNR { drop[$1]=1; next } !($1 in drop)' "$_ids_file" "$_titles" >"$_new_titles" &&
- mv "$_new_titles" "$_titles"
- fi
-
- _count="$(printf '%s\n' "$_selected" | grep -c .)"
- rm -f "$_ids_file"
-
- notify "🗑️ Removed $_count archive entry/entries" "from .music.txt and .music_titles.txt"
-}
# ---------------------------------------------------------------------------
# Listing & Cancellation
@@ -692,9 +639,6 @@ main() {
restore)
restore_archive
;;
- delete)
- delete_archive
- ;;
list)
list_queue
;;
@@ -702,10 +646,10 @@ main() {
kill_job
;;
"")
- die "⛔ No type specified" "Provide: music, video, restore, delete, list, or kill."
+ die "⛔ No type specified" "Provide: music, video, restore, list, or kill."
;;
*)
- die "⛔ Invalid type: $_type" "Recognized types: music, video, restore, delete, list, kill."
+ die "⛔ Invalid type: $_type" "Recognized types: music, video, restore, list, kill."
;;
esac
}
diff --git a/ar/.local/bin/setmonitors b/ar/.local/bin/setmonitors
index 76dabb8..287d785 100755
--- a/ar/.local/bin/setmonitors
+++ b/ar/.local/bin/setmonitors
@@ -9,7 +9,7 @@ edp_cfg="--mode 1920x1080 --rotate normal --scale 1.0x1.0 --dpi 82"
hdmi_cfg="--mode 1920x1080 --rotate normal --scale 1.0x1.0 --dpi 82"
dp_cfg="--mode 2560x1600 --rotate normal --scale 1.0x1.0 --dpi 192"
-# EDID 미감지 시 (640x480에 갇힌 경우) 1920x1080 폴백 적용
+# When EDID is not detected (stuck at 640x480), apply a 1920x1080 fallback
if xrandr -q | grep " connected" | grep -q "640x480+"; then
xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync 2>/dev/null
for output in $(xrandr -q | grep -w "connected" | cut -d ' ' -f 1); do
diff --git a/ar/.local/bin/v2m b/ar/.local/bin/v2m
index eda5d86..b2f0510 100755
--- a/ar/.local/bin/v2m
+++ b/ar/.local/bin/v2m
@@ -1,38 +1,38 @@
#!/bin/bash
-# 동영상에서 MP3 추출 스크립트
+# Extract MP3 audio from a video file
if [ $# -eq 0 ]; then
- echo "사용법: video2mp3 <입력파일> [출력파일]"
- echo "예시: video2mp3 video.mp4"
- echo "예시: video2mp3 video.mp4 audio.mp3"
+ echo "Usage: video2mp3 <input_file> [output_file]"
+ echo "Example: video2mp3 video.mp4"
+ echo "Example: video2mp3 video.mp4 audio.mp3"
exit 1
fi
INPUT="$1"
-# 파일 존재 확인
+# Check that the file exists
if [ ! -f "$INPUT" ]; then
- echo "오류: 파일을 찾을 수 없습니다: $INPUT"
+ echo "Error: file not found: $INPUT"
exit 1
fi
-# 출력 파일명 설정
+# Determine the output filename
if [ $# -eq 2 ]; then
OUTPUT="$2"
else
- # 입력 파일에서 확장자를 제거하고 .mp3 추가
+ # Strip the extension from the input file and append .mp3
OUTPUT="${INPUT%.*}.mp3"
fi
-echo "변환 중: $INPUT -> $OUTPUT"
+echo "Converting: $INPUT -> $OUTPUT"
-# ffmpeg로 mp3 추출 (고품질: 320kbps)
+# Extract mp3 with ffmpeg (high quality: 320kbps)
ffmpeg -i "$INPUT" -vn -acodec libmp3lame -b:a 320k "$OUTPUT"
if [ $? -eq 0 ]; then
- echo "✓ 완료: $OUTPUT"
+ echo "✓ Done: $OUTPUT"
else
- echo "✗ 오류 발생"
+ echo "✗ An error occurred"
exit 1
fi