Merge pull request 'feat(media): add play-media fzf picker for audio/video files' (#114) from feat/play-media-fzf-picker into main
This commit was merged in pull request #114.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
complete --command play-media --short p --long player --description "Force a specific media player" --require-parameter
|
||||
complete --command play-media --short h --long help --description "Print this help message"
|
||||
@@ -36,27 +36,27 @@ function _fish_deps_catalog
|
||||
set -g _fdc_bins \
|
||||
uv cargo fish starship fzf zoxide direnv paru yay \
|
||||
wakatime tailscale \
|
||||
eza lsd bat btop dust duf prettyping go ov rg lazygit lazydocker docker trash kitty wezterm python3 yt-dlp screen
|
||||
eza lsd bat btop dust duf prettyping go ov rg lazygit lazydocker docker trash kitty wezterm python3 yt-dlp screen mpv vlc
|
||||
|
||||
set -g _fdc_tiers \
|
||||
rec rec req rec req rec rec rec rec \
|
||||
int int \
|
||||
rec rec rec opt opt opt opt opt rec rec opt opt opt rec term term rec opt opt
|
||||
rec rec rec opt opt opt opt opt rec rec opt opt opt rec term term rec opt opt opt opt
|
||||
|
||||
set -g _fdc_cargo \
|
||||
"" "" "" starship "" zoxide "" "" "" \
|
||||
"" "" \
|
||||
eza lsd bat "" du-dust "" "" "" "" ripgrep "" "" "" trashy "" "" "" "" ""
|
||||
eza lsd bat "" du-dust "" "" "" "" ripgrep "" "" "" trashy "" "" "" "" "" "" ""
|
||||
|
||||
set -g _fdc_pm \
|
||||
uv cargo fish starship fzf zoxide direnv "" yay \
|
||||
wakatime tailscale \
|
||||
eza lsd bat btop dust duf prettyping go ov ripgrep lazygit lazydocker docker trash kitty wezterm python yt-dlp screen
|
||||
eza lsd bat btop dust duf prettyping go ov ripgrep lazygit lazydocker docker trash kitty wezterm python yt-dlp screen mpv vlc
|
||||
|
||||
set -g _fdc_special \
|
||||
curl-uv rustup-installer git-cargo-fish curl-installer fzf-update "" "" paru-build yay-build \
|
||||
wakatime-binary "" \
|
||||
"" "" "" "" "" "" "" "" go-ov "" "" curl-lazydocker "" "" "" "" "" "" ""
|
||||
"" "" "" "" "" "" "" "" go-ov "" "" curl-lazydocker "" "" "" "" "" "" "" "" ""
|
||||
end
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# _fzf_preview_media <file_path>
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Preview helper for play-media. Looks for a thumbnail already generated
|
||||
# by a desktop file manager (Dolphin, Nautilus, GNOME Videos, ...) in the
|
||||
# freedesktop thumbnail cache and renders it via _fzf_preview_image if
|
||||
# found. Otherwise falls back to ffprobe-formatted metadata (duration,
|
||||
# codec, resolution, tags) when ffprobe is installed, or plain `file`
|
||||
# output as a last resort. Neither the thumbnail cache lookup nor ffprobe
|
||||
# are tracked in fish-deps: both are best-effort, matching how the
|
||||
# image-preview tool chain (kitten/chafa/viu/timg) is already handled.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# file_path Path to the audio/video file to preview
|
||||
#
|
||||
# EXIT STATUS
|
||||
# 0 Always
|
||||
#
|
||||
# EXAMPLE
|
||||
# _fzf_preview_media ./Videos/clip.mp4
|
||||
function _fzf_preview_media
|
||||
set -f file_path $argv
|
||||
if not test -e "$file_path"
|
||||
echo "$file_path doesn't exist." >&2
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l abs_path (realpath -- "$file_path" 2>/dev/null)
|
||||
|
||||
# freedesktop.org thumbnail spec: md5 of the file:// URI names the
|
||||
# cached thumbnail. Dolphin/Nautilus/GNOME Videos already populate this
|
||||
# cache, so reuse it instead of generating a new thumbnail ourselves.
|
||||
set -l uri "file://"(string escape --style=url -- "$abs_path")
|
||||
set -l hash (echo -n "$uri" | md5sum | string split ' ')[1]
|
||||
set -l cache_home (set --query XDG_CACHE_HOME; and echo $XDG_CACHE_HOME; or echo "$HOME/.cache")
|
||||
|
||||
for size in normal large x-large xx-large
|
||||
set -l thumb "$cache_home/thumbnails/$size/$hash.png"
|
||||
if test -f "$thumb"
|
||||
_fzf_preview_image "$thumb"
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
if command -q ffprobe
|
||||
set -l info (command ffprobe -v error -show_entries \
|
||||
format=duration,bit_rate:format_tags=title,artist,album:stream=codec_name,codec_type,width,height \
|
||||
-of default=noprint_wrappers=1 -- "$abs_path" 2>/dev/null)
|
||||
if test -n "$info"
|
||||
printf '%s\n' $info
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
command file --brief -- "$abs_path"
|
||||
end
|
||||
@@ -0,0 +1,127 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CATEGORY
|
||||
# 13-media-and-utilities
|
||||
#
|
||||
# SYNOPSIS
|
||||
# play-media [-p|--player <cmd>]
|
||||
# play-media --help
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Opens an fzf picker (with thumbnail/metadata preview via
|
||||
# _fzf_preview_media) listing audio and video files under the current
|
||||
# directory, and plays the selection(s) in the best available media
|
||||
# player. Supports multi-select (Tab) to queue several files at once.
|
||||
#
|
||||
# Player resolution order:
|
||||
# 1. -p/--player <cmd> (explicit override, validated as a command)
|
||||
# 2. $play_media_player (explicit override, validated as a command)
|
||||
# 3. xdg-mime default handler for the first selected file's mimetype
|
||||
# 4. First known player binary found in a built-in list (mpv, vlc)
|
||||
#
|
||||
# The player is launched backgrounded and detached, mirroring open-url,
|
||||
# so the shell is never blocked.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# -p, --player <cmd> Force a specific player command
|
||||
# -h, --help Print usage and exit
|
||||
#
|
||||
# EXIT STATUS
|
||||
# 0 Player launched (or the picker was cancelled)
|
||||
# 1 No media files found, invalid --player/$play_media_player, or no
|
||||
# player found
|
||||
#
|
||||
# EXAMPLE
|
||||
# play-media
|
||||
# play-media --player mpv
|
||||
function play-media --description 'Pick audio/video files with fzf and play them'
|
||||
argparse h/help p/player= -- $argv
|
||||
or return 1
|
||||
|
||||
if set -q _flag_help
|
||||
echo "Usage: play-media [-p|--player <cmd>]"
|
||||
echo "Pick audio/video files under the current directory with fzf and play them."
|
||||
echo
|
||||
echo " -p, --player <cmd> Force a specific player command"
|
||||
echo " -h, --help Show this help"
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l audio_exts mp3 flac wav ogg oga opus m4a aac wma alac aiff
|
||||
set -l video_exts mp4 mkv webm avi mov wmv flv m4v mpg mpeg ts
|
||||
|
||||
# Directly use fd binary to avoid output buffering delay caused by a fd
|
||||
# alias, if any. Debian-based distros install fd as fdfind.
|
||||
set -f fd_cmd (command -v fdfind || command -v fd || echo "fd")
|
||||
set -f --append fd_cmd --color=always $fzf_fd_opts
|
||||
for ext in $audio_exts $video_exts
|
||||
set -f --append fd_cmd -e $ext
|
||||
end
|
||||
|
||||
set -l selection ($fd_cmd 2>/dev/null | _fzf_wrapper --ansi --multi \
|
||||
--height=90% \
|
||||
--layout=reverse \
|
||||
--border=rounded \
|
||||
--border-label=' Play Media ' \
|
||||
--prompt='Play> ' \
|
||||
--header='Enter: Play Tab: Select Ctrl-/: Toggle Preview Esc: Cancel' \
|
||||
--bind='ctrl-/:toggle-preview' \
|
||||
--preview='_fzf_preview_media {}' \
|
||||
--preview-window='right:50%:wrap:border-left')
|
||||
|
||||
if test -z "$selection"
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l player
|
||||
if set -q _flag_player
|
||||
set player $_flag_player
|
||||
if not type -q $player[1]
|
||||
set_color red
|
||||
echo "error: --player '$player[1]' is not a valid command" >&2
|
||||
set_color normal
|
||||
return 1
|
||||
end
|
||||
else if set -q play_media_player
|
||||
echo $play_media_player | read -at player
|
||||
if not type -q $player[1]
|
||||
set_color red
|
||||
echo "error: \$play_media_player '$player[1]' is not a valid command" >&2
|
||||
set_color normal
|
||||
return 1
|
||||
end
|
||||
else
|
||||
if type -q xdg-mime; and command -q file
|
||||
set -l mime (command file --brief --mime-type -- "$selection[1]" 2>/dev/null)
|
||||
set -l desk (xdg-mime query default "$mime" 2>/dev/null)
|
||||
if test -n "$desk"
|
||||
set -l candidate (string replace -r '\.desktop$' '' -- $desk)
|
||||
if type -q $candidate
|
||||
set player $candidate
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not set -q player[1]
|
||||
for p in mpv vlc
|
||||
if type -q -f $p
|
||||
set player $p
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not set -q player[1]
|
||||
set_color red
|
||||
echo "error: could not find a media player — set \$play_media_player, pass --player, or install mpv/vlc" >&2
|
||||
set_color normal
|
||||
return 1
|
||||
end
|
||||
|
||||
# Background the player so it doesn't block the terminal, and discard
|
||||
# its own console chatter, mirroring open-url.
|
||||
sh -c '("$@") >/dev/null 2>&1 &' -- $player $selection
|
||||
return 0
|
||||
end
|
||||
Reference in New Issue
Block a user