@ Pohon BBS
PLAY NU MPV (2 replies)

■ 🕑 1. PLAY NU MPV
│  https://x0.at/30jh.png
│  #!/bin/bash
│  # ┏━┓╻ ┏━┓╻ ╻┏┓╻╻ ╻┏┳┓┏━┓╻ ╻ USAGE: playnumpv <days>
│  # ┣━┛┃ ┣━┫┗┳┛┃┗┫┃ ┃┃┃┃┣━┛┃┏┛ (where days = number of days to
│  # ╹ ┗━╸╹ ╹ ╹ ╹ ╹┗━┛╹ ╹╹ ┗┛ search back for newer media files)
│  
│  # Check if argument is provided
│  if [ -z "$1" ] || [[ ! "$1" =~ ^[0-9]+$ ]]; then
│   echo "Usage: $0 <days>"
│   exit 1
│  fi
│  
│  # Create a temporary playlist file in a safe location
│  playlist=$(mktemp) || { echo "Failed to create temporary file"; exit 1; }
│  
│  # Set trap to clean up temporary file on exit
│  trap 'rm -f "$playlist"' EXIT
│  
│  # Get absolute path of the playlist to exclude it from search
│  abs_playlist=$(realpath "$playlist")
│  
│  # Find all media files modified in the last $1 days and add them to the playlist
│  # Using absolute paths to avoid issues with relative paths
│  find "$PWD" -type f -regextype posix-extended -regex '.*\.(mp3|flac|opus|ogg|m4a|wav|nsf|mod|xm)' \
│   -mtime -"${1}" ! -path "$abs_playlist" -print0 | \
│   sort -z | \
│   tr '\0' '\n' > "$playlist"
│  
│  # Check if any files were found
│  if [ ! -s "$playlist" ]; then
│   echo "No files found newer than ${1} days."; exit 0
│  fi
│  
│  # Count the number of files in the playlist
│  file_count=$(wc -l < "$playlist")
│  echo "Found $file_count files to play."
│  
│  # Play playlist with mpv using unbuffer to maintain terminal connection
│  # and process substitution to capture output without breaking stdin
│  unbuffer -p mpv --shuffle --term-osd=auto --osd-level=2 --no-audio-display \
│   --playlist="$playlist" 2>&1 > >(grep -E "Playing") < /dev/tty
│  
│   
└─■ 🕑 2. explanation console stdin, stdout, redirection
    #!/bin/bash
    # ┏━┓╻ ┏━┓╻ ╻┏┓╻╻ ╻┏┳┓┏━┓╻ ╻ USAGE: playnumpv <days>
    # ┣━┛┃ ┣━┫┗┳┛┃┗┫┃ ┃┃┃┃┣━┛┃┏┛ (where days = number of days to
    # ╹ ┗━╸╹ ╹ ╹ ╹ ╹┗━┛╹ ╹╹ ┗┛ search back for newer media files)
    
    # Check if argument is provided
    if [ -z "$1" ] || [[ ! "$1" =~ ^[0-9]+$ ]]; then
     echo "Usage: $0 <days>"
     exit 1
    fi
    
    # Create a temporary playlist file in a safe location
    playlist=$(mktemp) || { echo "Failed to create temporary file"; exit 1; }
    
    # Set trap to clean up temporary file on exit
    trap 'rm -f "$playlist"' EXIT
    
    # Get absolute path of the playlist to exclude it from search
    abs_playlist=$(realpath "$playlist")
    
    # Find all media files modified in the last $1 days and add them to the playlist
    # Using absolute paths to avoid issues with relative paths
    find "$PWD" -type f -regextype posix-extended -regex '.*\.(mp3|flac|opus|ogg|m4a|wav|nsf|mod|xm)' \
     -mtime -"${1}" ! -path "$abs_playlist" -print0 | \
     sort -z | \
     tr '\0' '\n' > "$playlist"
    
    # Check if any files were found
    if [ ! -s "$playlist" ]; then
     echo "No files found newer than ${1} days."
     exit 0
    fi
    
    # Count the number of files in the playlist
    file_count=$(wc -l < "$playlist")
    echo "Found $file_count files to play."
    
    # Play the playlist with mpv, using unbuffer to maintain terminal connection
    # and process substitution to capture output without breaking stdin
    unbuffer -p mpv --shuffle --term-osd=auto --osd-level=2 --no-audio-display \
     --playlist="$playlist" 2>&1 > >(grep -E "Playing") < /dev/tty
    
    # Multi-line comment explaining the redirection technique:
    : <<'EOF'
    EXPLANATION OF THE REDIRECTION TECHNIQUE:
    
    The command uses several advanced shell features to maintain keyboard control while filtering output:
    
    1. `unbuffer -p`:
     - Creates a pseudo-terminal for mpv
     - Ensures mpv maintains interactive behavior including keyboard input handling
    
    2. `2>&1`:
     - Redirects stderr to stdout
     - Combines both output streams
    
    3. `> >(grep -E "Playing")`:
     - Uses process substitution (the `>(...)` syntax)
     - Creates a temporary file descriptor connected to grep
     - Sends mpv's output to grep without breaking terminal connection
     - Unlike a regular pipe, this doesn't disrupt keyboard input
    
    4. `< /dev/tty`:
     - Explicitly redirects stdin to the terminal device
     - Ensures mpv gets keyboard input directly from the terminal
     - This is critical for maintaining keyboard control
    
    WHY THIS WORKS WHEN REGULAR PIPES FAIL:
    
    Regular pipes (mpv | grep) break keyboard input because:
    - The shell puts commands in separate process groups
    - mpv detects its output is going to a pipe and may change behavior
    - Terminal control gets disrupted
    
    Our solution works because:
    - unbuffer maintains the terminal connection
    - Process substitution doesn't break the terminal connection like a pipe
    - Explicit terminal input redirection ensures keyboard control
    - The combination preserves mpv's interactive capabilities
    
    DATA FLOW:
    Keyboard Input → /dev/tty → mpv (via unbuffer) → Process Substitution → grep → Terminal
    EOF
    
     

Pohon BBS