Compare commits
	
		
			4 Commits
		
	
	
		
			4343521a46
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ed12cef7e4 | |||
| 06485fbce7 | |||
| 214a1cda4c | |||
| d13436b963 | 
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
								
							@@ -12,6 +12,7 @@ Control playback from your terminal while browsing the vast world of music relea
 | 
				
			|||||||
- Handle metadata without touching your audio files
 | 
					- Handle metadata without touching your audio files
 | 
				
			||||||
- Fast and hackable application with [vim](https://www.vim.org)-like keybindings
 | 
					- Fast and hackable application with [vim](https://www.vim.org)-like keybindings
 | 
				
			||||||
- Save and load playlists
 | 
					- Save and load playlists
 | 
				
			||||||
 | 
					- Lyrics support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
🎞️ Screenshot
 | 
					🎞️ Screenshot
 | 
				
			||||||
-------------
 | 
					-------------
 | 
				
			||||||
@@ -19,7 +20,7 @@ Control playback from your terminal while browsing the vast world of music relea
 | 
				
			|||||||
The MusicBrainz database is automatically searched after entering a query.
 | 
					The MusicBrainz database is automatically searched after entering a query.
 | 
				
			||||||
In the screenshot below, the emoji 🔆 indicates that some tracks of _Mc Solaar_ are available in the local music library.
 | 
					In the screenshot below, the emoji 🔆 indicates that some tracks of _Mc Solaar_ are available in the local music library.
 | 
				
			||||||
They are played by hitting `<enter>`.
 | 
					They are played by hitting `<enter>`.
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Browse Local Music Library
 | 
					### Browse Local Music Library
 | 
				
			||||||
Here, we fuzzily search an album of _Daft Punk._
 | 
					Here, we fuzzily search an album of _Daft Punk._
 | 
				
			||||||
@@ -119,7 +120,7 @@ $ fuzic --decorate ~/Music/Daft\ Punk/Random\ Access\ Memories
 | 
				
			|||||||
Info: Decorating /home/amin/Music/Daft Punk/Random Access Memories as release 5000a285-b67e-4cfc-b54b-2b98f1810d2e
 | 
					Info: Decorating /home/amin/Music/Daft Punk/Random Access Memories as release 5000a285-b67e-4cfc-b54b-2b98f1810d2e
 | 
				
			||||||
$ fuzic --decorate-as ~/Music/Mc\ Solaar/Prose\ Combat 69e5cf67-7cea-4fe8-9129-9779f0a93d69
 | 
					$ fuzic --decorate-as ~/Music/Mc\ Solaar/Prose\ Combat 69e5cf67-7cea-4fe8-9129-9779f0a93d69
 | 
				
			||||||
Info: Decorating /home/amin/Music/Mc Solaar/Prose Combat as the release Prose Combat by MC Solaar
 | 
					Info: Decorating /home/amin/Music/Mc Solaar/Prose Combat as the release Prose Combat by MC Solaar
 | 
				
			||||||
Info: We discovered the following associatoin:
 | 
					Info: We discovered the following association:
 | 
				
			||||||
Track 'Aubade'                         File './01 Aubade.m4a'
 | 
					Track 'Aubade'                         File './01 Aubade.m4a'
 | 
				
			||||||
Track 'Obsolète'                       File './02 Obsolète.m4a'
 | 
					Track 'Obsolète'                       File './02 Obsolète.m4a'
 | 
				
			||||||
Track 'Nouveau western'                File './03 Nouveau western.m4a'
 | 
					Track 'Nouveau western'                File './03 Nouveau western.m4a'
 | 
				
			||||||
@@ -176,6 +177,28 @@ You may also define the playlist directory using the `PLAYLIST_DIRECTORY` enviro
 | 
				
			|||||||
In `share/playlists` you find example playlists.
 | 
					In `share/playlists` you find example playlists.
 | 
				
			||||||
Thus, the command `PLAYLIST_DIRECTORY=share/playlists fuzic` launches this application with access to these example playlists.
 | 
					Thus, the command `PLAYLIST_DIRECTORY=share/playlists fuzic` launches this application with access to these example playlists.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					📜 Lyrics
 | 
				
			||||||
 | 
					---------
 | 
				
			||||||
 | 
					By using the key `L` (normal mode), the lyrics of the selected track are displayed.
 | 
				
			||||||
 | 
					The lyrics are taken from (in that order)
 | 
				
			||||||
 | 
					1. the lyrics stored using `fuzic`, or
 | 
				
			||||||
 | 
					2. from the `.lrc` file with the same name as the audio file, or
 | 
				
			||||||
 | 
					3. from the audio-file tags (requires `ffprobe`), or
 | 
				
			||||||
 | 
					4. from a custom script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To specify the custom script, you can set the `LYRICS_FETCH_CUSTOM` environment variable to point to an executable.
 | 
				
			||||||
 | 
					The executable reads a JSON string on the standard input, and is supposed to print the lyrics (see `share/lyrics/example.sh`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may also skip the first three sources and directly make a call to your custom script by using the key `Y` (normal mode).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The key `alt-L` opens the lyrics in a new window using the `EDITOR`.
 | 
				
			||||||
 | 
					This requires one of the following terminal emulators (`kitty`, `x-terminal-emulator`, `gnome-terminal`, `xterm`).
 | 
				
			||||||
 | 
					If you use another terminal emulator, you may specify the environment variable `EXTERNALEDIT` to hold the string such that
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					$ExTERNALEDIT "$file"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					spawns a text editor with `$file` loaded inside a terminal emulator.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
🧭 Planned Features
 | 
					🧭 Planned Features
 | 
				
			||||||
-------------------
 | 
					-------------------
 | 
				
			||||||
The following features are planned:
 | 
					The following features are planned:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								share/lyrics/example.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										25
									
								
								share/lyrics/example.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Example script for `fuzic` to display the lyrics of a track. This script
 | 
				
			||||||
 | 
					# reads from stdin a JSON string and stores it in the variable `j`. The
 | 
				
			||||||
 | 
					# variable `tj` contains the JSON string of the track.
 | 
				
			||||||
 | 
					j="$(cat)"
 | 
				
			||||||
 | 
					tj="$(echo "$j" | jq -r '.trackid as $tid | .release.media[].tracks[] | select(.id == $tid)')"
 | 
				
			||||||
 | 
					# The following four variables are self-explanatory:
 | 
				
			||||||
 | 
					track_name="$(echo "$tj" | jq -r '.title')"
 | 
				
			||||||
 | 
					artist_name="$(echo "$tj" | jq -r '."artist-credit" | map([.name, .joinphrase] | join("")) | join("")')"
 | 
				
			||||||
 | 
					album_name="$(echo "$j" | jq -r '.release.title')"
 | 
				
			||||||
 | 
					duration="$(echo "$tj" | jq -r '.length / 1000 | round')"
 | 
				
			||||||
 | 
					# Now, you may call an API to fetch the lyrics for this track,
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# curl \
 | 
				
			||||||
 | 
					#   --get \
 | 
				
			||||||
 | 
					#   --silent \
 | 
				
			||||||
 | 
					#   --data-urlencode "track_name=$track_name" \
 | 
				
			||||||
 | 
					#   --data-urlencode "artist_name=$artist_name" \
 | 
				
			||||||
 | 
					#   --data-urlencode "album_name=$album_name" \
 | 
				
			||||||
 | 
					#   --data-urlencode "duration=$duration" \
 | 
				
			||||||
 | 
					#   "$URL"
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# or simply print a template to write the lyrics yourself:
 | 
				
			||||||
 | 
					printf "Lyrics '%s' by '%s' (album: %s, duration: %s seconds)\n" "$track_name" "$artist_name" "$album_name" "$duration"
 | 
				
			||||||
@@ -443,7 +443,7 @@ case "${1:-}" in
 | 
				
			|||||||
  ;;
 | 
					  ;;
 | 
				
			||||||
"--playlists")
 | 
					"--playlists")
 | 
				
			||||||
  # List available playlists
 | 
					  # List available playlists
 | 
				
			||||||
  stored_playlists
 | 
					  stored_playlists | cut -d "$(printf '\t')" -f 1
 | 
				
			||||||
  exit 0
 | 
					  exit 0
 | 
				
			||||||
  ;;
 | 
					  ;;
 | 
				
			||||||
"--print-playlist")
 | 
					"--print-playlist")
 | 
				
			||||||
