initial commit

This commit is contained in:
teraflops 2025-05-29 18:51:00 +02:00
commit 503856e135
Signed by: teraflops
GPG Key ID: 2B77D97AF6F8968C
8 changed files with 1110 additions and 0 deletions

18
LICENSE Normal file
View File

@ -0,0 +1,18 @@
MIT No Attribution
Copyright 2024 teraflops
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

60
README.md Normal file
View File

@ -0,0 +1,60 @@
# mympc
## Wrapper around the [mpc](https://musicpd.org/clients/mpc/) command line client for controlling a [Music Player Daemon](https://musicpd.org/) server.
It does zsh completion for the mpc command and provides a few functions to make it easier to use mpc.
### Installation.
copy the files in the same path as they are in the repo. Add the following to your .zshrc file:
```zsh
autoload -Uz compinit
compinit
```
```bash
Usage: /usr/local/bin/mympc [options] [arguments]
Options:
--artist [name] Search for songs by artist (comma-separated)
--genre [name] Search for songs by genre
--album [name] Search for songs by album
--track [name] Search for songs by track name (comma-separated)
--year [year] Search for songs by release year (e.g., --year=1990)
--duration [min:sec] Search for songs by duration (e.g., --duration=3:30)
-n, --number [number] Specify the number of songs to add to the playlist (default: 15)
--play Play directly after adding songs to the playlist
--preview Preview the songs that will be added to the playlist without adding them
--save-playlist [name] Save the current playlist with the given name
--remove [track1,track2,...] Remove one or more songs from the playlist, separated by commas
--list-artists List all available artists
--list-genres List all available genres
--list-albums List all available albums
--random Activate random mode
--repeat Activate repeat mode
--get-rating Get the rating of the current song
--rate [0-5] Set the rating of the current song (0-5)
--toprated Generate a playlist of top-rated songs (rating=5)
--add-tag [key=value] Add a custom tag to the current song
--delete-tag [key] Delete a custom tag from the current song
--list-tags List all tags of the current song
--update-tag [key=value] Update a custom tag of the current song
--playlist-by-mood [mood] Generate a playlist based on the specified mood
--playlist-by-mood=[mood] Same as above, using '=' syntax
--help, -h Show this help message
Examples:
/usr/local/bin/mympc --artist="Pink Floyd,AC/DC" --play -n 10
/usr/local/bin/mympc --album="The Dark Side of the Moon" --play
/usr/local/bin/mympc --genre="Blues" --year=1980 --play -n 5
/usr/local/bin/mympc --track="Comfortably Numb,Money" --play
/usr/local/bin/mympc --artist="Pink Floyd" --track="Money,Time" --play
/usr/local/bin/mympc --get-rating
/usr/local/bin/mympc --rate 4
/usr/local/bin/mympc --toprated --play
/usr/local/bin/mympc --add-tag "mood=happy"
/usr/local/bin/mympc --delete-tag "mood"
/usr/local/bin/mympc --list-tags
/usr/local/bin/mympc --update-tag "mood=energetic"
/usr/local/bin/mympc --playlist-by-mood=happy --play
```

635
usr/local/bin/mympc Executable file
View File

