Skip to content

Instantly share code, notes, and snippets.

@Misko-2083
Created January 19, 2020 23:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Misko-2083/2b2fff6fbdadaf88319ff3f4196d02fa to your computer and use it in GitHub Desktop.
Save Misko-2083/2b2fff6fbdadaf88319ff3f4196d02fa to your computer and use it in GitHub Desktop.
alarm script
#!/bin/bash
# Fancy alarm Misko_2083 @ 2020
# Requires: at, xfce4, wmctrl, xdotool, yad 0.42 (with html dialog), mpv
#########################
# Begin User Interface #
#########################
# JavaScript, HTML and CSS
YURI="$(cat << EOF
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--CSS for the page-->
<style>
.body, .html {
overflow-y: hidden;
cursor: default;
background-color: #CECECE;
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
top: 180%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 1s;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
#jsalarmclock{
font-weight: bold;
font-size: 14px;
}
#jsalarmclock div{
margin-bottom: 0.8em;
}
#jsalarmclock div.leftcolumn{
float: left;
width: 150px;
font-size: 14px;
clear: left;
}
#jsalarmclock span{
margin-right: 10px;
}
#jsalarmclock input[type=number]{
width: 50px;
}
p {
font-weight: bold;
font-size: 11px;
}
.btn {
border: 2px solid black;
background-color: white;
color: black;
padding: 8px 16px;
position: sticky;
font-size: 12px;
cursor: default;
}
/* Green */
.bar {
border-color: #4CAF50;
color: green;
text-decoration: none;
}
.bar:hover {
background-color: #4CAF50;
color: white;
}
/* Blue */
.bl {
border-color: #2196F3;
color: dodgerblue;
text-decoration: none;
}
.bl:hover {
background: #2196F3;
color: white;
text-decoration: none;
}
/* Orange */
.bltop {
border-color: #ff9800;
color: orange;
text-decoration: none;
}
.bltop:hover {
background: #ff9800;
color: white;
text-decoration: none;
}
/* Red */
.restart{
border-color: #f44336;
color: red;
text-decoration: none;
}
.restart:hover {
background: #f44336;
color: white;
}
/* Gray */
.default {
border-color: #000000;
color: black;
text-decoration: none;
}
.default:hover {
background: #000000;
color: white;
text-decoration: none;
}
.title {
font-size: 10px
cursor: default;
}
</style>
<!--Script to prevent right click menu-->
<script type="text/javascript">
if (document.addEventListener) { // IE >= 9; other browsers
document.addEventListener('contextmenu', function(e) {
//here you do nothing
e.preventDefault();
}, false);
} else { // IE < 9
document.attachEvent('oncontextmenu', function() {
alert("You've tried to open context menu");
window.event.returnValue = false;
});
}
</script>
<script type="text/javascript">
/***********************************************
* JavaScript Alarm Clock- by JavaScript Kit (www.javascriptkit.com)
* This notice must stay intact for usage
* Visit JavaScript Kit at http://www.javascriptkit.com/ for this script and 100s more
***********************************************/
/* Modified for my needs Misko_2083 */
var jsalarm={
padfield:function(f){
return (f<10)? "0"+f : f
},
showcurrenttime:function(){
var dateobj=new Date()
var ct=this.padfield(dateobj.getHours())+":"+this.padfield(dateobj.getMinutes())+":"+this.padfield(dateobj.getSeconds())
this.ctref.innerHTML=ct
this.ctref.setAttribute("title", ct)
},
init:function(){
var dateobj=new Date()
this.ctref=document.getElementById("jsalarm_ct")
this.submitref=document.getElementById("submitbutton")
this.submitref.onclick=function(){
jsalarm.setalarm()
//this.value="Alarm Set"
this.disabled=false
return false
}
var selections=document.getElementsByTagName("select")
this.hourselect=selections[0]
this.minuteselect=selections[1]
for (var i=0; i<60; i++){
if (i<24) //If still within range of hours field: 0-23
this.hourselect[i]=new Option(this.padfield(i), this.padfield(i), false, dateobj.getHours()==i)
this.minuteselect[i]=new Option(this.padfield(i), this.padfield(i), false, dateobj.getMinutes()+1==i)
}
jsalarm.showcurrenttime()
jsalarm.timer=setInterval(function(){jsalarm.showcurrenttime()}, 1000)
},
info:function(a) {
var h = document.createElement("p");
var filename = String(a).replace(/^.*[\\\/]/, '');
var t = document.createTextNode("Alarm "+filename);
h.appendChild(t);
document.body.appendChild(h);
h.setAttribute("id", "info");
},
dom:function(a){
// DOM 2 Events
var dispatchMouseEvent = function(target, var_args) {
var e = document.createEvent("MouseEvents");
// If you need clientX, clientY, etc., you can call
// initMouseEvent instead of initEvent
e.initEvent.apply(e, Array.prototype.slice.call(arguments, 1));
target.dispatchEvent(e);
};
dispatchMouseEvent(a, 'mouseover', true, true);
dispatchMouseEvent(a, 'mousedown', true, true);
dispatchMouseEvent(a, 'click', true, true);
dispatchMouseEvent(a, 'mouseup', true, true);
},
setalarm:function(){
this.hourwake=this.hourselect.options[this.hourselect.selectedIndex].value
this.minutewake=this.minuteselect.options[this.minuteselect.selectedIndex].value
var a = document.createElement('a');
var linkText = document.createTextNode("Go");
a.appendChild(linkText);
a.title = "fake link";
a.href = this.hourselect.options[this.hourselect.selectedIndex].value+":"+this.minuteselect.options[this.minuteselect.selectedIndex].value;
jsalarm.dom(a)
jsalarm.info(a)
a.href = "repeat@"+document.getElementById("repeat").value;
jsalarm.dom(a)
if(document.getElementById("forever").checked == true) {
a.href = "repeat@"+document.getElementById("forever").value;
jsalarm.dom(a)
}
a.href = "command@"+document.getElementById("command").value;
jsalarm.dom(a)
//a.parentNode.removeChild(linkText);
//this.hourselect.disabled=true
//this.minuteselect.disabled=true
}
}
</script>
</head>
<body class="body">
<!--left-->
<div
style="-moz-user-select: none; -webkit-user-select: none; -ms-user-select:none; user-select:none;-o-user-select:none;position:absolute;left:0;"
unselectable="on"
onselectstart="return false;"
onmousedown="return false;">
<div class="tooltip">
<a href="move" class="btn default">#</a>
<span class="tooltiptext">Move</span>
</div>
<text class="title"> Alarm </text>
</div>
<!--right-->
<div
style="-moz-user-select: none; -webkit-user-select: none; -ms-user-select:none; user-select:none;-o-user-select:none;position:absolute;right:0;"
unselectable="on"
onselectstart="return false;"
onmousedown="return false;">
<!--Here you define window button links and text-->
<div class="tooltip">
<a href="resize" class="btn bar">+</a>
<span class="tooltiptext">Resize</span>
</div>
<div class="tooltip">
<a href="minimize" class="btn bltop">_</a>
<span class="tooltiptext">Minimize</span>
</div>
<div class="tooltip">
<a href="maximize" class="btn bl">[]</a>
<span class="tooltiptext">Maximize</span>
</div>
<a href="exit" class="btn restart">X</a>
</div>
<br />
<br />
<form action="" method="">
<div id="jsalarmclock">
<div><div class="leftcolumn">Current Time:</div> <span id="jsalarm_ct" style="letter-spacing: 2px"></span></div>
<div><div class="leftcolumn">Set Alarm:</div> <span><select></select> Hour</span> <span><select></select> Minutes</span> </div>
<div><div class="leftcolumn">Repeat:</div><input size="5" type="number" id="repeat" min="1" value="1"/> <br>
<div class="leftcolumn">Loop forever</div> <input type="checkbox" id="forever" value="forever"/>
<span style="font: normal 11px Tahoma">Loop forever overides repeat</span> <br>
<div><div class="leftcolumn">Set file:</div><a href="file:///musicfile@"><button type="button">Select a file to play</button></a>
<span style="font: normal 11px Tahoma">Select a file to run with mpv or type in a custom action</span></div>
<div><div class="leftcolumn">Set Custom Action:</div> <input type="text" id="command" size="55" value="" /> <br>
<span style="font: normal 11px Tahoma">*Command to launch, if empty mpv will be used (do not use "@" character here)</span></div>
<input type="submit" value="Set Alarm!" id="submitbutton" />
</div>
</form>
<a href="file:///atq@"><button type="button">At Job List</button></a>
<script type="text/javascript">
jsalarm.init()
</script>
</body>
</html>
EOF
)"
#########################
# End of User interface #
#########################
#########################
# Bash functions #
#########################
# fuction to recursively kill all descendants
function _kill_descendant_processes() {
local pid="$1"
local and_self="${2:-false}"
if children="$(pgrep -P "$pid")"; then
for child in $children; do
_kill_descendant_processes "$child" true
done
fi
if [[ "$and_self" == true ]]; then
kill -SIGTERM "$pid"
fi
}
# Main window
function _yad_ui(){
# Set the line buffering with stdbuf
echo "${YURI}" | stdbuf -oL -eL yad --title="Set Alarm" --width=650 --height=500 --no-escape \
--html --no-buttons --print-uri --undecorated --borders=0 --window-icon="alarm1c.png" 2>&1 & echo $!
}
# Main Function
function _do_stuff(){
# fetch yad process id
read YAD_PID
# read yad stdout line by line
while read -r line
do
case ${line##*/} in
resize) xdotool key alt+F8 ;;
move) xdotool key alt+F7 ;;
exit) if yad --width=400 --title="Set Alarm" --height=100 --text="Exit?" --button="No:1" --button="Yes:0" --window-icon="alarm1c.png" 2>/dev/null; then
kill -SIGUSR1 $YAD_PID ;
_kill_descendant_processes $$ 2>/dev/null;
break
fi
;;
minimize) xdotool getactivewindow windowminimize ;;
maximize) if xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) _NET_WM_STATE | grep -E "MAXIMIZED_HORZ.*MAXIMIZED_VERT|MAXIMIZED_VERT.*MAXIMIZED_HORZ" > /dev/null 2>&1
then
wmctrl -ir $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) -b remove,maximized_vert,maximized_horz
else
wmctrl -ir $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) -b add,maximized_vert,maximized_horz
fi ;;
[0-9][0-9]:[0-9][0-9]*)
#kill -SIGUSR1 $YAD_PID
echo "Alarm set to: ${line##*/}"
alarm_time="${line##*/}"
;;
repeat@*) REPEAT="$(echo "${line##*@}" | sed 's/%20/ /g')"
;;
command@*) COMMAND="$(echo "${line##*@}" | sed 's/%20/ /g')"
if [ ! -e "/tmp/yalarm.$$" ] ; then
MUSIC="$(yad --width=600 --height=500 \
--title="Alarm" --text="Select a file to play in mpv" \
--file-filter="Audio | *.mp3 *.MP3 *.wav *.WAV *.ogg *.OGG" \
--file 2>/dev/null)"
[ $? != 0 ] && continue
echo "${MUSIC}" > /tmp/yalarm.$$
fi
# Fredx181
hrnow=$(echo $(date +"%k"))
# For when trying to set alarm for next day e.g. from current 21:00 to target 6:00
if [ "${alarm_time%%:*}" -eq "$hrnow" ] && [ "${alarm_time##*:}" -le "$(date +"%M")" ]; then
# prompt yes/no in case accidentally chosen current hour but less than current minute
yad --center --title="Are you sure?" --text="Are you sure to set the alarm to ${alarm_time} - tomorrow ?" --width=400 --button="Yes:0" --button="No:1"
[ $? -ne 0 ] && continue
fi
if [ ! "${COMMAND}" = "" ]; then
at "${alarm_time}" << EOF
exec env DISPLAY="$DISPLAY" $(echo "${line##*@}" | sed 's/%20/ /g') &
EOF
else
if [ "${REPEAT}" = "forever" ]; then
at "${alarm_time}" << EOF
exec env DISPLAY="$DISPLAY" mpv --force-window --loop inf "$(cat /tmp/yalarm.$$)"
EOF
else
at "${alarm_time}" << EOF
exec env DISPLAY="$DISPLAY" mpv --force-window --loop "${REPEAT}" "$(cat /tmp/yalarm.$$)"
EOF
fi
fi
# Here we set alarm
#at "${alarm_time}" << EOF
#exec env DISPLAY="$DISPLAY" $(echo "${line##*@}" | sed 's/%20/ /g')
#EOF
;;
atq@*) (REMOVE_JOB="$(atq | yad --list --width=600 --height=500 \
--text="Select 'at' job to remove or close this window" \
--column "Job List" \
--button="Remove at Job" 2>/dev/null \
| awk '{print $1}')"
if [[ "${REMOVE_JOB}" == [0-9]* ]]; then
echo "${REMOVE_JOB}"
atrm "${REMOVE_JOB}"
killall mpv
fi) &
;;
musicfile@*) (MUSIC="$(yad --width=600 --height=500 \
--title="Alarm" --text="Select a file to play in mpv" \
--file-filter="Audio | *.mp3 *.wav" \
--file 2>/dev/null)" \
[ $? = 0 ] && echo "${MUSIC}" > /tmp/yalarm.$$) &
;;
esac
done
rm /tmp/yalarm.$$
exit
}
_yad_ui | _do_stuff & wait $! 2>/dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment