diff --git a/list_functions.txt b/list_functions.txt new file mode 100644 index 0000000..59760e8 --- /dev/null +++ b/list_functions.txt @@ -0,0 +1,86 @@ +about +add_playlist_to_queue +alarms +all +all_mute_off +all_mute_on +all_status_light_off +all_status_light_on +all_zones +clear_queue +create_alarms +create_playlist +deezer_flow +delete_playlist +delete_speaker_cache +devices +enable_alarms +favourite_radio_stations +franceinfo +franceinter +groupstatus +help +info_groups +inform +infos +is_int +k6fm +led +level_11 +level_13 +level_15 +list_alarms +list_albums +list_all_playlist_tracks +list_artists +list_favs +list_playlists +list_queue +main +make_playlist +minfo +modify_alarms +move_alarms +mute_off +mute_on +next +option_7 +party_mode +pause +play_album_from_library +play_artist_from_library +play_local_dir +play_local_file +play_local_m3u +play_radio_from_tunein +play_shared_link +play_track_from_library +play_uri +prev +refresh_speaker_list +reindex +remove_alarms +remove_from_playlist +remove_from_queue +rename_spk +rires +rtl +shares +shazaaaam +shazam +sleeep +sleeep_cancel +sleeep_duration +sleeep_timer +snooze_alarms +soco +soco_alarms +soco_infos +soco_lists +spec +start +stop +sysinfo +ungroup_all +vol+ +vol- diff --git a/macros.txt b/macros.txt new file mode 100644 index 0000000..6759237 --- /dev/null +++ b/macros.txt @@ -0,0 +1,3 @@ +# SoCo-CLI HTTP API Server Macros file +# Format is: +# macro_name = speaker [: speaker ...] diff --git a/old_functions.sh b/old_functions.sh new file mode 100644 index 0000000..5508d54 --- /dev/null +++ b/old_functions.sh @@ -0,0 +1,524 @@ +# play local file (.mp3|.mp4|.m4a|.aac|.flac|.ogg|.wma|.wav) +# alac in m4v +# /Users/bruno/Music/The Smile - A Light For Attracting Attention [Japan Edition] (2022)/01. The Same.mp3 + +# BLOQUANT Ctrl-C to quit + +play_local_file() { + playing="Play a local audio file..." + echo -e "\n${bold} $playing ${reset}\n" + + echo -e "${underline}Enter audio file/folder path${reset} (.mp3|.mp4|.m4a|.aac|.flac|.ogg|.wma|.wav) " + read -e -i "$HOME/" -p ": " fa + + #fa=/Users/bruno/Music/Alanis\ Morissette\ -\ Such\ Pretty\ Forks\ In\ The\ Road + + if ! command -v mediainfo &> /dev/null; then + echo "Install mediainfo to display media tags !" + echo -e "${italic}brew install mediainfo${reset}" + mediainfo=false + else + mediainfo=true + fi + + audio=$(echo "$fa" | awk -F"/" '{print $NF}') + + if [ -d "$fa" ]; then + if [[ "$OSTYPE" == "darwin"* ]]; then + echo $fa + list=$(find -E "$fa" -iregex ".*\.(mp3|mp4|m4a|aac|flac|ogg|wma|wav)" | sort) + else + list=$(find "$fa" -iregex ".*\.\(mp3\|mp4\|m4a\|aac\|flac\|ogg\|wma\|wav\)" | sort) + fi + + echo -e "\n${underline}Tracks to play...${reset}" + i=1 + while IFS= read -r line; do + [ "$mediainfo" = true ] && minfo "${line}" "$i" + ((i++)) + done <<< "$list" + + echo -e "\n${underline}Playing...${reset}" + echo -e "\nHit CTRL-C to play next track \n" + printf " %-2s %-20s %-30s %-30s %-12s %-10s \n" "N°" "Artist" "Track" "Album" "Duration" "Year" + + i=1 + while IFS= read -r line; do + [ "$mediainfo" = true ] && minfo "${line}" "$i" + + sonos $loc $device play_file "${line}" + + [ $? != 0 ] && echo -e "${red}Error !${reset}"; break + ((i++)) + done <<< "$list" + + #sonos $loc $device play_file "$list" + + elif [ -f "$fa" ]; then + echo -e "\nCurrently playing ${underline}$audio${reset} ...\n" + [ "$mediainfo" = true ] && minfo "$fa" + + echo -e "\n${italic}Wait for the music to end, hit from another shell or hit CTRL-C to quit${reset}" + sonos $loc $device play_file "$fa" + #album_art + else + echo -e "❗ ️File/folder ${bold}$audio${reset} doesn't exist!" && sleep 2 + playing="" + fi +} + + +play_local_dir() { + + playing="Playing a local directory..." + echo -e "\n${bold} $playing ${reset}\n" + + echo -e "${underline}Enter a folder path:${reset} " + read -e -i "$HOME/" -p "? " dir + echo $fa + #dir=$(echo "$fa" | sed 's/ /\\ /g') + if [ -d "$dir" ]; then + sonos $loc $device play_directory "$dir" + else + echo -e "❗ ️Folder ${bold}$dir${reset} doesn't exist!" && sleep 2 + playing="" + fi + + read -p "< Press Enter>" + sleep 2 + +} +export -f play_local_dir + + +play_shared_link() { + + playing="Playing a shared link..." + echo -e "\n${bold} $playing ${reset}\n" + + echo -e "\nExample:" + echo "https://open.spotify.com/track/6cpcorzV5cmVjBsuAXq4wD" + echo "https://tidal.com/browse/album/157273956" + echo "https://www.deezer.com/en/playlist/5390258182" + echo "https://music.apple.com/dk/album/black-velvet/217502930?i=217503142" + + music=("https://open.spotify.com" "https://tidal.com" "https://www.deezer.com/" "https://music.apple.com") + echo -e "${underline}Enter an url:${reset} " + read -e -i "https://" -p "? " sl + + for i in ${music[@]}; do + [[ "$sl" == *"$i"* ]] && s_link=$sl + done + if [ -n "$s_link" ]; then + echo "$sl" + queue=$(sonos $loc $device sharelink "$sl") + sonos $loc $device play_from_queue $queue + else + echo -e "❗ ️Invalid shared link !" + playing="" + fi + + read -p "< Press Enter>" + sleep 2 +} + + +make_playlist() { + + playing="Create a playlist..." + echo -e "\n${bold} $playing ${reset}\n" + + # GNU bash, version 3.2.57(1)-release-(x86_64-apple-darwin20) + #read -e -p "Choose folder to create playlist from: " folder + # GNU bash, version 5.1.4(1)-release (x86_64-apple-darwin19.6.0) (brew install bash) + read -e -i "$HOME/Music/" -p "Choose folder to create playlist from: " folder + + if [ -d "$folder" ]; then + + read -e -p "Include subfolder ? (y/n) " sub + + if [ "$sub" == "y" ] || [ "$sub" == "Y" ]; then + #m3u=$(echo "$fp" | awk -F"/" '{print $NF}') + if [[ "$OSTYPE" == "darwin"* ]]; then list=$(find -E "$folder" -iregex ".*\.(mp3|mp4|m4a|aac|flac|ogg|wma|wav)" | sort) + else list=$(find "$folder" -iregex ".*\.\(mp3\|mp4\|m4a\|aac\|flac\|ogg\|wma\|wav\)" | sort); fi + else + if [[ "$OSTYPE" == "darwin"* ]]; then list=$(find -E "$folder" -maxdepth 1 -iregex ".*\.(mp3|mp4|m4a|aac|flac|ogg|wma|wav)" | sort) + else list=$(find "$folder" -maxdepth 1 -iregex ".*\.\(mp3\|mp4\|m4a\|aac\|flac\|ogg\|wma\|wav\)" | sort); fi + fi + + while [ true ] ; do + read -t 10 -e -p "Give a name to the playlist (without extension): " pl_name + if [ -n "$pl_name" ] ; then + break ; + else + echo "Waiting for a name !" + fi + done + + plst="$pl_name.m3u" + printf "#EXTM3U\n" > "$plst" + echo "$list" >> "$plst" + + + read -e -p "Do you want to edit $plst ? (y/n) " edit + if [ "$edit" == "y" ] || [ "$edit" == "Y" ]; then + [ -n $EDITOR ] && $EDITOR "$plst" || nano "$plst" + fi + + # Extract album art from .mp3 + # ffmpeg -hide_banner -loglevel error -i 01.\ Portez\ vos\ croix.mp3 -s 300x300 album_art.jpg + + read -e -p "Do you want to play $plst ? (y/n) " play + if [ "$play" == "y" ] || [ "$play" == "Y" ]; then + playing="Playing the ${bold_under}$plst${reset}${underline} playlist..." + echo -e "\n${underline}$playing${reset}" + pls=$(cat "$plst") + echo -e "\n$pls\n" + + ### BUG: bloc menu avec CTRL-C ### + + echo -e "Hit CTRL-C to exit playlist \n" + sonos $loc $device play_m3u "$plst" pi + fi + + else + echo "Folder $folder doesn't exist !'" + fi +} + +# Play URI +play_uri() { + playing="" + echo -e "\n${bold} Play radio stream... ${reset}\n" + + read -p "Enter radio stream URL [.mp3|.aac|.m3u|.pls]: " url + #url="http://jazzradio.ice.infomaniak.ch/jazzradio-high.aac" + + read -p "Enter radio stream name: " title + + if [[ "$url" =~ ^http ]]; then + if [ -n "$title" ]; then playing="Playing $title radio stream..." + else playing="Playing $url radio stream..."; fi + echo -e "\n${bold} $playing ${reset}" + sonos $loc $device play_uri $url "$title" + else + echo -e "\nWrong radio stream URL !" + fi + sleep 2 + } + + +# Search artist in library -> add album to queue -> play it +play_artist_from_library() { + read -e -p "Search artist in library: " search + + if [ -n "$search" ]; then + a=$(sonos $loc $device search_artists "$search") + + # fzf + + if [ -n "$a" ]; then + echo -e "$a\n" + read -e -p "Album to play (n°): " number + + if [[ "$number" =~ ^[+-]?[0-9]+$ ]]; then + b=$(echo "$a" | grep -m 1 "$number: ") + album=$(echo "$b" | awk -F ": " '{print $3}' | awk -F "|" '{print $1}' | sed 's/ *$//g') + artist=$(echo "$b" | awk -F ": " '{print $4}') + + playing="Playing $album from $artist..." + echo -e "\n${bold} $playing ${reset}" + + sonos $loc $device queue_search_result_number $number first : $device play_from_queue > /dev/null + else echo "Please, enter the number of the album to play !" + fi + else echo -e "Artist ${underline}$search${reset} was not found !" + fi + else echo "Empty query !" + fi + } + +# Search album in library -> add to queue -> play it +play_album_from_library() { + read -e -p "Search album in library: " search + + if [ -n "$search" ]; then + a=$(sonos $loc $device search_albums "$search") + if [ -n "$a" ]; then + echo -e "$a\n" + read -e -p "Album to play (n°): " number + + if [[ "$number" =~ ^[+-]?[0-9]+$ ]]; then + b=$(echo "$a" | grep -m 1 "$number: ") + album=$(echo "$b" | awk -F ": " '{print $3}' | awk -F "|" '{print $1}' | sed 's/ *$//g') + artist=$(echo "$b" | awk -F ": " '{print $4}') + + playing="Playing $album from $artist..." + echo -e "\n${bold} $playing ${reset}" + + sonos $loc $device queue_search_result_number $number first : $device play_from_queue > /dev/null + else echo "Please, enter the number of the album to play !" + fi + else echo -e "Album ${underline}$search${reset} was not found !" + fi + else echo "Empty query !" + fi + } + +# Search track in library -> add to queue -> play it +play_track_from_library() { + read -e -p "Search track in library: " search + + if [ -n "$search" ]; then + a=$(sonos $loc $device search_tracks "$search") + if [ -n "$a" ]; then + echo -e "$a\n" + read -e -p "Track to play: " number + + if [[ "$number" =~ ^[+-]?[0-9]+$ ]]; then + b=$(echo "$a" | grep -m 1 "$number: ") + # 1: Artist: Alain Souchon | Album: Collection (1984-2001) | Title: J'veux du cuir + track=$(echo "$b" | awk -F ": " '{print $5}') + artist=$(echo "$b" | awk -F ": " '{print $3}' | awk -F "|" '{print $1}' | sed 's/ *$//g') + + playing="Playing $track from $artist..." + echo -e "\n${bold} $playing ${reset}" + + sonos $loc $device queue_search_result_number $number first : $device play_from_queue > /dev/null + else echo "Please, enter the number of the track to play !" + fi + else echo -e "Track ${underline}$search${reset} was not found !" + fi + else echo "Empty query !" + fi + } + + +search_tracks_from_youtube_ytdlp() { + + # https://github.com/mps-youtube/yewtube + # https://github.com/pystardust/ytfzf + + # https://stackoverflow.com/questions/49804874/download-the-best-quality-audio-file-with-youtube-dl + + #yt-dlp ytsearch5:"the clash" --get-id --get-title + + # yt-dlp -f 'ba' -ciw --extract-audio --audio-quality 0 --audio-format aac -o "%(title)s.%(ext)s" -v --downloader aria2c 'https://www.youtube.com/watch?v=l0Q8z1w0KGY' + # yt-dlp -f 251 'https://www.youtube.com/watch?v=l0Q8z1w0KGY' (webm opus) + # yt-dlp -f 140 'https://www.youtube.com/watch?v=l0Q8z1w0KGY' (m4a) + + # cache: ~/.cache/yt-dlp/ ~/.cache/youtube-dl/ + + # dl + # yt-dlp -- bJ9r8LMU9bQ + # yt-dlp -o - "https://www.youtube.com/watch?v=bJ9r8LMU9bQ" | vlc - + # audio='yt-dIp -f 'ba' -x --audio-format mp3' + # -o '%(id)s.%(ext)s' + # ytfzf + + if (! type yt-dlp > /dev/null 2>&1); then + echo -e "Install ${bold}yt-dlp${reset} for searching / downloading from YouTube !" + echo -e "https://github.com/yt-dlp/yt-dlp" + echo -e "${italic}brew install yt-dlp${reset}" + exit + fi + + tmp_path=/tmp/soco-cli-gui + [ -d $tmp_path ] && rm -rf $tmp_path + mkdir $tmp_path + tempfile=$(mktemp) + youtube_dl_log=$(mktemp) + + read -e -p $'\e[1mSearch in YouTube: \e[1m' search + + yt-dlp -j "ytsearch20:$search" | jq -r '{"Title": .fulltitle,"URL": .webpage_url,"Id": .id,"Thumbnail": .thumbnail,"Duration": .duration_string,"Description": .description}' | sed 's/\\\"/*/g' > $tempfile + # --match-filter "description !~= '\"'" + + img=$(_sanitize $search) + #cat $tempfile | jq + + echo + + declare -a yt_urls=() + declare -a yt_titles=() + declare -a yt_durations=() + j=1 + + while read i; do + #echo "$i" + title=$(jq -r '.Title' <<< "$i") + url=$(jq -r '.URL' <<< "$i") + idx=$(jq -r '.Id' <<< "$i") + desc=$(jq -r '.Description' <<< "$i") + thumb=$(jq -r '.Thumbnail' <<< "$i") + duration=$(jq -r '.Duration' <<< "$i") + [ ${#duration} -le 2 ] && duration="0:$duration" + echo -e "${bold}$j. $title${reset} ($duration)" + # "Title": "Arno \"Je serais devenu un gangster sans la scène\" #INA #short", + echo -e "${desc:0:200}" | fold -w 80 -s + echo "$url" + #echo "$thumb" + #echo "$idx" + yt_urls+=("$url") + yt_titles+=("$title") + yt_durations+=("$duration") + + if [ -n "$thumb" ]; then + name="$img$j.png" + magick "$thumb" -quality 75 -resize 300x300\> $tmp_path/$name + + if [ -f "$tmp_path/$name" ]; then + printf "\n\t\033]1337;File=;width=300px;inline=1:`cat $tmp_path/$name | base64`\a\n" + fi + + fi + echo + ((j++)) + done <<< $(jq -c '.' "$tempfile") + + nb=${#yt_urls[@]} + + while : + do + read -e -p $'\e[1mEnter video number to download/listen or q to quit: \e[1m' i + echo + + [ "$i" == "q" ] && break + if ((i >= 1 && i <= $nb)); then + ((i=i-1)) + youtube_title=${yt_titles[$i]} + youtube_duration=${yt_durations[$i]} + youtube_url=${yt_urls[$i]} + + if [ -n "$youtube_url" ]; then + yt-dlp -f 140 $youtube_url -P $dest_yt -o "%(title)s.%(ext)s" --restrict-filenames + filename=$(yt-dlp -f 140 $youtube_url -P $dest_yt -o "%(title)s.%(ext)s" --restrict-filenames --get-filename) + + echo -e "\nPlaying ${bold}$youtube_title${reset} ($youtube_duration) (Ctrl-C to quit)\n" + sonos $loc $device play_file "$filename" + fi + + fi + done + +} + + +s_ar_f_l() { +######################@ + while : + do + echo + read -e -p "Search artist in library: " search + + if [ -n "$search" ]; then + + artists=$(sonos "$loc" "$device" list_artists | tail -n+4 | fzf "${fzf_music_folder_args[@]}") + #artists=$(sonos "$loc" "$device" search_artists "$search" | tail -n+4 | awk NF | grep -v -E "^ ===" | sort) + #tracks=$(cat search_tracks.txt| tail -n+4) + echo "$artists" + nb=$(echo -n "$artists" | grep -c '^') + + if [ "$nb" -gt 0 ]; then + + if [ $fzf_bin -eq 1 ]; then + + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select artist; ESC for a new search" + ) + alb=$(echo "$artists" | fzf "${fzf_music_folder_args[@]}") + [ -n "$alb" ] && break + + else + [ "$nb" -gt 1 ] && echo "Artists found:" || echo "Artist found:" + echo -e "$artists\n" + + while : + do + read -e -p "Choose index of artist or (q) to re-search: " research + + if [ "$research" != "q" ] && [ -n "$research" ]; then + alb=$(echo "$artists" | grep -E ^[[:blank:]]+"$research:") + [ -n "$art" ] && break 2 || echo "Wrong Choice !" + + else break + fi + done + + fi + fi + fi + done + + if [ -n "$alb" ]; then + echo "$alb" + fi +} + +s_al_f_l() { + + while : + do + echo + read -e -p "Search album in library: " search + + if [ -n "$search" ]; then + + albums=$(sonos "$loc" "$device" search_albums "$search" | tail -n+4) + nb=$(echo -n "$albums" | grep -c '^') + + if [ "$nb" -gt 0 ]; then + + #fzf_bin=0 + if [ $fzf_bin -eq 1 ]; then + + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select album; ESC for a new search" + --prompt="Search album..." + ) + alb=$(echo "$albums" | fzf "${fzf_music_folder_args[@]}") + [ -n "$alb" ] && break + + else + [ "$nb" -gt 1 ] && echo "Albums found:" || echo "Album found:" + echo -e "$albums\n" + + while : + do + read -e -p "Choose index of album, (s) to re-search, (q) to quit: " research + + [ "$research" == "s" ] && break + [ "$research" == "q" ] && break 2 + if [[ $research == ?(-)+([[:digit:]]) ]]; then + if [ $research -gt 0 ] && [ $research -le $nb ]; then + alb=$(echo "$albums" | grep -E ^[[:blank:]]+"$research:") + #result=$research + [ -n "$alb" ] && break 2 || echo "Wrong Choice !" + fi + fi + done + + fi + fi + fi + done + + if [ -n "$alb" ]; then + + track=$(echo "$alb" | awk -F ": " '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') + artist=$(echo "$alb" | awk -F ": " '{print $3}' | awk -F "|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') + album=$(echo "$alb" | awk -F ": " '{print $4}' | awk -F "|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') + #title=$(echo "$alb" | awk -F ": " '{print $5}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') + + echo -e "\nPlaying album ${bold}$album${reset} of ${bold}$artist${reset}..." + + sonos "$loc" "$device" queue_search_result_number $track first : $device play_from_queue > /dev/null + + art + fi + +} diff --git a/soco-cli-gui.sh b/soco-cli-gui.sh index d129db6..fc516d8 100755 --- a/soco-cli-gui.sh +++ b/soco-cli-gui.sh @@ -8,7 +8,7 @@ # TODO # -# Add queue position option for 'add_sharelink_to_queue' +# Add queue position option for 'add_sharelink_to_queue' or 'sharelink' 1120 play_shared_link() # - Add 'last' option to 'play_from_queue' action # - Add 'random' option to 'play_from_queue' action # - Add 'last_added' option to 'play_from_queue' action @@ -132,6 +132,10 @@ _sanitize() { echo "${s,,}" # convert to lowercase } +_trim () { + read -rd '' $1 <<<"${!1}" +} + # Get url status ans radio's name from uri stream _curl_url() { status_uri= @@ -462,7 +466,7 @@ help() { echo echo -e "\n${bold}Sonos <$device> lists Menu:${reset}" echo -e " ${greenbold}1) Favourite radio stations:${reset} lists the favourite radio stations" - echo -e " ${greenbold}2) Favourites:${reset} lists all Sonos favourites" echo + echo -e " ${greenbold}2) Favourites:${reset} lists all Sonos favourites" echo echo -e " ${greenbold}3) Queue:${reset} list the tracks in the queue" echo -e " ${greenbold}4) Remove from queue:${reset} remove tracks from the queue. Track numbers start from 1. (single integers, sequences ('4,7,3'), ranges ('5-10')" @@ -893,7 +897,7 @@ play_local_m3u() { echo -e "\n${underline}$m3u:${reset}" pls=$(cat "$pl_file") echo -e "\n$pls\n" - #sonos "$loc" "$device" play_m3u "$fp" pi + sonos "$loc" "$device" play_m3u "$fp" pi else echo -e "File ${bold}$m3u${reset} doesn't exist!" fi @@ -1271,20 +1275,19 @@ make_playlist() { search_artist_from_library() { echo - fzf_bin=0 + #fzf_bin=0 if [ $fzf_bin -eq 1 ]; then fzf_music_folder_args=( --border --exact + --header="ENTER for select artist; ESC to quit" + --prompt="Search artist in library > " ) art=$(sonos "$loc" "$device" list_artists | tail -n+4 | fzf "${fzf_music_folder_args[@]}") - fi - echo "$art" - - if [ -z "$art" ]; then + elif [ -z "$art" ]; then art=$(sonos "$loc" "$device" list_artists | tail -n+4) while : @@ -1301,65 +1304,66 @@ search_artist_from_library() { do read -e -p "Choose index of artist or q to re-search: " research + [ "$research" == "q" ] && break if [ "$research" != "q" ] && [ -n "$research" ]; then art=$(echo "$x" | grep -E ^[[:blank:]]+"$research:") [ -n "$art" ] && break 2 - else break fi done fi done fi + if [ -n "$art" ]; then + + artiste=$(echo "$art" | awk -F":" '{print $2}' | xargs -0) - artiste=$(echo "$art" | awk -F":" '{print $2}' | xargs -0) - #index=$(echo "$art" | awk -F":" '{print $1}' | xargs) - - if [ $fzf_bin -eq 1 ]; then + if [ $fzf_bin -eq 1 ]; then - fzf_music_folder_args=( - --border - --exact - ) + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select album; ESC for a new search" + --prompt="Search album from $artiste in library > " + ) - l_alb=$(sonos "$loc" "$device" list_albums | tail -n+4 | grep -i "$artiste" | fzf "${fzf_music_folder_args[@]}") - fi + l_alb=$(sonos "$loc" "$device" list_albums | tail -n+4 | grep -i "$artiste" | fzf "${fzf_music_folder_args[@]}") + echo "$l_alb" # 788: Album: The Suburbs | Artist: Arcade Fire + #fi - if [ -z "$l_alb" ]; then - l_alb=$(sonos "$loc" "$device" list_albums | tail -n+4 | grep -i "$artiste") + elif [ -z "$l_alb" ]; then + l_alb=$(sonos "$loc" "$device" list_albums | tail -n+4 | grep -i "$artiste") - echo -e "\n${underline}Albums from $artiste:${reset}" - echo -e "$l_alb\n" - if [ -n "$l_alb" ]; then - while : - do - read -e -p "Choose index of album or (q) to quit: " research + echo -e "\n${underline}Albums from $artiste:${reset}" + echo -e "$l_alb\n" + if [ -n "$l_alb" ]; then + while : + do + read -e -p "Choose index of album or (q) to quit: " research - if [ "$research" != "q" ]; then - alb=$(echo "$l_alb" | grep -E ^[[:blank:]]+"$research:") + if [ "$research" != "q" ]; then + l_alb=$(echo "$l_alb" | grep -E ^[[:blank:]]+"$research:") - [ -n "$alb" ] && break - else break - fi - done - else echo -e "No albums from ${bold}$artiste${reset} found !" - fi - else - alb="$l_alb" - fi + [ -n "$l_alb" ] && break + else break + fi + done + else echo -e "No albums from ${bold}$artiste${reset} found !" + fi + fi - if [ -n "$alb" ]; then - artiste=$(echo "$alb" | awk -F":" '{print $4}' | awk -F"|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') - album=$(echo "$alb" | awk -F":" '{print $3}' | awk -F"|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') # xargs: unterminated quote - #index=$(echo "$alb" | awk -F":" '{print $1}' | xargs) - - echo -e "\nAdding ${bold}$album${reset} from ${bold}$artiste${reset} to queue and playing..." + if [ -n "$l_alb" ]; then + artiste=$(echo "$l_alb" | awk -F":" '{print $4}' | awk -F"|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') + album=$(echo "$l_alb" | awk -F":" '{print $3}' | awk -F"|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') # xargs: unterminated quote + #index=$(echo "$alb" | awk -F":" '{print $1}' | xargs) + + echo -e "\nAdding ${bold}$album${reset} from ${bold}$artiste${reset} to queue and playing..." - #list_queue + w=$(sonos $loc $device queue_album "$album" first : $device play_from_queue) # ajoute en pos 1 et joue + _tia "$album" + fi - w=$(sonos $loc $device queue_album "$album" first : $device play_from_queue) # ajoute en pos 1 et joue - _tia "$album" fi } @@ -1410,6 +1414,7 @@ search_album_from_library() { done fi + #sonos "$loc" "$device" queue_search_result_number $track first : $device play_from_queue > /dev/null if [ -n "$alb" ]; then artiste=$(echo "$alb" | awk -F":" '{print $4}' | awk -F"|" '{print $1}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//') @@ -1420,7 +1425,7 @@ search_album_from_library() { #list_queue - w=$(sonos $loc $device queue_album "$album" first : $device play_from_queue) # ajoute en pos 1 et joue + w=$(sonos $loc $device queue_album "$album" first : $device play_from_queue) # ajoute en pos 1 et joue _tia "$album" fi @@ -1571,6 +1576,8 @@ search_tracks_from_youtube() { } + + # Search track in library -> add to queue -> play it search_tracks_from_library() { @@ -1586,7 +1593,7 @@ search_tracks_from_library() { nb=$(echo -n "$tracks" | grep -c '^') if [ "$nb" -gt 0 ]; then - + if [ $fzf_bin -eq 1 ]; then fzf_music_folder_args=( @@ -1945,7 +1952,7 @@ soco_lists() { echo -e " 3) ${bgd}Q${reset}ueue " " | " " 13) D${bgd}e${reset}lete playlists " " | " echo -e " 4) Re${bgd}m${reset}ove from queue " " | " " 14) ${bgd}L${reset}ists tracks in all Sonos Playlists " " | " echo -e " 5) ${bgd}C${reset}lear queue " " | " " 15) Ad${bgd}d${reset} a Sonos playlist to queue " " | " - echo -e " 6) " " | " " 16) Remove a trac${bgd}k${reset} from a Sonos playlist" " | " + echo -e " 6) Pla${bgd}y${reset} from queue " " | " " 16) Remove a trac${bgd}k${reset} from a Sonos playlist" " | " echo -e " 7) List ${bgd}a${reset}rtists " " | " " 17) " " | " echo -e " 8) List al${bgd}b${reset}ums " " | " " 18) " " | " echo -e " 9) " " | " " 19) " " | " @@ -1961,6 +1968,7 @@ soco_lists() { 3|q|Q) list_queue;; 4|m|M) remove_from_queue;; 5|c|C) clear_queue;; + 6|y|Y) play_queue;; 7|a|A) list_artists;; 8|b|B) list_albums;; 11|p|P) create_playlist;; @@ -1977,49 +1985,177 @@ soco_lists() { } -# Favourite radio stations +# List and play Favourite radio stations (Tune-In) favourite_radio_stations() { - echo -e "\n${bold} Favourite radio stations... ${reset}" - s=$(sonos "$loc" "$device" favourite_radio_stations) - echo -e "\n $s \n" - read -p "< Press Enter>" + echo -e "\n${bold} Favourite radio stations (Tune-In)... ${reset}" + + if [ $fzf_bin -eq 1 ]; then + + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select radio; ESC to quit" + --prompt="Choose a radio: " + ) + + rad=$(sonos "$loc" "$device" favourite_radio_stations | awk NF | fzf "${fzf_music_folder_args[@]}") + + else + + r=$(sonos "$loc" "$device" favourite_radio_stations | awk NF) + + echo -e "$r\n" + + while : + do + read -e -p "Choose a radio station or (q) to quit: " choose + + [ "$choose" == "q" ] && break; + if [ "$choose" != "q" ] && [ -n "$choose" ]; then + if _is_int "$choose"; then + rad=$(echo "$r" | grep -E ^[[:blank:]]+"$choose:") + [ -n "$rad" ] && break + fi + fi + done + fi + + if [ -n "$rad" ]; then + no_radio=$(awk -F":" '{print $1}' <<< "$rad") + _trim no_radio + radio=$(awk -F":" '{print $2}' <<< "$rad") + _trim radio + + echo -e "\nPlaying ${bold}$radio${reset} ..." + sonos "$loc" "$device" play_fav_radio_station_no "$no_radio" + fi + + sleep 0.5 } -# Favourites +# List and play Sonos Favourites list_favs() { - echo -e "\n${bold} Favourites... ${reset}" - f=$(sonos "$loc" "$device" list_favs) - echo -e "\n $f \n" - read -p "< Press Enter>" + echo -e "\n${bold} Sonos Favourites... ${reset}" + #fzf_bin=0 + if [ $fzf_bin -eq 1 ]; then + + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select favourite; ESC to quit" + --prompt="Choose a Sonos favourite: " + ) + + fav=$(sonos "$loc" "$device" list_favs | awk NF | fzf "${fzf_music_folder_args[@]}") + + else + + f=$(sonos "$loc" "$device" list_favs | awk NF) + + echo -e "$f\n" + + while : + do + read -e -p "Choose a Sonos favourite or (q) to quit: " choose + + [ "$choose" == "q" ] && break; + if [ "$choose" != "q" ] && [ -n "$choose" ]; then + if _is_int "$choose"; then + fav=$(echo "$f" | grep -E ^[[:blank:]]+"$choose:") + [ -n "$fav" ] && break + fi + fi + done + fi + + if [ -n "$fav" ]; then + no_favourite=$(awk -F":" '{print $1}' <<< "$fav") + _trim no_favourite + favourite=$(awk -F":" '{print $2}' <<< "$fav") + _trim favourite + + echo -e "\nPlaying ${bold}$favourite${reset} ..." + sonos "$loc" "$device" play_favourite_number "$no_favourite" 2>/dev/null + + if [ $? -gt 0 ]; then echo -e "Podcast are not supported !"; fi + fi + + sleep 0.5 } # Queue list_queue() { echo -e "\n${bold} Queue... ${reset}" q=$(sonos "$loc" "$device" list_queue) - q=$(echo "$q" | head -n75) - echo -e "\n $q \n" - read -p "< Press Enter>" + #q=$(echo "$q" | head -n75) + #echo -e "\n $q \n" + fzf_bin=0 + if [ $fzf_bin -eq 1 ]; then + + fzf_queue_args=( + --border + --exact + --height 60% + --header="ENTER or ESC to quit" + --prompt="List of tracks in queue: " + ) + + t=$(echo "$q" | awk NF | fzf "${fzf_queue_args[@]}") + + else + #q=$(echo "$q" | more) + echo -e "\nList of tracks in queue: (using )" + echo -e "$q \n" | more + #read -p "< Press Enter>" + fi } # Remove from queue remove_from_queue() { echo -e "\n${bold} Remove from queue... ${reset}" - - l=$(sonos "$loc" "$device" queue_length) - if [ $l -ne 0 ]; then - while : - do - sonos "$loc" "$device" list_queue + + tracks= + if [ $fzf_bin -eq 1 ]; then + + fzf_queue_args=( + --border + --exact + --multi + --height 60% + --header="TAB for select track; ENTER to remove; ESC to quit" + --prompt="Select tracks to remove: " + ) - read -p "Enter track to remove [3][4,7,3][5-10][1,3-6,10] or [q] to quit: " track - if [[ "$track" == "q" || "$track" == "Q" ]]; then break; fi - sonos "$loc" "$device" remove_from_queue $track - done + t=$(sonos "$loc" "$device" list_queue | awk NF | fzf "${fzf_queue_args[@]}") + tracks=$(echo "$t" | awk -F":" '{print $1}' | awk '{$1=$1;print}' | sort -n | tr '\n' ',' | sed 's/.$//') + else - echo -e "\n${red}Queue is empty !${reset}" - fi - sleep 2 + + l=$(sonos "$loc" "$device" queue_length) + if [ $l -ne 0 ]; then + while : + do + sonos "$loc" "$device" list_queue + + read -p "Enter tracks to remove [3][4,7,3][5-10][1,3-6,10] or [q] to quit: " enter + [[ "$enter" =~ ^[qQ] ]] && break + if [[ "$enter" =~ ^[[:digit:]]+([,-][[:digit:]]+)*$ ]]; then + tracks="$enter" + #[ -n "$tracks" ] && break + break + fi + done + else + echo -e "\n${red}Queue is empty !${reset}" + fi + fi + + if [ -n "$tracks" ]; then + echo -e "Removing tracks $tracks..." + sonos "$loc" "$device" remove_from_queue $tracks + fi + + sleep 0.5 } # Clear queue @@ -2031,6 +2167,69 @@ clear_queue() { sleep 1.5 } +# Play queue +play_queue() { + echo -e "\n${bold} Play queue... ${reset}" + q=$(sonos "$loc" "$device" list_queue) + #q=$(cat queue.txt | tail -n +2 ) + + #q_length=$(sonos "$loc" "$device" queue_length) + + fzf_bin=0 + + if [ -n "$q" ]; then + + if [ $fzf_bin -eq 1 ]; then + + q=$(echo -e "last_added: last_added\n random: random\n last: last\n current: current\n$q") + + fzf_music_folder_args=( + --border + --exact + --header="ENTER for select track; ESC for a new search" + --prompt="Choose index of queue file: " + ) + queue=$(echo "$q" | fzf "${fzf_music_folder_args[@]}") + pos_queue=$(echo "$queue" | awk -F":" '{print $1}') + + else + #q=$(echo "$q" | head -n75) + echo -e "\n $q \n" + + while : + do + echo -e "Choose index of queue file or" + echo -e " - (a) to last added: " + echo -e " - (c) to play current: " + echo -e " - (l) to play last: " + echo -e " - (r) to play random: " + echo -e " - (q) to quit: " + read -e -p "> " research + + [ "$research" == "a" ] && pos_queue="last_added" && break + [ "$research" == "c" ] && pos_queue="current" && break + [ "$research" == "l" ] && pos_queue="last" && break + [ "$research" == "r" ] && pos_queue="random" && break + if [ "$research" != "q" ] && [ -n "$research" ]; then + queue=$(echo "$q" | grep -E ^[[:blank:]]+"$research:") + pos_queue=$(echo "$queue" | awk -F":" '{print $1}') + [ -n "$queue" ] && break + else break + fi + done + + fi + + echo "$queue" + echo "$pos_queue" + + # sonos "$loc" "$device" play_from_queue "$pos_queue" + else + echo "Queue is empty !" + fi + read -p "< Press Enter>" + } + # List Artists list_artists() { echo -e "\n${bold} List artists... ${reset}" @@ -2055,7 +2254,7 @@ create_playlist() { sonos "$loc" "$device" create_playlist "$name" } -#list_playlists +# List the Sonos playlists list_playlists() { echo -e "\n${bold} List Sonos playlist... ${reset}" l=$(sonos "$loc" "$device" list_playlists) @@ -2063,7 +2262,7 @@ list_playlists() { read -p "< Press Enter>" } -#delete_playlist +# Delete a Sonos playlist delete_playlist() { echo -e "\n${bold} Delete Sonos playlist... ${reset}" @@ -2073,7 +2272,7 @@ delete_playlist() { read -p "Enter playlist to delete or [q] to quit: " pll if [[ "$pll" == "q" || "$pll" == "Q" ]]; then break; fi - sonos "$loc" "$device" delete_playlist $pll + sonos "$loc" "$device" delete_playlist "$pll" # !!! BUG !!! done } @@ -2433,7 +2632,6 @@ move_alarms() { done sleep 1 - # read -p "< Press Enter>" } copy_alarms() { @@ -2885,7 +3083,7 @@ all() { echo -e " 2) ${bgd}S${reset}witch Status Light ON " " | " echo -e " 3) ${bgd}M${reset}ute ON " " | " echo -e " 4) M${bgd}u${reset}te OFF " " | " - echo -e " 5) ${bgd}S${reset}top all device " " | " + echo -e " 5) ${bgd}S${reset}top all devices " " | " echo -e " 6) " " | " echo -e " 7) " " | " echo -e " 8) " " | " @@ -2987,13 +3185,13 @@ all_mute_off() { list_functions=$(declare -F | awk '{print $NF}' | sort | grep -E -v "^_") -help_functions(){ +help_functions() { echo -e "${bold}List of functions:${reset}" echo "$list_functions" | column #echo "$list_functions" > list_functions.txt } -cli_help(){ +cli_help() { echo -e "${bold}Help soco-cli-gui:${reset}" echo echo "-f Display list of functions"