Compare commits

..

10 commits

Author SHA1 Message Date
zerf58
d187c37f03 dont run find_or_open when sourcing 2025-07-02 09:02:46 -07:00
fred
61b06082d0 update readme 2025-06-18 19:38:40 -07:00
fred
cfbdca17d8 README 2025-06-18 13:26:52 -07:00
zerf58
1ad241d6e1 add freetube 2025-06-18 10:10:22 -07:00
zerf58
c467b52cfe more shellcheck 2025-06-18 09:54:29 -07:00
fred
d7accc8c69 shellcheck tweaks 2025-06-18 09:47:16 -07:00
zerf58
fa119a8d4f allow running find_or_open as standalone 2025-06-18 09:29:04 -07:00
htpc
847ecd0214 stop this from blocking site specific actions 2025-06-13 16:38:13 -07:00
zerf58
3a60983070 better log handling 2025-06-13 16:25:23 -07:00
zerf58
ad9315f166 fix init 2025-06-13 16:12:54 -07:00
11 changed files with 163 additions and 644 deletions

2
.gitignore vendored
View file

@ -1,3 +1,3 @@
/secrets.env
/tv_state
/debug

94
README.md Normal file
View file

@ -0,0 +1,94 @@
## Overview:
This project is designed to control a home theater PC (HTPC) with a pepper jobs remote control.
The buttons on the remote control are hard coded to common windows shortcuts, depending on the desktop environment some of these will work as generic shortcuts in linux out of the box, but this project aims to expand their functionality and provide custom commands based on the application that has focus.
For example: when firefox is open to the site youtube.com, pressing the search button will type "/" to move focus to the search bar at the top of the screen and type "control+a" to select all then type "BackSpace" to clear any text in it so you can flip the remote and start typing; In kodi the same button will open a kodi search menu by executing: kodi-send --action="VideoLibrary.Search".
Another goal of this project is to simplify modifications by allowing easy customization of button actions within applications. To add a new program, simply create a new .sh file in /apps with the name returned by get_active_window.sh and define methods within this file with the commands to run when the buttons are pressed.
### Parts list:
Beelink Ser5 Mini PC
<img src="https://kagi.com/proxy/Beelink-SER5.jpg?c=Sry64v3AQdbrqAk1MK4X_IpvYWn_9QPQIHyBL3hdg54PbzBSdWDk3bhAaEiq5NccxPtgmHKAh0Wl7bXyQ9OoBWb-qtRbj6TyTVJ4gtlogBgnigcspYPiYT6yA6ZJZ8PdXo3RkxoGm4TmahnNk3LK8w%3D%3D" width="500px">
<a target="_blank" rel="noopener noreferrer" href="https://www.pepper-jobs.com/products/w10-gyro-smart-remote">Pepper Jobs Remote</a>
<img src="https://www.pepper-jobs.com/cdn/shop/files/img_01_03ca82de-33a6-4ec7-b523-a32e7a952a0e_540x.jpg?v=1614291123" width="500px">
<a target="_blank" rel="noopener noreferrer" href="https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter">Pulse eight usb-hdmi-cec-adapter</a>
<img src="https://www.pulse-eight.com/generated-assets/products/0000381.jpeg" width="500px"><br><br>
The computer could be anything, the hardware requirements are what you want to do with it.
The cec adapter is optional, but allows the computer to turn the tv on and off via software which is mapped to the power button on the remote. It is also not necessary if running on a raspberry pi since cec is built into the hardware.
### OS:
I am running EndeavourOS on the computer, but this could be any linux distro with the following software installed.
### Software:
#### required:
Xorg<br>
xfce4<br>
xdotool<br>
wmctrl<br>
#### optional:
libcec # for cec controls<br>
kodi<br>
freetube<br>
spotify<br>
\# other apps etc...<br>
### How it works:
1. The button combos that are hardcoded on the remote are mapped as keyboard shortcuts in xfce to run the buttons.sh script with the button name as $1 when pressed
2. buttons.sh runs get_active_window.sh to find what program is active
3. It then looks for this program in the scripts in the app folder and initializes it if it finds it
4. next it will execute the method with the pressed button name if it finds it in the file it just sourced and exit
5. If it does not find the button it will look for the button in apps/default_commands.sh and run it if it finds it
### Notes:
find_or_open.sh will check running programs, if what it is looking for is running already it will give it focus, if it is not it will launch the program.
When possible I am using commands that will preform the desired actions in the specified software. If that is not possible instead I simulate key presses using xdotool to use keyboard shortcuts provided by the application.
For an example of further segementing button presses in an app, ie firefox has different methods when on youtube.com vs pbs.org, see: get_active_window.sh and apps/firefox.sh
Debug output goes to both the debug file and stdout when the buttons.sh script is run. This way troubleshooting can happen both on the command line when manually running buttons.sh and also in the debug file when testing buttons on the remote.
There is an init.sh script that will copy the xfce4 shortcuts to the .config folder as well as a kodi config file. It also disables the XF86PowerOff button in Xorg. Without this the power button caused the remote to lock up until the system was rebooted even if XF86PowerOff was set to do nothing in xfce. After this the power button can be repurposed to run the cec.sh script to turn the tv on and off.
Some buttons are left as globals:<br>
close is alt+f4,>br?
tab is tab. Additionally, in xfce config, cycle_windows_key is remapped to just tab instead of standard alt + tab, so this button can be used to cycle through open programs.
### Button Names:
\# if no comment the name matches the word(s) on the remote<br>
sleep, # power<br>
main,<br>
notification,<br>
search,<br>
settings,<br>
action_center,<br>
file_explorer,<br>
desktop,<br>
refresh,<br>
browser,<br>
task_manager,<br>
move_up,<br>
play,<br>
forward,<br>
back,<br>
fast_forward,<br>
rewind,<br>
split_up, # bottom row left<br>
split_down, # bottom row left middle<br>
split_left, # bottom row right middle<br>
split_right, # bottom row right<br>
#### Future Plans:
In the future I plan to migrate this project to Nixos

