Haiku scripting

It’s a riff on a famous quotation from a science fiction story: I Have No Mouth & I Must Scream Quotes by Harlan Ellison

1 Like

I don’t use Tor but I regularly have problems accessing it as well. Not sure if they use agressive blocking themselves or there is some legal blocking at DNS level. Running an unmoderated open file sharing service without any authentication/accounts seems like a bad idea anyway and a sure way to have illegal activities using your service.

After writing my post,I saw that they even explain the blocking of Tor in their FAQ: https://git.0x0.st/mia/0x0/wiki/FAQ#why-is-the-instance-at-0x0-st-not-reachable-from-anonymizing-networks-is-this-some-kind-of-honeypot
Again,I understand why they probably don’t want uploads from Tor,but there is no legit reason for also preventing accessing existing content over Tor.
Oxo also explains their moderation pretty good,so it isn’t unmoderated after all.
It’s nice that services like that exist from a user perspective,but running them seems risky for the admin and it’s only getting worse with laws everywhere getting more strict about everything.

[code]

#!/bin/sh
if [[ -z “$@” ]] ; then
echo “error: missing argument” >&2
exit 1
fi

input_file=“$1”

if [ ! -f “${input_file}” ] ; then
echo “error: no such file” >&2
exit 1
fi

output_file=“${input_file%.*}.fixed.mp4”

ffmpeg -i “${input_file}” -c copy “${output_file}”

[/code]

this solves an issues with medias produced with Haiku, especially using BSC, not recognized by other applications, a corrupted header? I dunno, but this way it works

1 Like

AutoUpdate

Checks for updates, and if found launches SoftwareUpdater

A Super useful script I have in my ~/config/boot/launch folder:

#!bash

while true;do
  TEST_OUT=$(yes no | pkgman update  2> /dev/null);

  case "$TEST_OUT" in 

	*Continue*)
		SoftwareUpdater
	;;
  esac

sleep 1h	 # How often to check for updates: 1h= every hour, "1d"=1 day etc..

done
1 Like

You can put the below function in your profile to simplify the addition of an icon to a script / program:

