scripts/kodi.controller.sh

377 lines
11 KiB
Bash
Raw Permalink Normal View History

2022-05-25 10:11:25 +02:00
#!/bin/sh
#
# Purpose {{{
# This script will try to control Kodi with kodi-send command
# 1. Start Kodi if not already running.
# 2. Send user command to Kodi running instance.
#
# In Kodi, pause|play|toggle = TOGGLE ! 😑
# So for a real PAUSE, some extra tests are required :
# * Request the API (with curl) to check if a playlist is active.
# * Request the API to get the media speed.
# * Exit if the media is already paused (speed = 0).
#
# 2022-07-04
2022-05-25 10:11:25 +02:00
# }}}
# Vars {{{
PROGNAME=$(basename "${0}"); readonly PROGNAME
PROGDIR=$(readlink -m $(dirname "${0}")); readonly PROGDIR
ARGS="${*}"; readonly ARGS
readonly NBARGS="${#}"
[ -z "${DEBUG}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG
## Default values for some vars
readonly USER_MULTIMEDIA_COMMAND_DEFAULT="toggle"
readonly KODI_PROC_REGEXP="kodi.bin"
readonly KODI_HOST_DEFAULT="127.0.0.1"
2022-07-04 17:35:22 +02:00
readonly KODI_PORT_DEFAULT="8080"
2022-05-25 10:11:25 +02:00
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat <<- HELP
usage: $PROGNAME [-c|-d|-h]
Manage Kodi player with some commands.
EXAMPLES:
- Starts playing current playlist
${PROGNAME} --command start
- Start Kodi if not already running
${PROGNAME}
2022-07-04 10:37:07 +02:00
- Stop current current media
${PROGNAME} --command stop
- Send default action (${USER_MULTIMEDIA_COMMAND_DEFAULT}) to default Kodi instance
2022-05-25 10:11:25 +02:00
${PROGNAME}
- Toggle current status on remote host (default : ${KODI_HOST_DEFAULT})
${PROGNAME} --host 192.168.1.33 --command toggle
2022-05-25 10:11:25 +02:00
OPTIONS:
-c,--command
Send a command to running Kodi. Available commands :
* toggle, play
* pause (real one thanks to the API and curl!)
2022-07-04 10:37:07 +02:00
* stop
2022-05-25 10:11:25 +02:00
* next
* previous
* random, party, partymode
-h,--host
Set the Kodi host to manage.
2022-07-04 17:35:22 +02:00
-p,--port
Set the Kodi API's port to use.
2022-05-25 10:11:25 +02:00
-d,--debug
Enable debug messages.
--help
2022-05-25 10:11:25 +02:00
Print this help message.
HELP
}
# }}}
debug_message() { # {{{
local_debug_message="${1}"
## Print message if DEBUG is enable (=0)
[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG ${PROGNAME}: ${local_debug_message}"
unset local_debug_message
return 0
}
# }}}
error_message() { # {{{
local_error_message="${1}"
local_error_code="${2}"
## Print message
printf '%b\n' "ERROR ${PROGNAME}: ${RED}${local_error_message}${RESET}"
exit "${local_error_code:=66}"
}
# }}}
define_vars() { # {{{
## If KODI_HOST wasn't defined (argument) {{{
if [ -z "${KODI_HOST}" ]; then
## Use default value
readonly KODI_HOST="${KODI_HOST_DEFAULT}"
fi
## }}}
2022-07-04 17:35:22 +02:00
## If KODI_PORT wasn't defined (argument) {{{
if [ -z "${KODI_PORT}" ]; then
## Use default value
readonly KODI_PORT="${KODI_PORT_DEFAULT}"
fi
## }}}
2022-05-25 10:11:25 +02:00
## If USER_MULTIMEDIA_COMMAND wasn't defined (argument) {{{
if [ -z "${USER_MULTIMEDIA_COMMAND}" ]; then
## Use default value
readonly USER_MULTIMEDIA_COMMAND="${USER_MULTIMEDIA_COMMAND_DEFAULT}"
fi
## }}}
## Translate user command to Kodi action {{{
case "${USER_MULTIMEDIA_COMMAND}" in
2022-07-05 09:12:15 +02:00
toggle|play|pause ) ## Toggle current play
2022-05-25 10:11:25 +02:00
KODI_ACTION="PlayerControl(play)"
;;
2022-07-04 10:37:07 +02:00
stop ) ## Stop current play
KODI_ACTION="PlayerControl(stop)"
;;
2022-05-25 10:11:25 +02:00
next ) ## Next element in the playlist
KODI_ACTION="PlayerControl(next)"
;;
previous ) ## Next element in the playlist
KODI_ACTION="PlayerControl(previous)"
;;
random|party|partymode ) ## Start random music
KODI_ACTION="PlayerControl(partymode)"
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid Kodi command: ${USER_MULTIMEDIA_COMMAND}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
## }}}
}
# }}}
is_proc_absent() { # {{{
2022-05-25 10:11:25 +02:00
local_proc_pattern="${1}"
## Proc is absent by default
return_proc_absent="0"
local_count_proc_pattern="$(pgrep -f -- "${local_proc_pattern}" | wc -l)"
case "${local_count_proc_pattern}" in
0 ) ## No procs related to this pattern are running
return_proc_absent="0"
;;
* ) ## At least one proc seems running
return_proc_absent="1"
;;
esac
## Simple debug message to valid current variables
debug_message "is_proc_absent \
procs running (with the pattern: ${RED}${local_proc_pattern}${COLOR_DEBUG}) on the current host: ${RED}${local_count_proc_pattern}${COLOR_DEBUG}."
return "${return_proc_absent}"
}
# }}}
get_current_media_type() { # {{{
debug_message "get_current_media_type \
2022-07-05 09:12:15 +02:00
Run a request to ${KODI_HOST}:${KODI_PORT} API."
KODI_CURRENT_MEDIA_TYPE=$(curl -s -X POST http://"${KODI_HOST}:${KODI_PORT}"/jsonrpc -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"Player.GetActivePlayers","id":0}' | sed -n 's/.*"type":"\(.*\)".*/\1/p')
}
# }}}
is_audio_paused() { # {{{
## Media is playing by default
return_is_audio_paused="1"
debug_message "is_audio_paused \
Run a request to ${KODI_HOST}:${KODI_PORT} API to get status of audio media."
KODI_CURRENT_AUDIO_SPEED=$(curl -s -X POST http://"${KODI_HOST}:${KODI_PORT}"/jsonrpc -H 'Content-Type: application/json' --data '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": { "playerid": 0, "properties": [ "speed" ] }, "id": "AudioGetItem" }' | sed -n 's/.*"speed":\(.\).*/\1/p')
case "${KODI_CURRENT_AUDIO_SPEED}" in
0 ) ## Media is paused
debug_message "is_audio_paused \
The current media is paused (speed: ${RED}${KODI_CURRENT_MEDIA_TYPE}${COLOR_DEBUG})."
return_is_audio_paused="0"
;;
1 ) ## Media is playing
debug_message "is_audio_paused \
The current media is playing (speed: ${RED}${KODI_CURRENT_MEDIA_TYPE}${COLOR_DEBUG})."
return_is_audio_paused="1"
;;
* ) ## Error getting current media speed
error_message "Error with media speed (${KODI_CURRENT_AUDIO_SPEED})." 1
;;
esac
return "${return_is_audio_paused}"
}
# }}}
2022-07-05 09:12:15 +02:00
is_video_paused() { # {{{
## Media is playing by default
return_is_video_paused="1"
debug_message "is_video_paused \
Run a request to ${KODI_HOST}:${KODI_PORT} API to get status of video media."
KODI_CURRENT_VIDEO_SPEED=$(curl -s -X POST http://"${KODI_HOST}:${KODI_PORT}"/jsonrpc -H 'Content-Type: application/json' --data '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": { "playerid": 1, "properties": [ "speed" ] }, "id": "VideoGetItem" }' | sed -n 's/.*"speed":\(.\).*/\1/p')
case "${KODI_CURRENT_VIDEO_SPEED}" in
0 ) ## Media is paused
debug_message "is_video_paused \
The current video is paused (speed: ${RED}${KODI_CURRENT_MEDIA_TYPE}${COLOR_DEBUG})."
return_is_video_paused="0"
;;
1 ) ## Media is playing
debug_message "is_video_paused \
The current video is playing (speed: ${RED}${KODI_CURRENT_MEDIA_TYPE}${COLOR_DEBUG})."
return_is_video_paused="1"
;;
* ) ## Error getting current media speed
error_message "Error with media speed (${KODI_CURRENT_VIDEO_SPEED})." 1
;;
esac
return "${return_is_video_paused}"
}
# }}}
2022-05-25 10:11:25 +02:00
main() { # {{{
## Define all vars
define_vars
## For localhost
if [ "${KODI_HOST}" = "${KODI_HOST_DEFAULT}" ]; then
## If kodi is not running {{{
### AND Start it
### AND exit 0
is_proc_absent "${KODI_PROC_REGEXP}" \
&& debug_message "Start a new Kodi instance." \
&& kodi \
&& exit 0
## }}}
fi
2022-05-25 10:11:25 +02:00
## If the media should be paused {{{
if [ "${USER_MULTIMEDIA_COMMAND}" = "pause" ]; then
## Get current playlist type
get_current_media_type
case "${KODI_CURRENT_MEDIA_TYPE}" in
audio ) ## Manage audio media
is_audio_paused \
&& debug_message "${RED}audio${COLOR_DEBUG} media is already paused, no more action is required." \
&& exit 0
;;
video ) ## Manage video media
2022-07-05 09:12:15 +02:00
is_video_paused \
&& debug_message "${RED}video${COLOR_DEBUG} media is already paused, no more action is required." \
&& exit 0
;;
* ) ## Unknown media type or no media at all
debug_message "Unknown media type ->${RED}${KODI_CURRENT_MEDIA_TYPE}${COLOR_DEBUG}<- or no media is playing (if empty), exit."
exit 0
;;
esac
fi
## }}}
2022-05-25 10:11:25 +02:00
## Send Kodi action to running instance {{{
### And exit
debug_message "Send ${RED}${USER_MULTIMEDIA_COMMAND}${COLOR_DEBUG} (${RED}${KODI_ACTION}${COLOR_DEBUG}) action to running Kodi instance (on ${RED}${KODI_HOST}${COLOR_DEBUG} host)." \
&& kodi-send --host="${KODI_HOST}" --action="${KODI_ACTION}" > /dev/null \
2022-05-25 10:11:25 +02:00
&& exit 0
## }}}
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to argument management
if [ ! "${NBARGS}" -eq "0" ]; then
manage_arg="0"
## If the first argument is not an option
if ! printf -- '%s' "${1}" | grep -q -E -- "^-+";
then
## Print help message and exit
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' "${1}" | grep -q -E -- "^-+"; do
case "${1}" in
-c|--command ) ## User command
### Move to the next argument
shift
### Define var
USER_MULTIMEDIA_COMMAND="${1}"
;;
-d|--debug ) ## debug
DEBUG=0
;;
-h|--host ) ## Kodi host to manage
### Move to the next argument
shift
### Define var
KODI_HOST="${1}"
;;
2022-07-04 17:35:22 +02:00
-p|--port ) ## Kodi API port
### Move to the next argument
shift
### Define var
KODI_PORT="${1}"
;;
--help ) ## help
2022-05-25 10:11:25 +02:00
usage
## Exit after help informations
exit 0
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
debug_message "Arguments management \
${RED}${1}${COLOR_DEBUG} option|command managed."
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
done
debug_message "Arguments management \
${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
debug_message "Arguments management \
No arguments/options to manage."
fi
# }}}
main
exit 255