View file

@ -27,16 +27,16 @@ all(){
### top buttons
"main" | "notification" | "settings" | "task_manager" | "search")
echo "no default action assigned to $1"
echo "button all_$1 is no-op"
;;
"browser")
helper_find_or_open firefox
find_or_open firefox
;;
"file_explorer")
helper_find_or_open kodi
find_or_open kodi
;;
"action_center")
helper_find_or_open steam
find_or_open steam
;;
### arrow buttons
@ -56,7 +56,7 @@ all(){
echo "sucessful test"
;;
*)
echo "unexpected action: ${1-}"
echo "button $1 not found"
;;
esac

View file

@ -1,9 +1,10 @@
firefox(){
debug "no op for ff on this website"
}
#firefox(){
# debug "no op for ff on this website"
#}
firefox_youtube(){
# fullscreen
split_up(){
sleep .2
xdotool key f
}
search(){
@ -11,6 +12,7 @@ firefox_youtube(){
search
}
play(){
sleep .2
xdotool key k
}
# kiosk

29
apps/freetube.sh Normal file
View file

@ -0,0 +1,29 @@
# fullscreen
split_up(){
sleep .2
xdotool key f
}
search(){
sleep .2
xdotool key alt+d
sleep .1
xdotool key BackSpace
}
play(){
sleep .2
xdotool key k
}
# TOD) setup profiles
# go to yt.com in shared container
desktop(){
echo "placeholder"
}
# open hh container
back(){
echo "placeholder"
}
# open fr container
forward(){
echo "placeholder"
}

View file

@ -10,10 +10,12 @@ kodi(){
kodi-send --action="SkipPrevious"
}
split_up(){
xdotool_helper "key p"
sleep .2
xdotool key p
}
move_up(){
xdotool_helper "key o"
sleep .2
xdotool key o
}
search(){
kodi-send --action="VideoLibrary.Search"

View file

@ -1,30 +1,24 @@
#!/bin/bash
export ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
button=$1
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export ROOT="$ROOT"
button="$1"
debug(){
debug=$ROOT/debug
echo $1
echo $1>>$debug
debug="$ROOT"/debug
# todo:
# this keeps the log file at 30 lines but breaks the pipe when doing "tail -F debug"
tail -n 30 "$debug" > debug.tmp && mv debug.tmp "$debug"
echo "$1"
echo "$1">>"$debug"
}
# debugging
#tail -n 30 "$debug" > tmp && cp tmp "$debug"
active=$(bash $ROOT/get_active_window.sh)
active=$(bash "$ROOT"/get_active_window.sh)
debug ""
debug "$(date +%s)"
debug "active: $active"
debug "button: $button"
# source the app folder
#APPS="$(pwd)/apps"
#if [ -d "$APPS" ]; then
# for file in "$APPS"/*; do
# if [ -f "$file" ]; then
# . "$file"
# fi
# done
#fi
. $ROOT/find_or_open.sh
. $ROOT/apps/default_commands.sh
if [ -f "$ROOT/apps/${active%%_*}.sh" ]; then
@ -35,18 +29,18 @@ else
fi
### find and run $1
if [[ $(type -t $active) == function ]]; then
if [[ $(type -t "$active") == function ]]; then
debug "found $active methods"
$active
"$active"
else
debug "no $button method found in $active"
fi
if [[ $(type -t $button) == function ]]; then
if [[ $(type -t "$button") == function ]]; then
debug "found $button"
$1
"$1"
else
debug "program specific method not found calling all $button"
all $1
all "$1"
fi

2
cec.sh
View file

@ -13,7 +13,7 @@ tv_off() {
if [[ -z "$1" ]]; then
if grep -q off ~/scripts/PJ/tv_state; then
tv_on
elif grep -q on ~/scripts/PJ/tv_state; then
else
tv_off
fi
elif [[ $1 = "on" ]]; then

607
debug
View file

@ -1,607 +0,0 @@
/home/htpc/scripts/PJ
1749852338
test firefox firefox_youtube
desktop
/home/htpc/scripts/PJ
1749852353
test firefox firefox_youtube
desktop
/home/htpc/scripts/PJ
1749852354
test firefox firefox_youtube
desktop
/home/htpc/scripts/PJ
1749852462
desktop
/home/htpc/scripts/PJ
1749852550
test firefox firefox_youtube
/home/htpc/scripts/PJ
1749852604
test firefox firefox_youtube
/home/htpc/scripts/PJ
1749852608
test firefox firefox_youtube
/home/htpc/scripts/PJ
1749852609
test firefox firefox_youtube
desktop
/home/htpc/scripts/PJ
1749852611
test firefox firefox_youtube
search
/home/htpc/scripts/PJ
1749852615
test firefox firefox_youtube
desktop
/home/htpc/scripts/PJ
1749852624
test firefox firefox_youtube
desktop
1749852696
test firefox firefox_youtube
11111
1749852703
test firefox firefox_youtube
11111
home
1749852705
test firefox firefox_youtube
11111
desktop
1749852759
firefox_youtube
11111
desktop
1749852765
firefox_youtube
11111
search
1749852818
firefox_youtube
home
1749852819
firefox_youtube
home
1749852824
firefox_youtube
home
1749852846
firefox_youtube
desktop
1749852886
firefox_youtube
desktop
1749852907
firefox_youtube
desktop
1749852927
firefox_youtube
desktop
1749852946
firefox_youtube
desktop
1749853013
firefox_youtube
desktop
1749853048
firefox_youtube
desktop
1749853051
firefox_youtube
desktop
1749853057
firefox_youtube
back
1749853060
firefox_youtube
forward
1749853064
firefox_youtube
desktop
1749853085
firefox
desktop
1749853087
firefox
desktop
1749853090
firefox
desktop
1749853097
firefox
desktop
1749853117
xfdesktop
browser
1749853119
firefox
browser
1749853121
firefox
browser
1749853122
firefox
desktop
1749853149
firefox_youtube
desktop
1749853154
firefox
desktop
1749853182
firefox
desktop
1749853198
firefox
desktop
1749853200
firefox
desktop
1749853254
firefox
file_explorer
1749853482
kodi
desktop
target: kodi
no desktop method found in kodi
program specific method not found calling all desktop
1749853484
kodi
desktop
target: kodi
no desktop method found in kodi
program specific method not found calling all desktop
1749853552
kodi
desktop
target: kodi
no desktop method found in kodi
program specific method not found calling all desktop
1749853600
kodi
desktop
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853630
kodi
desktop
kodi sourced
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853765
active: kodi
button: desktop
kodi sourced
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853786
active: kodi
button: desktop
kodi sourced
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853788
active: kodi
button: desktop
kodi sourced
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853791
active: kodi
button: desktop
kodi sourced
active:
no desktop method found in kodi
program specific method not found calling all desktop
1749853891
active: kodi
button: desktop
kodi sourced
found kodi methods
found desktop
1749853980
active: xfdesktop
button: search
xfdesktop sourced
found xfdesktop methods
found search
1749853994
active: xfdesktop
button: forward
xfdesktop sourced
found xfdesktop methods
program specific method not found calling all forward
1749854004
active: xfdesktop
button: fast_forward
xfdesktop sourced
found xfdesktop methods
program specific method not found calling all fast_forward
1749854038
active: xfdesktop
button: forward
xfdesktop sourced
found xfdesktop methods
found forward
1749854040
active: xfdesktop
button: forward
xfdesktop sourced
found xfdesktop methods
found forward
1749854196
active: vncviewer
button: desktop
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktop
1749854224
active: vncviewer
button: desktop
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktop
1749854233
active: vncviewer
button: desktop
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktop
no op
1749854234
active: vncviewer
button: desktop
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktop
no op
1749854261
active: vncviewer
button: desktop
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktop
no op
1749854293
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854295
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854297
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854299
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854301
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854302
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854306
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854309
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854311
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854312
active: vncviewer
button: split_down
vncviewer sourced
found vncviewer methods
program specific method not found calling all split_down
1749854320
active: vncviewer
button: split_up
vncviewer sourced
found vncviewer methods
found split_up
1749854461
active: vncviewer
button: desktopp
vncviewer sourced
found vncviewer methods
program specific method not found calling all desktopp
1749855450
active: xfdesktop
button: browser
xfdesktop sourced
found xfdesktop methods
program specific method not found calling all browser
1749855455
active: firefox_youtube
button: desktop
firefox_youtube sourced
found firefox_youtube methods
found desktop
1749855458
active: firefox_youtube
button: desktop
firefox_youtube sourced
found firefox_youtube methods
found desktop
1749855464
active: firefox_youtube
button: desktop
firefox_youtube sourced
found firefox_youtube methods
found desktop
1749855472
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855479
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855481
active: firefox_youtube
button: forward
firefox_youtube sourced
found firefox_youtube methods
found forward
1749855572
active: firefox_youtube
button: file_explorer
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all file_explorer
1749855576
active: kodi
button: browser
kodi sourced
found kodi methods
program specific method not found calling all browser
1749855578
active: firefox_youtube
button: file_explorer
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all file_explorer
1749855579
active: kodi
button: file_explorer
kodi sourced
found kodi methods
found file_explorer
1749855580
active: kodi
button: file_explorer
kodi sourced
found kodi methods
found file_explorer
1749855581
active: kodi
button: browser
kodi sourced
found kodi methods
program specific method not found calling all browser
1749855582
active: firefox_youtube
button: browser
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all browser
1749855583
active: firefox_youtube
button: browser
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all browser
1749855584
active: firefox_youtube
button: browser
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all browser
1749855584
active: firefox_youtube
button: browser
firefox_youtube sourced
found firefox_youtube methods
program specific method not found calling all browser
1749855587
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855588
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855589
active: firefox_youtube
button: desktop
firefox_youtube sourced
found firefox_youtube methods
found desktop
1749855717
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855720
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855728
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855737
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855755
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855764
active: firefox_youtube
button: forward
firefox_youtube sourced
found firefox_youtube methods
found forward
1749855775
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855779
active: firefox_youtube
button: desktop
firefox_youtube sourced
found firefox_youtube methods
found desktop
1749855783
active: firefox_youtube
button: back
firefox_youtube sourced
found firefox_youtube methods
found back
1749855786
active: firefox_youtube
button: forward
firefox_youtube sourced
found firefox_youtube methods
found forward
1749855804
active: firefox_youtube
button: search
firefox_youtube sourced
found firefox_youtube methods
found search
1749855811
active: firefox_youtube
button: search
firefox_youtube sourced
found firefox_youtube methods
found search
1749856037
active: firefox
button: desktop
firefox sourced
found firefox methods
no op for ff on this website
program specific method not found calling all desktop
no op

View file

@ -1,5 +1,5 @@
#!/bin/bash
helper_find_or_open(){
find_or_open(){
windows=$(wmctrl -l)
if [[ "${windows,,}" == *"$1"* ]]; then
xdotool windowactivate "$(wmctrl -l | grep -i "$1" | cut -d " " -f 1)"
@ -9,3 +9,8 @@ helper_find_or_open(){
echo "opening $1"
fi
}
# this can either be sourced by buttons.sh or run as a standalone script
if [ "${BASH_SOURCE[0]}" = "$0" ] && [[ -n $1 ]]; then
find_or_open "$1"
fi

View file

@ -7,8 +7,8 @@ rm /home/htpc/.kodi/userdata/keymaps/keyboard.xml
ln /home/htpc/scripts/PJ/xml/keyboard.xml /home/htpc/.kodi/userdata/keymaps/keyboard.xml
rm /home/htpc/.kodi/userdata/advancedsettings.xml
export $(grep -v '^#' /home/htpc/scripts/PJ/xml/secrets.env | xargs)
envsubst < /home/htpc/scripts/PJ/advancedsettings.xml > /home/htpc/.kodi/userdata/advancedsettings.xml
export $(grep -v '^#' /home/htpc/scripts/PJ/secrets.env | xargs)
envsubst < /home/htpc/scripts/PJ/xml/advancedsettings.xml > /home/htpc/.kodi/userdata/advancedsettings.xml
# disable the power button on PJ, ignore if already commented
# this usually doesn't revert, but occasionally does after updating system