@ -0,0 +1,635 @@
#!/bin/bash
# mympc: A script to interact with mpc in an efficient and flexible way.
# ========================
# Initial Setup
# ========================
# Source centralized tag definitions
# Ensure that /usr/local/share/mympc/tags.sh exists and is properly configured
if [[ -f /usr/local/share/mympc/tags.sh ]]; then
source /usr/local/share/mympc/tags.sh
else
echo "Error: /usr/local/share/mympc/tags.sh not found. Please create it with necessary tag definitions."
exit 1
fi
# Function to display help message
show_help() {
cat << EOF
Usage: $0 [options] [arguments]
Options:
--artist [name] Search for songs by artist
--genre [name] Search for songs by genre
--album [name] Search for songs by album
--track [name] Search for songs by track name
--year [year] Search for songs by release year (e.g., --year=1990)
--duration [min:sec] Search for songs by duration (e.g., --duration=3:30)
-n, --number [number] Specify the number of songs to add to the playlist (default: 15)
--play Play directly after adding songs to the playlist
--preview Preview the songs that will be added to the playlist without adding them
--save-playlist [name] Save the current playlist with the given name
--remove [track1,track2,...] Remove one or more songs from the playlist, separated by commas
--list-artists List all available artists
--list-genres List all available genres
--list-albums List all available albums
--random Activate random mode
--repeat Activate repeat mode
--get-rating Get the rating of the current song
--rate [0-5] Set the rating of the current song (0-5)
--toprated Generate a playlist of top-rated songs (rating=5)
--add-tag [key=value] Add a custom tag to the current song
--delete-tag [key] Delete a custom tag from the current song
--list-tags List all tags of the current song
--update-tag [key=value] Update a custom tag of the current song
--playlist-by-mood [mood] Generate a playlist based on the specified mood
--help, -h Show this help message
Examples:
$0 --artist="Pink Floyd,AC/DC" --play -n 10
$0 --album="The Dark Side of the Moon" --play
$0 --genre="Blues" --year=1980 --play -n 5
$0 --track="Comfortably Numb,Money" --play
$0 --artist="Pink Floyd" --track="Money,Time" --play
$0 --get-rating
$0 --rate 4
$0 --toprated --play
$0 --add-tag "mood=happy"
$0 --delete-tag "mood"
$0 --list-tags
$0 --update-tag "mood=energetic"
$0 --playlist-by-mood=happy --play
EOF
}
# Function to get the URI of the current song
get_current_song_uri() {
mpc --format %file% current
}
# Function to check if a tag exists on a song
tag_exists() {
local song="$1"
local key="$2"
mpc sticker "$song" list 2>/dev/null | cut -d'=' -f1 | grep -qw "$key"
}
# Function to check if a value is in an array
is_in_array() {
local element
for element in "${@:2}"; do
[[ "$element" == "$1" ]] && return 0
done
return 1
}
delete_song_from_playlist() {
local position="$1"
# Validate that position is a positive integer
if ! [[ "$position" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: Position must be a positive integer."
exit 1
fi
# Delete the song at the specified position
if mpc del "$position"; then
echo "Song at position $position deleted from the playlist."
else
echo "Error: Failed to delete song at position $position."
exit 1
fi
}
# ========================
# Initialize Variables
# ========================
number_of_songs=15
play_now=false
preview=false
declare -A search_params
artists=()
genres=()
albums=()
tracks=()
years=()
durations=()
remove_songs=()
playlist_name=""
get_rating=false
set_rating_value=""
toprated=false
# Tag-related variables
add_tag=""
delete_tag=""
list_tags=false
update_tag=""
# Playlist by mood variables
mood_value=""
playlist_name_override=""
# ========================
# Option Parsing with getopt
# ========================
# Define the options
TEMP=$(getopt -o n:h --long artist:,genre:,album:,track:,year:,duration:,number:,play,preview,save-playlist:,remove:,list-artists,list-genres,list-albums,random,repeat,get-rating,rate:,toprated,add-tag:,delete-tag:,list-tags,update-tag:,playlist-by-mood:,playlist-by-mood,help -n "$0" -- "$@")
# Check if getopt succeeded
if [ $? != 0 ] ; then show_help; exit 1 ; fi
# Reorder the arguments
eval set -- "$TEMP"
# Parse the options
while true; do
case "$1" in
--artist)
if [[ -n "${search_params[genre]}" || -n "${search_params[artist]}" ]]; then
echo "Error: --artist cannot be used with --genre or multiple times."
exit 1
fi
shift
# Usar eval para manejar correctamente las comillas y espacios
artist_names=$(eval echo "$1")
IFS=',' read -ra ARTISTS_ARRAY <<< "$artist_names"
for artist in "${ARTISTS_ARRAY[@]}"; do
artist=$(echo "$artist" | xargs)
if [[ "$artist" =~ [^a-zA-Z0-9\ \.\,\&\'\-\/] ]]; then
echo "Error: Artist names can only contain letters, numbers, spaces, and characters like .,&,',-,/."
exit 1
fi
artists+=("$artist")
done
search_params[artist]=1
shift
;;
--genre)
if [[ -n "${search_params[artist]}" || -n "${search_params[album]}" || -n "${search_params[genre]}" ]]; then
echo "Error: --genre cannot be used with --artist, --album, or multiple times."
exit 1
fi
shift
genres+=("$1")
search_params[genre]=1
shift
;;
--album)
if [[ -n "${search_params[genre]}" || -n "${search_params[album]}" || -n "${search_params[number]}" ]]; then
echo "Error: --album cannot be used with --genre, --number, or multiple times."
exit 1
fi
shift
# Usar un enfoque más robusto para manejar comillas y apóstrofes
album_name="$1"
# Escapar solo lo necesario para mpc sin usar eval
albums+=("$album_name")
search_params[album]=1
shift
;;
--track)
if [[ -n "${search_params[track]}" ]]; then
echo "Error: --track cannot be used multiple times."
exit 1
fi
shift
track_names="$1"
IFS=',' read -ra TRACKS_ARRAY <<< "$track_names"
for track in "${TRACKS_ARRAY[@]}"; do
track=$(echo "$track" | xargs)
if [[ "$track" =~ [^a-zA-Z0-9\ \.\,\&\'\-\/] ]]; then
echo "Error: Track names can only contain letters, numbers, spaces, and characters like .,&,',-,/."
exit 1
fi
tracks+=("$track")
done
search_params[track]=1
shift
;;
--year)
if [[ -n "${search_params[year]}" ]]; then
echo "Error: --year cannot be used multiple times."
exit 1
fi
shift
if ! [[ "$1" =~ ^(19|20)[0-9]{2}$ ]]; then
echo "Error: --year must be a valid year (e.g., 1990)."
exit 1
fi
years+=("$1")
search_params[year]=1
shift
;;
--duration)
if [[ -n "${search_params[duration]}" ]]; then
echo "Error: --duration cannot be used multiple times."
exit 1
fi
shift
if ! [[ "$1" =~ ^([0-9]+):([0-5][0-9])$ ]]; then
echo "Error: --duration must be in the format min:sec (e.g., 3:30)."
exit 1
fi
durations+=("$1")
search_params[duration]=1
shift
;;
-n|--number)
if [[ -n "${search_params[album]}" || "$toprated" = true || -n "${search_params[number]}" ]]; then
echo "Error: --number cannot be used with --album, --toprated, or multiple times."
exit 1
fi
shift
number_of_songs="$1"
if ! [[ "$number_of_songs" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: --number must be a positive integer."
exit 1
fi
search_params[number]=1
shift
;;
--play)
play_now=true
shift
;;
--preview)
preview=true
shift
;;
--save-playlist)
shift
playlist_name_override="$1"
shift
;;
--remove)
shift
delete_song="$1"
shift
# Parse the position from "position: song name"
if [[ "$delete_song" =~ ^([0-9]+):\ (.+)$ ]]; then
delete_position="${BASH_REMATCH[1]}"
delete_song_name="${BASH_REMATCH[2]}"
else
echo "Error: Invalid format for --remove. Expected 'position: song name'."
exit 1
fi
# Call the function to delete the song from the playlist
delete_song_from_playlist "$delete_position"
exit 0
;;
--list-artists)
mpc list artist
exit 0
;;
--list-genres)
mpc list genre
exit 0
;;
--list-albums)
mpc list album
exit 0
;;
--random)
mpc random on
echo "Random mode activated."
exit 0
;;
--repeat)
mpc repeat on
echo "Repeat mode activated."
exit 0
;;
--get-rating)
get_rating=true
shift
;;
--rate)
if [[ -n "$set_rating_value" ]]; then
echo "Error: --rate cannot be used multiple times."
exit 1
fi
shift
set_rating_value="$1"
if ! [[ "$set_rating_value" =~ ^[0-5]$ ]]; then
echo "Error: Rating must be between 0 and 5."
exit 1
fi
shift
;;
--toprated)
if [[ -n "${search_params[number]}" || "$toprated" = true ]]; then
echo "Error: --toprated cannot be used with --number or multiple times."
exit 1
fi
toprated=true
shift
;;
--add-tag)
shift
add_tag="$1"
# Validate the format key=value
if ! [[ "$add_tag" =~ ^[^=]+=[^=]+$ ]]; then
echo "Error: --add-tag must be in the format key=value."
exit 1
fi
shift
;;
--delete-tag)
shift
delete_tag="$1"
shift
;;
--playlist-by-mood=*)
mood_value="${key#*=}"
# Invoke the Python script to handle playlist generation
/usr/local/share/mympc/add_mood_tag.py "$mood_value"
shift # past argument
;;
--playlist-by-mood)
mood_value="$2"
# Invoke the Python script to handle playlist generation
/usr/local/share/mympc/add_mood_tag.py "$mood_value"
shift # past argument
exit 0
;;
--list-tags)
# Handle --list-tags
list_tags=true
shift
;;
--update-tag)
shift
update_tag="$1"
# Validate the format key=value
if ! [[ "$update_tag" =~ ^[^=]+=[^=]+$ ]]; then
echo "Error: --update-tag must be in the format key=value."
exit 1
fi
shift
;;
--help|-h)
show_help
exit 0
;;
--)
shift
break
;;
*)
echo "Invalid option: $1"
echo "Use --help to see available options."
exit 1
;;
esac
done
# ========================
# Execute Tag Actions
# ========================
# Verify if mpc supports the sticker command
if ! mpc help | grep -q 'sticker'; then
echo "Error: Your mpc version does not support the sticker command."
exit 1
fi
# List all tags of the current song
if [ "$list_tags" = true ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "No song is currently playing."
exit 1
fi
tags=$(mpc sticker "$song_uri" list 2>/dev/null)
if [ -z "$tags" ]; then
echo "No tags found for the current song."
else
echo "Tags for '$song_uri':"
echo "$tags"
fi
exit 0
fi
# Add a custom tag to the current song
if [ -n "$add_tag" ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "Error: No song is currently playing."
exit 1
fi
key="${add_tag%%=*}"
value="${add_tag#*=}"
# Validate the key and value
if [[ "$key" == "mood" ]]; then
if ! is_in_array "$value" "${allowed_moods[@]}"; then
echo "Error: Invalid mood value '$value'. Allowed values are: ${allowed_moods[*]}"
exit 1
fi
elif [[ " ${allowed_custom_tags[*]} " != *" $key "* ]]; then
echo "Error: Invalid tag key '$key'. Allowed keys are: ${allowed_custom_tags[*]}"
exit 1
fi
mpc sticker "$song_uri" set "$key" "$value"
echo "Tag '$key=$value' added to '$song_uri'."
exit 0
fi
# Delete a custom tag from the current song
if [ -n "$delete_tag" ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "Error: No song is currently playing."
exit 1
fi
if tag_exists "$song_uri" "$delete_tag"; then
mpc sticker "$song_uri" delete "$delete_tag"
echo "Tag '$delete_tag' deleted from '$song_uri'."
else
echo "Error: Tag '$delete_tag' does not exist on '$song_uri'."
exit 1
fi
exit 0
fi
# Update a custom tag of the current song
if [ -n "$update_tag" ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "Error: No song is currently playing."
exit 1
fi
key="${update_tag%%=*}"
value="${update_tag#*=}"
# Validate the key and value
if [[ "$key" == "mood" ]]; then
if ! is_in_array "$value" "${allowed_moods[@]}"; then
echo "Error: Invalid mood value '$value'. Allowed values are: ${allowed_moods[*]}"
exit 1
fi
elif [[ " ${allowed_custom_tags[*]} " != *" $key "* ]]; then
echo "Error: Invalid tag key '$key'. Allowed keys are: ${allowed_custom_tags[*]}"
exit 1
fi
if tag_exists "$song_uri" "$key"; then
mpc sticker "$song_uri" set "$key" "$value"
echo "Tag '$key' updated to '$value' in '$song_uri'."
else
echo "Error: Tag '$key' does not exist on '$song_uri'. Use --add-tag to add it."
exit 1
fi
exit 0
fi
# ========================
# Execute Rating Actions
# ========================
if [ "$get_rating" = true ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "No song is currently playing."
exit 1
fi
rating=$(mpc sticker "$song_uri" get rating 2>/dev/null | sed 's/^rating=//')
if [ -z "$rating" ]; then
echo "No rating found for the current song."
else
echo "Rating of '$song_uri' is: $rating"
fi
exit 0
fi
if [ -n "$set_rating_value" ]; then
song_uri=$(get_current_song_uri)
if [[ -z "$song_uri" ]]; then
echo "Error: No song is currently playing."
exit 1
fi
mpc sticker "$song_uri" set rating "$set_rating_value"
echo "Rating of '$song_uri' set to $set_rating_value."
exit 0
fi
# ========================
# Final Validation
# ========================
if [ "$toprated" = false ] && [ "${#search_params[@]}" -eq 0 ]; then
echo "Error: You must specify at least one search criteria."
show_help
exit 1
fi
# ========================
# Build the Search Command
# ========================
# Clear the current playlist
mpc clear
if [ "$toprated" = true ]; then
# Call the Python script to get top-rated tracks
# Ensure that /usr/local/share/mympc/get_top_rated_tracks.py exists and is executable
if [ ! -x /usr/local/share/mympc/get_top_rated_tracks.py ]; then
echo "Error: Python script '/usr/local/share/mympc/get_top_rated_tracks.py' not found or not executable."
exit 1
fi
python3 /usr/local/share/mympc/get_top_rated_tracks.py
if [ "$play_now" = true ]; then
mpc play
echo "Playing playlist."
fi
exit 0
fi
# Construct the search command
search_cmd="mpc search"
for key in "${!search_params[@]}"; do
if [[ "$key" == "artist" ]]; then
for artist in "${artists[@]}"; do
# Escapar comillas internas y mantener las externas para mpc
artist_escaped="${artist//\"/\\\"}"
search_cmd+=" artist \"$artist_escaped\""
done
elif [[ "$key" == "genre" ]]; then
for genre in "${genres[@]}"; do
genre_escaped="${genre//\"/\\\"}"
search_cmd+=" genre \"$genre_escaped\""
done
elif [[ "$key" == "album" ]]; then
for album in "${albums[@]}"; do
album_escaped="${album//\"/\\\"}"
search_cmd+=" album \"$album_escaped\""
done
elif [[ "$key" == "track" ]]; then
for track in "${tracks[@]}"; do
track_escaped="${track//\"/\\\"}"
search_cmd+=" title \"$track_escaped\""
done
elif [[ "$key" == "year" ]]; then
for year in "${years[@]}"; do
search_cmd+=" date \"$year\""
done
elif [[ "$key" == "duration" ]]; then
for duration in "${durations[@]}"; do
search_cmd+=" duration \"$duration\""
done
fi
done
# Debugging: print the search command (uncomment if needed)
# echo "Executing search command: $search_cmd"
# Execute the search command and capture the songs
songs=$(eval "$search_cmd")
if [ -z "$songs" ]; then
echo "No songs found with the specified criteria."
exit 1
else
if [[ -n "${search_params[album]}" || -n "${search_params[track]}" ]]; then
# Add all found songs to the playlist
echo "$songs" | mpc add
num_songs_added=$(echo "$songs" | wc -l)
echo "Added $num_songs_added song(s) to the playlist."
else
# Add a random subset of songs to the playlist
selected_songs=$(echo "$songs" | shuf -n"$number_of_songs")
echo "$selected_songs" | mpc add
num_songs_added=$(echo "$selected_songs" | wc -l)
echo "Added $num_songs_added song(s) to the playlist."
fi
fi
# ========================
# Save Playlist
# ========================
if [ -n "$playlist_name" ]; then
mpc save "$playlist_name"
echo "Playlist saved as '$playlist_name'."
fi
# ========================
# Play Playlist
# ========================
if [ "$play_now" = true ]; then
mpc play
echo "Playing playlist."
fi
exit 0

View File

@ -0,0 +1,122 @@
#!/usr/bin/env python3
import sys
import argparse
from mpd import MPDClient, CommandError
import random
# Define the list of allowed mood tags
ALLOWED_MOOD_TAGS = {
"happy",
"sad",
"energetic",
"calm",
"angry",
"relaxed",
"excited",
"melancholic"
}
def parse_arguments():
parser = argparse.ArgumentParser(
description="Add songs with a specified mood tag to the MPD playlist."
)
parser.add_argument(
"mood",
type=str,
help=f"Desired mood tag. Allowed values: {', '.join(sorted(ALLOWED_MOOD_TAGS))}"
)
parser.add_argument(
"--host",
type=str,
default="localhost",
help="MPD server host (default: localhost)"
)
parser.add_argument(
"--port",
type=int,
default=6600,
help="MPD server port (default: 6600)"
)
return parser.parse_args()
def add_tracks_by_mood(mood, host="localhost", port=6600):
mood = mood.lower()
if mood not in ALLOWED_MOOD_TAGS:
print(f"Error: Invalid mood '{mood}'. Allowed moods are: {', '.join(sorted(ALLOWED_MOOD_TAGS))}.", file=sys.stderr)
sys.exit(1)
client = MPDClient()
try:
# Connect to the MPD server
client.connect(host, port)
print(f"Connected to MPD server at {host}:{port}.")
# Clear the current playlist
client.clear()
print("Cleared the current playlist.")
# Search for songs with the specified mood tag
# Assuming 'mood' is stored as a sticker in the format 'mood=<tag>'
# Using sticker_find to search for songs with the 'mood' sticker
response = client.sticker_find('song', '', 'mood')
# Process the response to filter tracks with the specified mood tag
matching_tracks = []
for entry in response:
file_path = entry.get('file')
sticker = entry.get('sticker')
if file_path and sticker:
try:
sticker_key, sticker_value = sticker.split('=', 1)
if sticker_key == 'mood' and sticker_value.lower() == mood:
matching_tracks.append(file_path)
except ValueError:
# Skip malformed sticker entries
continue
if matching_tracks:
# Remove duplicates
unique_tracks = sorted(set(matching_tracks))
# Shuffle songs for randomness
random.shuffle(unique_tracks)
# Add unique songs to the playlist
for track in unique_tracks:
client.add(track)
print(f"Added {len(unique_tracks)} unique song(s) with mood '{mood}' to the playlist.")
# Optionally, save the playlist with a specific name
# client.save('mood_playlist')
# Optionally, start playing the playlist
# client.play()
sys.exit(0) # Success
else:
print(f"No songs found with mood '{mood}'.")
sys.exit(0) # Treat as success since it's not a critical error
except CommandError as ce:
print(f"MPD command error: {ce}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"An error occurred: {e}", file=sys.stderr)
sys.exit(1)
finally:
# Close the connection to the MPD server
try:
client.close()
client.disconnect()
print("Disconnected from MPD server.")
except Exception:
pass
def main():
args = parse_arguments()
add_tracks_by_mood(args.mood, host=args.host, port=args.port)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
from mpd import MPDClient
def get_top_rated_tracks():
client = MPDClient()
client.connect("localhost", 6600) # Ajusta el host y el puerto si es necesario
# Utiliza el URI raíz o un directorio específico
response = client.sticker_find('song', '', 'rating')
# Procesar la respuesta
tracks = []
for entry in response:
if 'file' in entry and 'sticker' in entry:
sticker_name, sticker_value = entry['sticker'].split('=', 1)
if sticker_name == 'rating' and sticker_value == '5':
tracks.append(entry['file'])
if tracks:
for track in tracks:
client.add(track)
print(f"Added {len(tracks)} song(s) with a rating of 5 to the playlist.")
else:
print("there are no rated 5 songs.")
client.close()
client.disconnect()
if __name__ == '__main__':
get_top_rated_tracks()

View File

@ -0,0 +1,8 @@
# ~/.mympc/tags.conf
# Tag keys and their possible values
mood=happy,sad,energetic,calm,angry,relaxed,excited,melancholic
genre=rock,pop,jazz,blues,classical
rating=1,2,3,4,5
# Add more tags and their values as needed

45
usr/local/share/mympc/tags.sh Executable file
View File

@ -0,0 +1,45 @@
# ~/.mympc/tags.sh
# ========================
# Centralized Tag Definitions for mympc
# ========================
# Array of allowed mood values
allowed_moods=(
"happy"
"sad"
"energetic"
"calm"
"angry"
"relaxed"
"excited"
"melancholic"
# Add more moods as needed
)
# Array of allowed genre values
allowed_genres=(
"rock"
"pop"
"jazz"
"blues"
"classical"
"electronic"
"hiphop"
"country"
# Add more genres as needed
)
# Array of allowed rating values (optional)
allowed_ratings=( "0" "1" "2" "3" "4" "5" )
# Array of other custom tag keys (if any)
allowed_custom_tags=(
"custom1"
"custom2"
# Add more custom tag keys as needed
)
# ========================
# End of tags.sh
# ========================

View File

@ -0,0 +1,189 @@
#compdef mympc
# Fixed list of moods
_fixed_moods=("happy" "sad" "energetic" "calm" "angry" "relaxed" "excited" "melancholic")
_mympc() {
_arguments -s -C \
'--artist=[Search songs by artist (separated by commas)]:artist names:_my_mpc_artists' \
'--genre=[Search songs by genre]:genre name:_my_mpc_genres' \
'--album=[Search songs by album]:album name:_my_mpc_albums' \
'--track=[Search songs by track (separated by commas)]:track names:_my_mpc_tracks' \
'--year=[Filter songs by release year]:year:_mympc_years' \
'--duration=[Filter songs by duration (min:sec)]:duration:_mympc_durations' \
'--number=[Specify the number of songs]:number of songs:_mympc_number' \
'-n=[Specify the number of songs]:number of songs:_mympc_number' \
'--play[Play immediately]' \
'--preview[Preview songs to be added without adding them]' \
'--save-playlist=[Save the current playlist]:playlist name:_my_mpc_playlists' \
'--remove=[Remove songs from the playlist (separated by commas)]:songs to remove:_my_mpc_remove_songs' \
'--list-artists[List all available artists]' \
'--list-genres[List all available genres]' \
'--list-albums[List all available albums]' \
'--random[Activate random mode]' \
'--repeat[Activate repeat mode]' \
'--get-rating[Get the rating of the current song]' \
'--rate=[Set the current song rating (0-5)]:rating value (0-5):_mympc_ratings' \
'--toprated[Generate a list with top-rated tracks (5)]' \
'--add-tag=[Add a custom tag (key=value)]:custom tag:_mympc_add_tags' \
'--delete-tag=[Delete a custom tag]:tag key:_mympc_delete_tags' \
'--list-tags[List all tags of the current song]' \
'--update-tag=[Update a custom tag (key=value)]:custom tag:_mympc_update_tags' \
'--playlist-by-mood=[Generate a playlist based on mood]:mood:_my_mpc_playlist_by_mood' \
'--help[Show help message]' \
'-h[Show help message]'
}
# Custom autocomplete functions
_my_mpc_artists() {
compadd -- ${(f)"$(mpc list artist)"}
}
_my_mpc_genres() {
compadd -- ${(f)"$(mpc list genre)"}
}
_my_mpc_albums() {
local artist=""
local -a albums
# Buscar el artista en los argumentos ya escritos
for arg in ${words[@]}; do
if [[ $arg =~ --artist= ]]; then
# Extraer el nombre del artista (manejando espacios escapados)
artist=${arg#--artist=}
artist=${artist//\\ / }
break
fi
done
if [[ -n $artist ]]; then
# Obtener álbumes específicos del artista (manejando comillas)
albums=(${(f)"$(mpc list album artist "$artist")"})
else
# Obtener todos los álbumes si no hay artista especificado
albums=(${(f)"$(mpc list album)"})
fi
# Mostrar los álbumes como opciones de completado
_describe 'album' albums
}
_my_mpc_tracks() {
compadd -- ${(f)"$(mpc list title)"}
}
_my_mpc_playlists() {
compadd -- ${(f)"$(mpc lsplaylists)"}
}
_my_mpc_remove_songs() {
# Define arrays for predefined tag values if needed
local _fixed_moods=("happy" "sad" "energetic" "calm" "angry" "relaxed" "excited" "melancholic")
local _fixed_genres=("rock" "pop" "jazz" "blues" "classical" "hiphop" "electronic")
local _fixed_ratings=("1" "2" "3" "4" "5")
# Fetch the playlist with position and title
local IFS=$'\n' # Handle song titles with spaces
local songs=($(mpc playlist -f "%position%: %title%"))
# Initialize an array for completions
local -a completions
for song in "${songs[@]}"; do
completions+=("${song}")
done
# Provide the completions
compadd -- "${completions[@]}"
}
_mympc_years() {
local -a years
years=($(mpc list date | grep -E '^(19|20)[0-9]{2}$' | sort -u))
compadd -- "${years[@]}"
}
_mympc_durations() {
compadd -- "1:00" "2:00" "3:00" "4:00" "5:00" "6:00" "7:00" "8:00" "9:00" "10:00" # Adjust durations as needed
}
# Autocomplete for numbers
_mympc_number() {
_numbers
}
# Autocomplete for rating values
_mympc_ratings() {
compadd -- 0 1 2 3 4 5
}
# Autocomplete for adding tags (key=value)
_mympc_add_tags() {
# Get the current word being completed
local tag_word="${words[CURRENT]}"
# Check if the user has already typed '=' indicating key and is now completing the value
if [[ "$tag_word" == " " ]]; then
# Extract the key from 'key=value'
local key="${tag_word%%=*}"
local value="${tag_word#*=}"
if [[ "$key" == "mood" ]]; then
# Suggest only predefined mood values
compadd -- "${_fixed_moods[@]}"
else
# For other keys, do not suggest anything to prevent file completions
return 0
fi
else
# Suggest tag keys
local keys=("mood" "genre" "rating" "custom1" "custom2")
compadd -- "${keys[@]}"
fi
}
# Autocomplete for updating tags (key=value)
_mympc_update_tags() {
# Get the current word being completed
local tag_word="${words[CURRENT]}"
if [[ "$tag_word" == " " ]]; then
# Extract the key from 'key=value'
local key="${tag_word%%=*}"
local value="${tag_word#*=}"
if [[ "$key" == "mood" ]]; then
# Suggest only predefined mood values
compadd -- "${_fixed_moods[@]}"
else
# For other keys, do not suggest anything to prevent file completions
return 0
fi
else
# Suggest existing tag keys from the current song
local song_uri
song_uri=$(mpc --format %file% current)
local -a keys
keys=($(mpc sticker "$song_uri" list 2>/dev/null | cut -d'=' -f1))
compadd -- "${keys[@]}"
fi
}
# Autocomplete for deleting tags (only keys)
_mympc_delete_tags() {
local song_uri
song_uri=$(mpc --format %file% current)
local -a tags
tags=($(mpc sticker "$song_uri" list 2>/dev/null | cut -d'=' -f1))
compadd -- "${tags[@]}"
}
# Autocomplete for generating playlist by mood
_my_mpc_playlist_by_mood() {
# Use the predefined mood list for suggestions
_values "mood" "${_fixed_moods[@]}"
}
# Register the autocompletion function with Zsh
compdef _mympc mympc