@@ -474,7 +474,7 @@ GENERAL OPTIONS:
 | 
				
			|||||||
  --playlists                   List stored playlists and exit
 | 
					  --playlists                   List stored playlists and exit
 | 
				
			||||||
  --load-playlist <playlist>    Load specified playlist
 | 
					  --load-playlist <playlist>    Load specified playlist
 | 
				
			||||||
  --print-playlist <playlist>   Print specified playlist and exit
 | 
					  --print-playlist <playlist>   Print specified playlist and exit
 | 
				
			||||||
  --lyrics <release> <mbid>     Show lyrics specified track and exit
 | 
					  --lyrics <relid> <mbid>       Show lyrics of track <mbid> in release <relid> and exit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MANAGE LOCAL MUSIC:
 | 
					MANAGE LOCAL MUSIC:
 | 
				
			||||||
  --decorate <path>             Decorate directory containing a tagged release
 | 
					  --decorate <path>             Decorate directory containing a tagged release
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,7 +157,7 @@ END { for (i in id) print title[i], id[i], fname[i] }
 | 
				
			|||||||
' "$tmpj" "$tmpf" >"$assocfile"
 | 
					' "$tmpj" "$tmpf" >"$assocfile"
 | 
				
			||||||
  rm -f "$tmpj" "$tmpf"
 | 
					  rm -f "$tmpj" "$tmpf"
 | 
				
			||||||
  # Ask user if this is ok
 | 
					  # Ask user if this is ok
 | 
				
			||||||
  info "We discovered the following associatoin:"
 | 
					  info "We discovered the following association:"
 | 
				
			||||||
  while IFS= read -r line; do
 | 
					  while IFS= read -r line; do
 | 
				
			||||||
    t="$(echo "$line" | cut -d "$(printf '\t')" -f 1)"
 | 
					    t="$(echo "$line" | cut -d "$(printf '\t')" -f 1)"
 | 
				
			||||||
    f="$(echo "$line" | cut -d "$(printf '\t')" -f 3)"
 | 
					    f="$(echo "$line" | cut -d "$(printf '\t')" -f 3)"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,9 @@ if [ ! "${LYRICS_LOADED:-}" ]; then
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  # Custom command to fetch lyrics
 | 
					  # Custom command to fetch lyrics
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  # This command reads from stdin the json object of the track and prints the
 | 
					  # This command reads from stdin the json object of the release and prints the
 | 
				
			||||||
  # lyrics.
 | 
					  # lyrics of the track.
 | 
				
			||||||
  LYRICS_FETCH_CUSTOM="${LYRICS_FETCH_CUSTOM:-"$JQ '.trackid as \$tid | .release.media[].tracks[] | select(.id == \$tid) | .title'"}"
 | 
					  LYRICS_FETCH_CUSTOM="${LYRICS_FETCH_CUSTOM:-""}"
 | 
				
			||||||
  #LYRICS_FETCH_CUSTOM="${LYRICS_FETCH_CUSTOM:-"$JQ '.trackid as \$trid | \"Lyrics for \" + .media[].tracks[] | select(.id == \$trid) | .title'"}"
 | 
					 | 
				
			||||||
  export LYRICS_FETCH_CUSTOM
 | 
					  export LYRICS_FETCH_CUSTOM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export LYRICS_LOADED=1
 | 
					  export LYRICS_LOADED=1
 | 
				
			||||||
@@ -51,13 +50,21 @@ store_lyrics() {
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# @argument $1: MusicBrainz release ID
 | 
					# @argument $1: MusicBrainz release ID
 | 
				
			||||||
# @argument $2: MusicBrainz track ID
 | 
					# @argument $2: MusicBrainz track ID
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The custom script is executed only if the environment variable is set. Else
 | 
				
			||||||
 | 
					# the message stored in `$LYRICS_NO_LYRICS` is saved.
 | 
				
			||||||
store_lyrics_custom() {
 | 
					store_lyrics_custom() {
 | 
				
			||||||
  rlid="${1:-}"
 | 
					  rlid="${1:-}"
 | 
				
			||||||
  mbid="${2:-}"
 | 
					  mbid="${2:-}"
 | 
				
			||||||
  mb_release "$rlid" |
 | 
					  if [ "$LYRICS_FETCH_CUSTOM" ]; then
 | 
				
			||||||
    $JQ --arg mbid "$mbid" '{release: ., trackid: $mbid}' |
 | 
					    mb_release "$rlid" |
 | 
				
			||||||
    sh -c "$LYRICS_FETCH_CUSTOM" |
 | 
					      $JQ --arg mbid "$mbid" '{release: ., trackid: $mbid}' |
 | 
				
			||||||
    store_lyrics "$mbid"
 | 
					      sh -c "$LYRICS_FETCH_CUSTOM" |
 | 
				
			||||||
 | 
					      store_lyrics "$mbid"
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    echo "$LYRICS_NO_LYRICS" |
 | 
				
			||||||
 | 
					      store_lyrics "$mbid"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Print lyrics
 | 
					# Print lyrics
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -399,5 +399,10 @@ if [ ! "${THEME_LOADED:-}" ]; then
 | 
				
			|||||||
  PLYSTORE_PLAYLIST="${PLYSTORE_PLAYLIST:-"🎼 ${CPURPLE}%f${OFF}"}"
 | 
					  PLYSTORE_PLAYLIST="${PLYSTORE_PLAYLIST:-"🎼 ${CPURPLE}%f${OFF}"}"
 | 
				
			||||||
  export TITLE_PLYLST TITLE_PLYLST_STORE PLYSTORE_PLAYLIST
 | 
					  export TITLE_PLYLST TITLE_PLYLST_STORE PLYSTORE_PLAYLIST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Lyrics
 | 
				
			||||||
 | 
					  # ======
 | 
				
			||||||
 | 
					  LYRICS_NO_LYRICS="${LYRICS_NO_LYRICS:-"(no lyrics)"}"
 | 
				
			||||||
 | 
					  export LYRICS_NO_LYRICS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export THEME_LOADED=1
 | 
					  export THEME_LOADED=1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user