seticon()
{
if [ $# -ne 2 ]; then
echo "Usage: seticon <icon-file> <executable>"
return 1
fi
addattr -f "$1" -t icon BEOS:ICON "$2"
}

Example :

seticon /boot/home/Desktop/game.hvif /boot/scripts/QSoloCards

2 Likes

You may like SoftwareUpdater check.

2 Likes
app_name="SoftwareUpdater"
app_path="$(finddir B_APPS_DIRECTORY)/${app_name}"

# initialize array
desklink_args=()

if ! desklink --list | grep -q -- "${app_name}"; then
	if [[ "$(${app_name} check | grep count)" ]] ; then
		desklink_args+=("cmd=Remove Replicant:desklink --remove=${app_name}")
		desklink "${desklink_args[@]}" "${app_path}"
	else
		notify --group "${app_name}" --messageID "${app_name}" --title "${app_name}" --icon "${app_path}" "There are no updates"
		exit 1
	fi
fi

it places a SU replicant as a reminder of available updates, if one wants to apply them later

“SoftwareUpdater check” doesn’t launch SoftwareUpdater if it finds updates, only launches a notification. With my script, pkgman runs in the background once an hour (or whatever you set it to..) to check for an update, and if it finds one, it will launch SoftwareUpdater. It will not install any updates until you click “Update now”

The notification is supposed to open the app if you click on it.

Anyway, I mentioned it just in case you didn’t know. I rediscovered it myself after reading your script. Of course use whatever best fits your needs.

2 Likes

The problem is that you may not have time to do it or you can be in middle of something if you automate the check. A reminder in Deskbar seems better than leaving the notification on the workspace in this case.

1 Like
#!/bin/bash

steps=4
# show_notification=1

script_name="$(basename "${0}")"
local_path="$(dirname ${0})"
[[ "${local_path}" == "." ]] && local_path="$(pwd)"
full_path="${local_path}/${script_name}"

fHelpUsage() {
	local help_usage="$(cat << EOF
usage:	${script_name} <0-100>
Options:
-d, --dim		cycle brightness in ${steps} steps
-h, --help		print this help
EOF
)"
	if [[ ${#} -ne 1 ]] ; then
		echo "${help_usage}"
		exit
	else
		echo "${help_usage}" >&2
		exit 1	
	fi
}

fCycleBrightness() {
	local current_brightness=$(screenmode -B | awk -v s=${steps} '{
	if ($2 !~ /inf/) {
		b = ($2 * 100)
		s = 100 / s
		b = int(b / s) * s
		b -= s
		if(!b) b = 100
	printf "%d", b
	}
}')
	[[ -z "${current_brightness}" ]] && return
	fSetBrightness ${current_brightness}
}

fSetBrightness() {
	local percent_value=${1}
	if (( percent_value < 0 || percent_value > 100 )) ; then
		echo "error:	out of range (0 to 100)" >&2
		exit 1
	fi
	local float_value
	float_value=$(awk -v p="${percent_value}" 'BEGIN{printf "%.2f", p/100}')
	screenmode -b "${float_value}" >/dev/null 2>&1
	if [[ -t 0 ]] ; then
		echo "${script_name}:	${percent_value}%"
	else
		(( ! show_notification )) && return
		notify --group "${script_name}" --title "Brightness"… --icon "${full_path}" --messageID "Brightness" "${percent_value}%"
	fi
}

fDeskLink() {
		if ! desklink --list | grep -q "${script_name}" ; then
			local desklink_args=()
			for ((i=1;i<=steps;i++)) ; do
				local brightness_item=$((100/steps*i))
				desklink_args+=("cmd=☀ ${brightness_item}% Brightness:${full_path} ${brightness_item}")
			done
			desklink_args+=("cmd=🛠 Open Screen Preferences:open application/x-vnd.Haiku-Screen")
			desklink_args+=("cmd=✖ Remove Replicant:desklink --remove=${script_name}")
			desklink "${desklink_args[@]}" "${full_path}"
		else
			fCycleBrightness
		fi

}

if [ ${#} -ne 1 ] ; then
	fDeskLink
else
	if [[ ${1} =~ [0-9]+ ]] ; then
		fSetBrightness ${1}
	else
		case ${1} in
		-h|--help)
			fHelpUsage
			;;
		-d|--dim)
			fCycleBrightness
			;;
		*)
			fHelpUsage 1
			;;
		esac
	fi
fi

this put a replicant in your deskbar to dim the light of your (supportrd) laptop screen in steps (4 by default, but you can change it), click on it to dim, right click to select the desired dim; it accepts direct arguments, <0-100> , or -d|–dim to dim

EDIT: I found that in beta 5 screenmode -B is not a valid option, so dimming would work only on nightlies

3 Likes

Thanks madmax

I didn’t know about that one either :grinning_face:

If I don’t know how to use hpkg and recipes, can I use script launcher

This is the bash version of my SuperMusicThingy. I was working on this quiet a lot until I ( with the help of AI) migrated it to c++

#!/usr/bin/env bash
#
#  Copy or link to prefered /bin directory
#  To Run open a terminal and type `music_thingy` 
#  or use keyboard shortcuts to pass argument
#  Examples "music_thingy https://ice2.somafm.com/secretagent-128-mp3" 
#  "music_thingy quit"  "/music_thingy shuffle"  "music_thingy favorites"



set -f
shopt -s nocasematch

# Do nothing if not executed from terminal and $1 does not exist
[[ ! -t 0 && ! "${1}" ]] && echo "Error: script must be executed from terminal, or passed with an argument e.g., music_thingy shuffle." &&  exit 1

# Check for version 4.1 or higher
if ! (( BASH_VERSINFO[0] > 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 1) )); then
    echo "This script requires Bash Version 4.1 or higher. Found version ${BASH_VERSION}."
    exit 1
fi


data="/tmp/music_thingy.data"
version="0.3.2"
player="mpv"

########################################
###### Stream qaulities  ###############
# low 32.pls
# high 64.pls
# highest 130.pls, 256.pls, 320.pls
# Default .pls includes 130.pls, 256.pls, 320.pls

### Default Stream Settings
default_qaulity=".pls"     # Highest 130 and above
exclude_quality1="32.pls"  # Low.
exclude_quality2="64.pls"  # High.
exclude_quality3="80.pls"  # Oddball bitrate.  There's just one and if not excluded makes the playlist go bonkers.
exclude_quality4="130.pls" # Highest. // excluded in default because it's alrady included in all <urls>.pls

########## Example setting for low 32.pls only 
# default_qaulity="32.pls"
# exclude_quality1="null.pls"
# exclude_quality2="null.pls"
# exclude_quality3="null.pls"
# exclude_quality4="null.pls"

########## Example setting for high 64.pls only
# default_qaulity="64.pls"
# exclude_quality1="null.pls"
# exclude_quality2="null.pls"
# exclude_quality3="null.pls"
# exclude_quality4="null.pls"

########## Example setting for highest 130.pls only // This works really well but ignores 256 and 320 bitrates.
# default_qaulity="130.pls"
# exclude_quality1="null.pls"
# exclude_quality2="null.pls"
# exclude_quality3="null.pls"
# exclude_quality4="null.pls"
#
########################################



OS_NAME="$(uname -s)"


# Create config file with some default values and an empty favorites file.
if [[ ! $config ]];then
	if [[ "${OS_NAME}" == haiku ]]; then
			notify="notify --title MusicThingy "
			ConfigDir="${HOME}/config/settings/music_thingy"
			ConfigName="music_thingy-${version}_config"
			[[ ! -d "$ConfigDir" ]] && mkdir "$ConfigDir"
			[[ ! -e "$ConfigDir/favorites" ]] && touch "$ConfigDir/favorites"
			[[ ! -e "$ConfigDir/${ConfigName}" ]] && touch "$ConfigDir/${ConfigName}"
			favs="$ConfigDir/favorites"
			config="$ConfigDir/${ConfigName}"
			if [[ ! -s "$config" ]];then
					declare -A _config=( 
										 [show_notify]="\"1\"" [show_listeners]="\"1\"" [show_volume]="\"1\"" 
										 [show_channels]="\"1\"" [show_favorites]="\"1\"" 
									   )
						for value in "${!_config[@]}"
							do
								echo "$value=${_config[$value]}" >> "$config"
							done
							unset _config
			fi
	fi

	if [[ "${OS_NAME}" == linux ]]; then
			notify="notify-send -a MusicThingy"
			ConfigDir="${HOME}/.config/music_thingy"
			ConfigName="music_thingy-${version}_config"
			[[ ! -d "$ConfigDir" ]] && mkdir -p "$ConfigDir"
			[[ ! -e "$ConfigDir/favorites" ]] && touch "$ConfigDir/favorites"
			[[ ! -e "$ConfigDir/${ConfigName}" ]] && touch "$ConfigDir/${ConfigName}"
			favs="$ConfigDir/favorites"
			config="$ConfigDir/${ConfigName}"
			if [[ ! -s "$config" ]];then
					declare -A _config=( 
										 [show_notify]="\"1\"" [show_listeners]="\"1\"" [show_volume]="\"1\""
									     [use_pactl_to_get_volume]="\"1\"" [show_channels]="\"1\"" [show_favorites]="\"1\""
									     
									   )
						for value in "${!_config[@]}"
							do
								echo "$value=${_config[$value]}" >> "$config"
							done
							unset _config
			fi

	fi
fi

source "$config"

# 
cleanup(){
	[[ -e "$data" ]] && source "$data" && kill -3 "$PID" && rm "$data"
}


vol() {

source "$config"

[[ -e "$data" ]] && source "$data"
if [[ "$show_volume" == 0 && ! "$PID" ]];then
	  	  return
fi
	  if [[ ${OS_NAME} == haiku ]]; then
  		  [[ "$REPLY" == + ]] && setvolume -i > /dev/null
  		  [[ "$REPLY" == - ]] && setvolume -d > /dev/null
  		  [[ "$REPLY" == m ]] && setvolume -m > /dev/null
  		  [[ "$REPLY" == u ]] && setvolume -u > /dev/null
  		  echo -e "  * $(setvolume)"


elif [[ "${OS_NAME}" == linux ]]; then

	if [[ "$use_pactl_to_get_volume" == 1 && "$show_volume" = 1 ]];then


		if [[ "$lastPlaying" ]];then

		 	while read -r line
		 	do
				if [[ "$line" =~ Sink\ Input\ #([0-9]+) ]]; then
					current_id="${BASH_REMATCH[1]}"
					elif [[ "$line" == *"media.name = \"$lastPlaying - mpv\""* ]];then
					sinkID="${current_id}"
				fi

				if [[ "$line" == *"Volume:"* ]];then
					line=($line)
					y="${line[11]}"
					soundlevel="${y//%/}"
				fi

			done < <(pactl list sink-inputs)
		fi
		 # inc_sound="$((soundlevel + 1))"
  		 # dec_sound="$((soundlevel - 1))"

		  [[ "$REPLY" == m ]] && pactl set-sink-input-mute $sinkID 1
		  [[ "$REPLY" == u ]] && pactl set-sink-input-mute $sinkID 0
  		  [[ "$REPLY" == + ]] && pactl set-sink-input-volume $sinkID $((soundlevel + 1))% && s=$((soundlevel + 1))%
  		  [[ "$REPLY" == - ]] && pactl set-sink-input-volume $sinkID $((soundlevel - 1))% && s=$((soundlevel - 1))%

  		  [[ -n "$soundlevel" ]] && echo -n "${BLUE}${info}  * Vol: ${soundlevel}%"


	fi

	if [[ "$use_pactl_to_get_volume" == 0 ]];then

	for l in "$(amixer get Master)"
		do
			 l=${l// /_}
 	         l=${l/_[/ }
 		 	 l=${l/]_/ }
  		 	 l=($l)
  		 	 s="${l[6]}"

  		 		#Fix for raspberry pi *** maybe outdated
 		 		[[ ${#s} -gt 3 ]] && s="${l[6]}"

  		  soundlevel="${s//%/}"
  		  #inc_sound="$((soundlevel + 1))"
  		  #dec_sound="$((soundlevel - 1))"

  		  [[ "$REPLY" == + ]] && amixer -q set Master $((soundlevel + 1))% && s=$((soundlevel + 1))%
  		  [[ "$REPLY" == - ]] && amixer -q set Master $((soundlevel - 1))% && s=$((soundlevel - 1))%
  		  [[ "$REPLY" == m ]] && amixer -q set Master mute
  		  [[ "$REPLY" == u ]] && amixer -q set Master unmute
		  [[ "${l[7]}" == "[off]" ]] && s=Muted
  		  echo -n "${BLUE}${info}  * Vol: ${s}"
	done
	fi
fi
}

# Added option to pass argument given to command line.
# Will Notify User if notify is set to 1
# Arguments accepted are quit, shuffle, favorites, add_favorite, del_favorite, inc_vol, dec_vol or a custom stream URL
# Works great with keyboard shortcuts or KDE-connect to play music_thingy in the backend.
# Examples "music_thingy https://ice2.somafm.com/secretagent-128-mp3" "music_thingy quit"  "music_thingy shuffle"  "music_thingy favorites"
if [[ "$1" ]];then

		[[ -e "$data" ]] && source "$data"

		if [[ "${1}" != @(quit|shuffle|favorites|del_favorite|add_favorite|inc_vol|dec_vol) ]];then
        	NOTERMINAL=1
        	REPLY=play
        	url="$1"
        fi

	    if [[ "${1}" == inc_vol ]]; then
        	 REPLY="+"
        	 vol
        	 exit
	  	fi

	    if [[ "${1}" == dec_vol ]]; then
        	 REPLY="-"
        	 vol
        	 exit
	  	fi

	    if [[ "${1}" == add_favorite ]]; then
 			 tmp="${url}" ### Repeat delete cmds so no duplicate entries
			 foo="$(< "$favs" )"
			 echo "${foo//"$tmp"}" | sed '/^$/d' > "$favs"
			 fav="${url}"
			 echo "$fav" >> "$favs"
			 if [[ "$show_notify" == 1 ]]; then
			   $notify "${fav//\\n */}
Added to favorites."
			 fi
   		 exit
		fi

		if [[ "${1}" == del_favorite ]]; then
			tmp="${url}"
			foo="$(< "$favs")"
			echo "${foo//"$tmp"}" | sed '/^$/d' > "$favs"
			if  [[ ! -s "$favs" && "$show_notify" == 1 ]];then
			 $notify "
Playlist is empty."
			 exit
			fi
			fav="${url}"

			if [[ "$show_notify" == 1 ]]; then
			 $notify "${fav//\\n */}
Deleted from favorites."
			fi
			fav="${url}"
         	exit
		fi

		if [[ "${1}" == favorites ]]; then
     	   cleanup
		   NOTERMINAL=1
     	   REPLY="f"
		fi

		if [[ "${1}" == shuffle ]]; then
       	   cleanup
		   NOTERMINAL=1
     	   REPLY=s     	   
		fi

		if [[ "${1}" == quit ]]; then
			   $notify "
Stopping Music Thingy."
        	cleanup
			exit 0
		fi
fi


getplaylist() {
    curl=$(curl -s -H 'Accept: application/json' https://somafm.com/channels.json \
    | jq -r --arg default_qaulity "${default_qaulity}" \
      --arg exclude_quality1 "${exclude_quality1}" \
      --arg exclude_quality2 "${exclude_quality2}" \
      --arg exclude_quality3 "${exclude_quality3}" \
      --arg exclude_quality4 "${exclude_quality4}" \
  '.. | select(
    (has("url") and (.url | contains($default_qaulity)) and 
     (.url | contains($exclude_quality1) | not) and 
     (.url | contains($exclude_quality2) | not) and 
     (.url | contains($exclude_quality3) | not) and
     (.url | contains($exclude_quality4) | not)) or
    has("description") or has("listeners") or has("id") or 
    has("genre") or has("title") or has("lastPlaying")
  )? 
  | "\(if .id != null then " [id]=\(.id | @sh)" else "" end) \(if .listeners != null then " [listeners]=\(.listeners | @sh)" else "" end) \(if .lastPlaying != null then " [lastPlaying]=\(.lastPlaying | @sh)" else "" end) \(if .title != null then " [title]=\(.title | @sh)" else "" end) \(if .description != null then " [description]=\(.description | @sh)" else "" end) \(if .genre != null then " [genre]=\(.genre | @sh)" else "" end) \(if .url != null then " [url]=\(.url | @sh)" else "" end)"')

		mapfile -t curl <<< "$curl"
		i=0
		channeltotal=0
		while [[ "$i" -le "${#curl[*]}" ]]
			do	
			    # The current jq script above outputs 1 line for the urls and another for everything else. To get channeltotal we filter out lines with [url]		
				[[ "${curl[$i]}" == *"[url]"* ]] && channeltotal="$channeltotal" && ((channeltotal++))
			((i++))
			done
			
		i=0
		cn=0  # This makes a total associative array up to the channel total	
		while [[ $i -le "${#curl[*]}" ]]
		 do			
		 	# Create associative arrays for each channel
		 	var="xplaylistdata_${cn}=(${curl[$i]}"
		 	((i++))
		 	var2="${curl[$i]}"
		 	# If findme is true we just need one associative array for it after making sure it matches one of the channels
		 	if [[ "$findme" && "$var2" == *"${findme}"* ]];then
		 	
		 	 [[ "$previous" ]] && var4="[previous]=\"${previous}\"" 
		 	 var2="[url]=\"${findme}\""
		 	 var="${var//xplaylistdata_/favorite}"
		 	 declare -A "${var//$cn/} ${var2} ${var4} [channeltotal]=\"${channeltotal}\")"	
		 	 
		 	  else
		 	    # If findme is not true, create the associative arrays here for all channels
		 	  	[[ -n "${curl[$i]}" ]] && declare -A "${var} ${var2} [channeltotal]=\"${channeltotal}\")" 	 
		 	  	
		 		# Debug the above line
		 		#[[ -n "${curl[$i]}" ]] && echo "declare -A \"${var} ${var2} [channeltotal]=\"${channeltotal}\"\")"
		 		# break or not to break !!		 	  	 	
		 	fi
		 			 
				# Make sure we stop iterating when channel total is reached	
		 	 [[ $cn -le $channeltotal ]] && ((cn++))
		  ((i++))		  
		 done	
		 				
							# Print out the channel list in a friendly format if "t" is pressed
							# REPLY is reassigned to "ta" to parse the function here inside getplaylist
		 					if [[ $REPLY == ta ]];then
								cn=0
								cp=1
								while [[ $cn -le $channeltotal ]];
								 do
								 		declare -n current_playlist="xplaylistdata_${cn}"
										#for value in "${!current_playlist[@]}"
											#do
												#echo "$cn ${BLUE}  * ${value}=\"${current_playlist[$value]}\""

											echo "${BLUE}  * $cp  ${current_playlist[description]} - ${current_playlist[url]}"
											#done
									((cn++))
									((cp++))
								done
								return

							fi
 

		 					# Create a shuffle variable
							shuf="$(shuf -i 0-${channeltotal} -n 1)"
							
							# This is need for associative arrays and using vars																					
							declare -n current_playlist="xplaylistdata_${shuf}"
							
							# See if a url already exists and if so make it a previous var when the data file is created
							[[ -e "$data" ]] && source "$data"	
							
							if [[ "${url}" ]];then
								echo "previous=\"${url}\"" > "$data"
								echo "version=\"${version}\"" >> "$data"
							else
								echo "version=\"${version}\"" > "$data"
							fi
							
							# Assign names to the array alements  
							id="${current_playlist[id]}"
							pl="${current_playlist[url]}"
							url="${current_playlist[url]}"
							description="${current_playlist[description]}"
							title="${current_playlist[title]}"
							genre="${current_playlist[genre]}"
							listeners="${current_playlist[listeners]}"
							lastPlaying="${current_playlist[lastPlaying]}"
							
							# Echo the names with elements to the data file
							echo "id=\"${id}\"" >> "$data"
							echo "url=\"${url}\"" >> "$data"
							echo "title=\"${title}\"" >> "$data"
							echo "description=\"${description}\"" >> "$data"														
							echo "genre=\"${genre}\"" >> "$data"														
							echo "listeners=\"${listeners}\"" >> "$data"														
							echo "lastPlaying=\"${lastPlaying}\"" >> "$data"
							echo "channeltotal=\"${channeltotal}\"" >> "$data"	
							
							# Create a new data file just for favorite mapping
							# This way we got all the info about the favorite and not use the url, which is only saved in the favorites file.
							if [[ $findme ]];then		
							echo "version=\"${version}\"" > "$data"					
							for value in "${!favorite[@]}"
							do
								echo "$value=\"${favorite[$value]}\"" >> "$data"
							done
							[[ -e "$data" ]] && source "$data"
							fi
																			
							# Source the data file once all the above is finished.
							[[ -e "$data" ]] && source "$data"
							

							
	
}
# Handy for debugging and watching the above functions work.
#getplaylist
#read -p ""
#exit
isinfavorite() {
	mapfile fv < "$favs"
	f=0
	while [[ "$f" -le "${#fv[*]}" ]]
		do
		    [[ "$url" && "${fv[$f]}" == *"${url}"* ]] && fip="[$(tput setaf 1)F$(tput setaf 3)a$(tput setaf 2)v$(tput setaf 6)o$(tput setaf 4)r$(tput setaf 5)i$(tput setaf 1)t$(tput setaf 3)e${BLUE}]"
	((f++))
	done
}

favoritesfull() {
	mapfile fv < "$favs"
	echo -en "${#fv[*]}"
}



body(){
	[[ -e "$data" ]] && source "$data"
	
	footer(){
		tput cup "$(tput lines)" 0
		echo -e "\\n${ORANGE}Interactive Music Thingy${BLUE}~ $:-)"
	}

	QUERYS(){

		mapfile x < "$config"
		var=0
		v=$((${#x[*]} - 1))

	while [[ $var -le $v ]]
		do
			if [[ $REPLY == $var ]];then
				echo -e "${RED}<Config>\\n ${BLUE}  * Press 0 thru ${v}${RED}"
				x=${x//\"/}
				name="${x[$var]}"
				c="${#name}"
				((c--)) && ((c--))
				value=${name[*]:$c}

				# Just a hack to change from 1 or 0	
				(( 0 == value )) && cv=1
				(( 1 == value )) && cv=0
			
					# just want 0s and 1s
					(( 3 == value )) && cv=3
					(( 4 == value )) && cv=4
					(( 5 == value )) && cv=5
					(( 6 == value )) && cv=6
					(( 7 == value )) && cv=7
					(( 8 == value )) && cv=8
					(( 4 == value )) && cv=4
					(( 9 == value )) && cv=9

				n1=${name%??}$value
				n2=${name%??}$cv

				mapfile x2 < "$config"
				var2=0
				v2=$((${#x2[*]} - 1))

					while [[ $var2 -le $v2 ]]
						do
							try=${x2[$var2]}
							try=${try//\"/}
							arr+=(${try/$n1/$n2})
							((var2++))

						done

						try2="${arr[*]}"
						try2="${try2//\"/}"
						echo -e "${try2// /\\n}" > "$config"

						source $config

						mapfile x3 < "$config"
						    	i=0
								ii=$((${#x3[*]} - 1))
								while [[ $i -le $ii ]]
									do
									echo -en "${BLUE}   * [${i}] ${BLUE}${x3[$i]}${RED}"
								((i++))
							done

							echo -e "${RED}</Config>${BLUE}"
							footer
				exit 0
			fi

			((var++))
	done

	}



	if [[ "${REPLY}" == h ]];then
		echo -e "${RED}<Help>"
		echo -e "${BLUE}   * ${RED} [s] ${BLUE} Shuffle All"
		echo -e "${BLUE}   * ${RED} [f] ${BLUE} Shuffle Favorites"
		echo -e "${BLUE}   * ${RED} [a] ${BLUE} Add Favorite"
		echo -e "${BLUE}   * ${RED} [d] ${BLUE} Delete Favorite"
		echo -e "${BLUE}   * ${RED} [p] ${BLUE} Previous Stream"
		echo -e "${BLUE}   * ${RED} [r] ${BLUE} Refresh Current Stream"
		echo -e "${BLUE}   * ${RED} [l] ${BLUE} List Favorites"
		echo -e "${BLUE}   * ${RED} [t] ${BLUE} Show Available Channels"
		echo -e "${BLUE}   * ${RED} [m] ${BLUE} Mute"
		echo -e "${BLUE}   * ${RED} [u] ${BLUE} Unmute"
		echo -e "${BLUE}   * ${RED} [+] ${BLUE} Vol Up"
		echo -e "${BLUE}   * ${RED} [-] ${BLUE} Vol Down"
		echo -e "${BLUE}   * ${RED} [h] ${BLUE} Help Menu"
		echo -e "${BLUE}   * ${RED} [c] ${BLUE} Config Manager"
		echo -e "${BLUE}   * ${RED} [q] ${BLUE} Quit and log out of Music Thingy"
		echo -e "${BLUE}   * ${RED} [k] ${BLUE} Stop playing"
		echo -e "${RED}</Help>${BLUE}"
		footer
 		return
	fi

	if [[ "$REPLY" == a ]];then
    	if [[ -s "$favs" ]];then ## make sure favorites is not empty
			tmpadd="${url}" ### Repeat the delete cmds so no duplicate entries
			foo=$(< "$favs")
			echo "${foo//"$tmpadd"}" | sed '/^$/d' > "$favs"
		fi
		tmpadd="${url}"
		fav="${url}"
		echo "$fav" >> "$favs"
		REPLY="af"

	fi

	if [[ "$REPLY" == l ]];then
		echo -e "${RED}<Favorites>${BLUE}"
		i="0"
		mapfile listfavorites <<< $(<"$favs")
		while [[ $i -le "${#listfavorites[*]}" ]]
			do
				[[ "${listfavorites[$i]}" ]] && echo -en "   * ${listfavorites[$i]}" 
	   			((i++))
			done
		echo -e "${RED}</Favorites>${BLUE}"
		footer
		return
	fi

 	 if [[ "$REPLY" == d ]];then
    	[[ "$url" ]] && tmpdel="${url}"
		[[ "${favorite}" ]] && tmpdel="${favorite}"
	
		foo=$(< "$favs")
		[[ ! -s "$favs" ]] && REPLY="fe"
		[[ -s "$favs" ]] && REPLY="df" && echo "${foo//"$tmpdel"}" | sed '/^$/d' > "$favs"
		REPLY="df"

	fi

	if [[ "$REPLY" == k ]];then
		cleanup
		shortmsg="Stopping Music Thingy"
		REPLY=showmsg
	fi

	if [[ "${REPLY}" == c ]];then
		mapfile x < "$config"
			i=0
	    	ii="$((${#x[*]} - 1))"
	    	echo -e "${RED}<Config>\\n ${BLUE}  * Press 0 thru ${ii}${RED}"
			while [[ "$i" -le "$ii" ]]
			 do
			    x="${x[$i]}"
		    
				echo -ne "${BLUE}   * ${RED}${BLUE}[${i}] ${x//\"/}"
				((i++))
			done
		echo -e "${RED}</Config>${BLUE}"

		footer
	 return
	fi

	if [[ "$REPLY" == t ]];then
		echo "${RED}<Playlist>"
		REPLY=ta
		getplaylist
		echo -n "${RED}</Playlist>"
		footer
		return
	fi

	if [[ "$REPLY" == df ]];then

			 if [[ -s "$favs" ]];then
				[[ $REPLY == df ]] && shortmsg="Deleted Favorite:"
				#player_start
			fi
			 if [[ ! -s "$favs" ]];then
			 shortmsg="Favorites Empty"
			 fi
	fi

	if [[ "$REPLY" == f ]];then
			 if [[ ! -s "$favs" ]];then
			 shortmsg="Favorites Empty ::"
			 fi
			 if [[ -s "$favs" ]];then
		 	
				mapfile -t playlist < "$favs"
				nu="0-$((${#playlist[*]}-1))"
				shuffle="$(shuf -i $nu -n 1)"
			
				shortmsg="Shuffling Favorites"
				cleanup
				
				if [[ "${url}" ]];then
				 previous="$url"
				fi

				url="${playlist[$shuffle]}"
				
				findme="${url}"
			
				getplaylist
	        	player_start
			fi
	fi

	if [[ "$REPLY" == af ]];then
			if [[ "${url}" ]];then
			   [[ "$REPLY" == af ]] && shortmsg="Added Favorite:"
		    fi
	fi

	if [[ "$REPLY" == p ]];then

			if [[ "${previous}" ]];then		
				cleanup
				shortmsg="Loading Previous"
				if [[ "$previous" ]];then
				findme="${previous}"			
				getplaylist
				fi
				player_start
		    fi
	fi

	if [[ "$REPLY" == r ]];then
			if [[ "${url}" ]];then
				cleanup
				shortmsg="Refreshing"
				findme="${url}"
				getplaylist
				player_start
			fi
	fi

	if [[ "$REPLY" == s ]];then
			cleanup
			shortmsg="Shuffling Channels"
			getplaylist
			player_start
	fi

	QUERYS

	#dofortune() {
    	# Added a tput function for fortune
    	# This helps long fortunes, albeit it's rather quick to display.
	#	mapfile df <<< "$(fortune)"
	#	i="0"
	#	c="11"
	#	while [[ "$i" -le "${#df[@]}" ]]
	#		do
	#			echo -en "$(tput cup $c 8) ${df[$i]}"
	#			((i++))
	#			((c++))
	#		done
	#}

	msg() {
		#[[ ! "$shortmsg" ]] && shortmsg="$(tput cup 11 8)$(dofortune)"
		echo "$(printf '\033[H\033[2J')$(logo)
		$(tput cup 11 14)${shortmsg}
		$([[ "$urlx" ]] && echo "$(tput cup 11 14)Gathering data for: ${url}")
		$([[ "$urlx" ]] && echo "$(tput cup 13 14)Please wait...${title}")
		$([[ "$tmpdel" && -s "$favs" ]] && echo "$(tput cup 11 31) ${title}")
		$([[ "$tmpadd" ]] && echo "$(tput cup 11 29) ${title}")
		$(footer)"
	}

	if [[ -n "$REPLY" && "$REPLY" = @(a|d|f|s|af|df|fe|p|r|showmsg) ]];then
		while read -r -t 3
			do
				return
					# Really don't wont to see the pv data, just the custom msg
					# Try to hide it with tput 0 0 and font black
			done | pv -N "$(msg)$(tput cup 0 0)$(tput setaf 0)" -F "%N"
	fi

    # close the file descriptor
	#exec {fd}<&-
	
    # source config again
	source "$config"
	[[ -e "$data" ]] && source "$data"
	#Add +1 for our connection
	((listeners++))
	isinfavorite
	[[ "$lastPlaying"     						   ]] &&  echo -e "   * $lastPlaying"
	[[ "$title"    		   						   ]] &&  echo -e "   * $title ${fip}"
	[[ "$description"	  						   ]] &&  echo -e "   * $description"
	[[ "$show_listeners" == 1 && "$listeners"  && "$listeners" != 1 ]] &&  echo -e "   * Listeners: $listeners"
	[[ "$show_channels" == 1  && "$channeltotal"   ]] &&  echo -e "   * Channels: $channeltotal"
	[[ "$show_favorites" == 1 					   ]] &&  echo -e "   * Favorites: $(favoritesfull)"
#	[[ "$url"     								   ]] &&  echo -e "   * Current: $url"
#	[[ "$previous" 								   ]] &&  echo -e "   * Previous: $previous"		
	[[ "$show_volume" == 1 				   ]] &&  echo -e " $(vol)"

	[[ "$REPLY" == start && ! "$url" ]] &&  echo -e "   * Press \"s\" to start."
	[[ "$REPLY" == start && ! "$url" ]] &&  echo -e "   * Press \"h\" for help."
#   [[ -e "$data" ]] && echo "$(<$data)"
	footer
#End Body
}

player_start() { 	
	        
	        (echo "PID=\"${BASHPID}\"" >> "$data"
        	source "$config"
        	#[[ "$debug" == 1 ]] && return 0
        	$player --really-quiet ${url})&> /dev/null &
        		    	
		       }

#mkfifo(){
#	fifo="$(mktemp -u)"
#	mkfifo "$fifo"
#	exec {fd}<>"$fifo"
#	rm "$fifo"
#		}
	
main() {
	## Make a tmp file descriptor Thanks chatgpt!
	#mkfifo

	#Clear the terminal
	tput clear

    tput civis
	# Make the terminal black
	printf "\033[30m\033[0m"

	# Create logo and use tput to set the dimensions
		logo() {
			echo "$(tput cup 5 19)${BLUE}Interactive Music Thingy"
			echo "$(tput cup 6 17)${BLUE}https://github.com/ablyssx74"
			echo "$(tput cup 7 11)${BLUE}[S]huffle/[Q]uit   Vol +/-   [H]elp Menu"
			   }

	logo

	# Set the body location with tput
	echo "$(tput cup 10 0)${BLUE}"
	
	body
	
}
	[[ ! "$NOTERMINAL" ]] && trap cleanup EXIT
	if [[ "$REPLY" == s && "$NOTERMINAL" ]];then
		getplaylist
		player_start
		if [[ "$show_notify" == 1 ]];then $notify "Shuffling
$title
$lastPlaying"
fi
		elif [[ "$REPLY" == f && "$NOTERMINAL" ]];then
			 if [[ -s "$favs" ]];then
				mapfile -t playlist < "$favs"
				nu="0-$((${#playlist[*]}-1))"
				shuffle="$(shuf -i $nu -n 1)"
				cleanup
				url="${playlist[$shuffle]}"
				findme="${url}"
				getplaylist
        		player_start
					if [[ "$show_notify" == 1 ]];then
$notify "Shuffling Favorites
$title
$lastPlaying"
					fi
			 fi
	
		elif [[ "$REPLY" == play && "$NOTERMINAL" ]];then
				cleanup
				$notify "Playing ${url}"
        		player_start


	else
	
	# Create while loop for the main function
	# Also set some tput colors and check if mpv, pv and jq are installed for the script to work correctly
	while true
		do		
		[[ ! "$REPLY" ]] && REPLY="start" 
		 BLUE="$(tput setaf 12)"
		 RED="$(tput setaf 9)"
		 ORANGE="$(tput setaf 9)"
		 testplayer=($(which ${player%}))
		 pv="pv"
		 testpv=($(which ${pv%}))
		 jq="jq"		
		 testjq=($(which ${jq%}))
		 if [[ "${OS_NAME}" == haiku ]]; then
			notify="notify"
			notify=($(which ${notify%}))
				[[ -z "${notify[0]}" ]] &&  echo -e "${ORANGE}notify${RED} not installed. ${BLUE}Please install it with your package manager. :-)" && break

		elif [[ "${OS_NAME}" == linux ]]; then
			notify="notify-send"
			notify=($(which ${notify%}))
				[[ -z "${notify[0]}" ]] && echo -e "${ORANGE}notify-send${RED} not installed. ${BLUE}Please install it with your package manager. :-)" && break

		fi
		[[ -z "${testplayer[0]}" ]] && echo -e "${ORANGE}${player}${RED} not installed. ${BLUE}Please install it with your package manager.  :-)" && break
		[[ -z "${testpv[0]}" ]] && echo -e "${ORANGE}pv${RED} not installed. ${BLUE}Please install it with your package manager. :-)" && break
		[[ -z "${testjq[0]}" ]] && echo -e "${ORANGE}jq${RED} not installed. ${BLUE}Please install it with your package manager. :-)" && break

		if [[ "$REPLY" != @(start|fe|af|df|ta|s|f|a|d|k|p|r|l|t|m|u|+|-|h|c|q|k|0|1|2|3|4|5|6|7|8|9) ]]; then
    		unset REPLY
		fi
						
		if [[ "${REPLY}" == q ]];then
			    tput cup "$(tput lines)" 0
				echo -e "${ORANGE}Interactive Music Thingy${BLUE}~ $:-) Logging out!"
				cleanup
		 	    tput sgr0
		 	    # Need a little buffer to cleanup correctly
		 	    while read -r -t 1 
					do						
						return
					done		 	    
		 	    break		        
		  else
		  	 read -r -s -p "$(main)" -n 1
		fi			
	done
  fi

This is similar to portmaster way of porting game I like this, I feel like haiku could benefit a lot from .sh launcher being full integrated along side recipe and hpkg

2 Likes