Skip to content

Instantly share code, notes, and snippets.

@dethell
Last active May 2, 2025 16:12
Show Gist options
  • Save dethell/993f513e96c085c047a2c11aca6c6511 to your computer and use it in GitHub Desktop.
Save dethell/993f513e96c085c047a2c11aca6c6511 to your computer and use it in GitHub Desktop.
AI-generated command line audio player for macos
#!/bin/bash
# Array of songs to play in order
songs=()
# Function to display instructions
display_instructions() {
echo "==============================================="
echo " MUSIC PLAYER CONTROLS "
echo "==============================================="
echo " p - Pause/Resume current song"
echo " n - Skip to next song"
echo " q - Quit the player"
echo "==============================================="
}
# Initialize variables
current_index=0
is_paused=false
player_pid=""
should_exit=false
# Function to get all songs in the current directory by listing all mp3 files
# and storing them in the songs array
get_songs() {
songs=()
for song in *.mp3; do
if [ -f "$song" ]; then
songs+=("$song")
fi
done
}
# Function to play a song
play_song() {
local song_index=$1
if [ $song_index -ge ${#songs[@]} ]; then
echo "End of playlist reached."
should_exit=true
return
fi
current_song="${songs[$song_index]}"
echo "Now playing: $current_song"
# Play the song in the background and capture its PID
afplay "$current_song" &
player_pid=$!
}
# Function to handle pause/resume
toggle_pause() {
if $is_paused; then
echo "Resuming playback..."
kill -CONT $player_pid
is_paused=false
else
echo "Pausing playback..."
kill -STOP $player_pid
is_paused=true
fi
}
# Function to skip to the next song
skip_song() {
echo "Skipping to next song..."
if [ -n "$player_pid" ]; then
kill $player_pid 2>/dev/null
wait $player_pid 2>/dev/null
fi
current_index=$((current_index + 1))
play_song $current_index
}
# Main function to control the player
run_player() {
clear
display_instructions
get_songs
if [ ${#songs[@]} -eq 0 ]; then
echo "No songs found in the current directory."
exit 1
fi
play_song $current_index
# Enable reading a single character without pressing Enter
stty -echo -icanon min 1
while ! $should_exit; do
# Check if the current song has finished
if [ -n "$player_pid" ] && ! kill -0 $player_pid 2>/dev/null; then
# Song has finished, move to the next one
current_index=$((current_index + 1))
if [ $current_index -ge ${#songs[@]} ]; then
echo "End of playlist reached."
should_exit=true
else
play_song $current_index
fi
fi
# Check for user input (non-blocking)
if read -t 1 -n 1 key; then
case $key in
p)
toggle_pause
;;
n)
skip_song
;;
q)
echo "Exiting player..."
if [ -n "$player_pid" ]; then
kill $player_pid 2>/dev/null
fi
should_exit=true
;;
esac
fi
done
# Restore terminal settings
stty sane
}
# Start the player
run_player
echo "Music player closed."
@dethell
Copy link
Author

dethell commented May 2, 2025

Was wanting a low-impact way to play files from the command line without needing an app. macos comes with afplay installed, but I didn't realize it responded to the kill -STOP and kill -CONT options until the AI bot generated this script. The only error the AI made in the script was the -t argument to the bash read command. It attempted a fractional timeout of -t 0.1 so I had to update it to -t 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment