diff --git a/README.md b/README.md index 10d77cf..616e219 100755 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Welcome to the .local-bin repository! Find key components below to enhance your - **[docker_check](scripts/docker_check):** This script automates the process of ensuring Docker is installed and running before executing Docker-related commands. If Docker is not installed, it provides an option to install it via Homebrew. - **[add_yaml_header](scripts/add_yaml_header):** This script ensures that YAML files within a specified directory contain the necessary `---` header. If a YAML file does not have the `---` header, the script adds it. - **[wzp](scripts/wzp):** This script automates the process of starting a new Wezterm project. It allows you to select a project from a predefined list or specify a project name as an argument. +- **[volumizer](scripts/volumizer):** This script manages volume levels on macOS and Linux systems. It limits the volume to a specified maximum when headphones are connected, protecting users' hearing. It integrates notifications to alert users of volume changes and headphone status seamlessly. ## Documentation diff --git a/docs/volumizer/Usage.md b/docs/volumizer/Usage.md new file mode 100644 index 0000000..e69de29 diff --git a/scripts/add_yaml_header b/scripts/add_yaml_header index 15423fd..6b507a6 100755 --- a/scripts/add_yaml_header +++ b/scripts/add_yaml_header @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Function to add '---' to YAML files if not present add_yaml_header() { diff --git a/scripts/docker_check b/scripts/docker_check index 89f3211..1a4e870 100755 --- a/scripts/docker_check +++ b/scripts/docker_check @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Function to start Docker if not running start_docker() { diff --git a/scripts/fzf_theme b/scripts/fzf_theme index cbd9543..7098d1f 100755 --- a/scripts/fzf_theme +++ b/scripts/fzf_theme @@ -1,32 +1,32 @@ -#!/usr/bin/env bash - set_fzf_theme() { + local appearance="$1" + # Detect the current system appearance (Light or Dark mode) for Linux and macOS - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS - APPEARANCE=$(defaults read -g AppleInterfaceStyle 2>/dev/null) - elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - # Linux - APPEARANCE=$(gsettings get org.gnome.desktop.interface gtk-theme 2>/dev/null) - else - # Default to Light mode if the system is not recognized - APPEARANCE="Dark" + if [[ -z "$appearance" ]]; then + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + appearance=$(defaults read -g AppleInterfaceStyle 2>/dev/null) + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + # Linux (assuming GNOME) + appearance=$(gsettings get org.gnome.desktop.interface gtk-theme 2>/dev/null) + else + # Default to Dark mode if the system is not recognized + appearance="Dark" + fi fi - # Set fzf theme based on system appearance - if [[ $APPEARANCE == *"Dark"* || -n "$TMUX" ]]; then - FZF_THEME="--color=bg+:#1e1e1e,bg:#1e1e1e,spinner:#d33682,hl:#b58900,fg:#ffffff,header:#d33682,info:#268bd2,pointer:#859900,marker:#859900,fg+:#ffffff,prompt:#268bd2,hl+:#b58900" + # Set fzf theme based on appearance + if [[ $appearance == *"Dark"* || -n "$TMUX" ]]; then + FZF_DEFAULT_OPTS="--color=bg+:#1e1e1e,bg:#1e1e1e,spinner:#d33682,hl:#b58900,fg:#ffffff,header:#d33682,info:#268bd2,pointer:#859900,marker:#859900,fg+:#ffffff,prompt:#268bd2,hl+:#b58900" else - # FZF_THEME="--color=bg+:#fdf6e3,bg:#fdf6e3,spinner:#d33682,hl:#b58900,fg:#657b83,header:#d33682,info:#268bd2,pointer:#859900,marker:#859900,fg+:#657b83,prompt:#268bd2,hl+:#b58900" - - FZF_THEME="--color=bg+:#fdf6e3,bg:#fdf6e3,spinner:#d33682,hl:#b58900,fg:#657b83,header:#d33682,info:#268bd2,pointer:#859900,marker:#859900,fg+:#657b83,prompt:#268bd2,hl+:#b58900" + FZF_DEFAULT_OPTS="--color=bg+:#fdf6e3,bg:#fdf6e3,spinner:#d33682,hl:#b58900,fg:#657b83,header:#d33682,info:#268bd2,pointer:#859900,marker:#859900,fg+:#657b83,prompt:#268bd2,hl+:#b58900" fi - echo "$FZF_THEME" + # export FZF_DEFAULT_OPTS + + echo "$FZF_DEFAULT_OPTS" } -# If sourced directly, set FZF_THEME -if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - set_fzf_theme -fi +# Call the function to set FZF_DEFAULT_OPTS +set_fzf_theme "$1" diff --git a/scripts/setup_dev_env b/scripts/setup_dev_env index 63f638f..78fd0bb 100755 --- a/scripts/setup_dev_env +++ b/scripts/setup_dev_env @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Function to check if a command is available command_exists() { diff --git a/scripts/update_brew_lists b/scripts/update_brew_lists index 75b347a..5f445ce 100755 --- a/scripts/update_brew_lists +++ b/scripts/update_brew_lists @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash BREW_PREFIX="/usr/local/bin/" BREW_LIST_DIR="$HOME/.local/bin/.brew_lists" @@ -111,3 +111,4 @@ if are_lists_different "$NEW_BREW_LIST" "$BREW_LIST" || are_lists_different "$NE # Commit changes to Git commit_to_git fi + diff --git a/scripts/volumizer b/scripts/volumizer new file mode 100755 index 0000000..c4d0f0f --- /dev/null +++ b/scripts/volumizer @@ -0,0 +1,170 @@ +#!/usr/bin/env bash + +APP_NAME="Volumizer" +MAX_VOLUME=50 +ONLY_ON_HEADPHONES=false +NOTIFICATION_TITLE="Volume Limiter" +HEADPHONES_CONNECTED=false +DELAY=3 + +# Function to get the current volume on macOS +get_current_volume_macos() { + osascript -e "output volume of (get volume settings)" +} + +# Function to set the volume on macOS +set_volume_macos() { + osascript -e "set volume output volume $1" +} + +# Function to display notification on macOS if not already displayed +display_notification_macos() { + local title="$1" + local subtitle="$2" + local notification_file="/tmp/volume_notification" + + if [[ -f "$notification_file" ]]; then + local last_notification + last_notification=$(cat "$notification_file") + if [[ "$last_notification" == "$subtitle" ]]; then + return 0 # Notification already displayed + fi + fi + + osascript -e "display notification \"$subtitle\" with title \"$title\"" + echo "$subtitle" > "$notification_file" +} + +# Function to check if output is on internal speakers on macOS +on_speaker_macos() { + local output_source + output_source=$(/usr/sbin/system_profiler SPAudioDataType | awk '/Output Source/ {print $NF}') + + # Check if 'Default' is found in the output source + if echo "$output_source" | grep -q 'Default'; then + return 1 + else + return 0 + fi +} + +# Function to get the current volume on Linux +get_current_volume_linux() { + amixer get Master | grep -oP '\d+%' | head -1 | tr -d '%' +} + +# Function to set the volume on Linux +set_volume_linux() { + amixer set Master "$1%" +} + +# Function to display notification on Linux if not already displayed +display_notification_linux() { + local title="$1" + local subtitle="$2" + local notification_file="/tmp/volume_notification" + + if [[ -f "$notification_file" ]]; then + local last_notification + last_notification=$(cat "$notification_file") + if [[ "$last_notification" == "$subtitle" ]]; then + return 0 # Notification already displayed + fi + fi + + notify-send "$title" "$subtitle" + echo "$subtitle" > "$notification_file" +} + +# Function to check if output is on internal speakers on Linux +on_speaker_linux() { + pacmd list-sinks | grep -q 'active port.*analog-output-speaker' +} + +# Function to check if headphones are connected +check_headphones() { + if [ "$ONLY_ON_HEADPHONES" = true ]; then + if $on_speaker; then + if [ "$HEADPHONES_CONNECTED" = true ]; then + HEADPHONES_CONNECTED=false + $display_notification "$NOTIFICATION_TITLE" "Volume limiter is stopped, be careful" + fi + else + if [ "$HEADPHONES_CONNECTED" = false ]; then + HEADPHONES_CONNECTED=true + $limit_volume + $display_notification "$NOTIFICATION_TITLE" "Limiting your 🎧 headphones to $MAX_VOLUME% to protect your ears" + fi + fi + fi +} + +# Function to limit volume +limit_volume() { + local current_volume + current_volume=$($get_current_volume) + if [ "$ONLY_ON_HEADPHONES" = true ]; then + if [ "$HEADPHONES_CONNECTED" = true ] && [ "$current_volume" -gt "$MAX_VOLUME" ]; then + $set_volume "$MAX_VOLUME" + fi + else + if [ "$current_volume" -gt "$MAX_VOLUME" ]; then + $set_volume "$MAX_VOLUME" + fi + fi +} + +# Main logic +if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + get_current_volume="get_current_volume_macos" + set_volume="set_volume_macos" + display_notification="display_notification_macos" + on_speaker="on_speaker_macos" +else + # Linux + get_current_volume="get_current_volume_linux" + set_volume="set_volume_linux" + display_notification="display_notification_linux" + on_speaker="on_speaker_linux" +fi + +# Parse command-line arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --headphones-only) + ONLY_ON_HEADPHONES=true + shift + ;; + --max-volume) + if [[ "$2" =~ ^[0-9]+$ && "$2" -ge 0 && "$2" -le 100 ]]; then + MAX_VOLUME="$2" + shift 2 + else + echo "Error: --max-volume must be followed by a valid percentage (0-100)." + exit 1 + fi + ;; + --delay) + if [[ "$2" =~ ^[0-9]+$ && "$2" -gt 0 ]]; then + DELAY="$2" + shift 2 + else + echo "Error: --delay must be followed by a valid positive integer." + exit 1 + fi + ;; + *) + echo "Usage: $0 [--headphones-only] [--max-volume ] [--delay ] [--macos | --linux]" + exit 1 + ;; + esac +done + +for (( i=1; i<=$((60/DELAY)); i++ )); do + check_headphones + limit_volume + + sleep $DELAY +done +