#!/usr/bin/env bash # Installs ffx Zsh wrappers globally via ~/.ffx.zshrc.snippet. # Prompts for ffx.sh's directory, validates it, or tries to find it automatically. set -euo pipefail SNIPPET="$HOME/.ffx.zshrc.snippet" ZSHRC="$HOME/.zshrc" find_ffx() { local found # First check the current directory. if [[ -f "./ffx.sh" ]]; then printf '%s\n' "$(cd . && pwd)/ffx.sh" return 0 fi # Search common locations, excluding slow/system-wide paths. found="$( find "$HOME/Desktop" "$HOME/Downloads" "$HOME/Documents" "$HOME" \ -maxdepth 5 \ -type f \ -name 'ffx.sh' \ -print 2>/dev/null | head -n 1 || true )" [[ -n "$found" ]] || return 1 printf '%s\n' "$found" } echo "ffx.sh installer" echo read -r -p "Directory containing ffx.sh (Enter to auto-find): " FFX_DIR if [[ -n "$FFX_DIR" ]]; then FFX_DIR="${FFX_DIR/#\~/$HOME}" FFX_SCRIPT="$FFX_DIR/ffx.sh" else echo "Searching for ffx.sh..." FFX_SCRIPT="$(find_ffx || true)" if [[ -z "$FFX_SCRIPT" ]]; then echo "Could not automatically find ffx.sh." read -r -p "Enter the full path to ffx.sh: " FFX_SCRIPT FFX_SCRIPT="${FFX_SCRIPT/#\~/$HOME}" else echo "Found: $FFX_SCRIPT" fi fi if [[ -d "$FFX_SCRIPT" ]]; then FFX_SCRIPT="$FFX_SCRIPT/ffx.sh" fi if [[ ! -f "$FFX_SCRIPT" ]]; then echo "Error: ffx.sh was not found at:" echo " $FFX_SCRIPT" exit 1 fi if [[ ! -x "$FFX_SCRIPT" ]]; then echo "Making ffx.sh executable..." chmod +x "$FFX_SCRIPT" fi if [[ ! -x "$FFX_SCRIPT" ]]; then echo "Error: ffx.sh is not executable:" echo " $FFX_SCRIPT" exit 1 fi if ! "$FFX_SCRIPT" --version >/dev/null 2>&1; then echo "Error: ffx.sh exists but could not run successfully:" echo " $FFX_SCRIPT" echo echo "Try manually:" echo " \"$FFX_SCRIPT\" --version" exit 1 fi FFX_SCRIPT="$(cd "$(dirname "$FFX_SCRIPT")" && pwd)/ffx.sh" echo "Using ffx.sh:" echo " $FFX_SCRIPT" # Write / replace the separate Zsh snippet. cat > "$SNIPPET" < star333033.mp3 ffx_output_name() { local input="\$1" local dir base ext hash dir="\${input:h}" base="\${input:t}" if [[ "\$base" == *.* && "\$base" != .* ]]; then ext=".\${base##*.}" base="\${base%.*}" else ext="" fi hash="\$(printf '%06d' "\$(( (RANDOM << 1 ^ RANDOM) % 1000000 ))")" print -r -- "\${dir}/\${base}\${hash}\${ext}" } bass() { local input="\$1" percent="\$2" fine_db="\$3" local output="\${4:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" bass "\$input" "\$percent" "\$fine_db" "\$output" } treble() { local input="\$1" percent="\$2" fine_db="\$3" local output="\${4:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" treble "\$input" "\$percent" "\$fine_db" "\$output" } volume() { local input="\$1" db="\$2" local output="\${3:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" volume "\$input" "\$db" "\$output" } distort() { local input="\$1" drive="\${2:-2}" local output="\${3:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" distort "\$input" "\$drive" "\$output" } trim() { local input="\$1" start="\$2" end="\$3" local output="\${4:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" trim "\$input" "\$start" "\$end" "\$output" } tempo() { local input="\$1" speed="\$2" local output="\${3:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" tempo "\$input" "\$speed" "\$output" } pitch() { local input="\$1" semitones="\$2" local output="\${3:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" pitch "\$input" "\$semitones" "\$output" } bassboost() { local input="\$1" local output="\${2:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" bass "\$input" 5 1 "\$output" } grunge() { local input="\$1" local output="\${2:-\$(ffx_output_name "\$input")}" "\$FFX_SCRIPT" distort "\$input" 2 "\$output" } EOF touch "$ZSHRC" grep -qxF 'source "$HOME/.ffx.zshrc.snippet"' "$ZSHRC" || printf '\nsource "$HOME/.ffx.zshrc.snippet"\n' >> "$ZSHRC" if [[ -n "${ZSH_VERSION:-}" ]]; then source "$ZSHRC" fi echo echo "installed helper: $SNIPPET" echo "added lines to: $ZSHRC" echo echo "reload your current zsh session with:" echo " source ~/.zshrc" echo echo "examples:" echo " bassboost ~/Music/song.mp3" echo " grunge ~/Music/song.mp3" echo " tempo ~/Music/song.mp3 1.5"