Skip to content

Instantly share code, notes, and snippets.

@MonoidMusician
Created December 23, 2020 17:33
Show Gist options
  • Save MonoidMusician/b252d9bb1ab30bba12ac4e80558c3120 to your computer and use it in GitHub Desktop.
Save MonoidMusician/b252d9bb1ab30bba12ac4e80558c3120 to your computer and use it in GitHub Desktop.
Simple web app to control mac volume & brightness
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Control my mac</title>
<style>
/* From https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/ */
input[type=range] {
-webkit-appearance: none;
margin: 10px 0;
width: 100%;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 12.8px;
cursor: pointer;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #ac51b5;
border-radius: 25px;
border: 0px solid #000101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #000000;
height: 20px;
width: 39px;
border-radius: 7px;
background: #65001c;
cursor: pointer;
-webkit-appearance: none;
margin-top: -3.6px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #ac51b5;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 12.8px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #ac51b5;
border-radius: 25px;
border: 0px solid #000101;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #000000;
height: 20px;
width: 39px;
border-radius: 7px;
background: #65001c;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 12.8px;
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
border-width: 39px 0;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #ac51b5;
border: 0px solid #000101;
border-radius: 50px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #ac51b5;
border: 0px solid #000101;
border-radius: 50px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #000000;
height: 20px;
width: 39px;
border-radius: 7px;
background: #65001c;
cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
background: #ac51b5;
}
input[type=range]:focus::-ms-fill-upper {
background: #ac51b5;
}
body {
padding: 30px;
}
</style>
</head>
<body>
<div>
<label><b style="font-size: 20px">Volume:</b><br/>
<input id="volume" type="range" min="0" max="100" step="1"/>
</label>
</div>
<div>
<label><b style="font-size: 20px">Brightness:</b><br/>
<input id="brightness" type="range" min="0" max="1" step="0.01"/>
</label>
</div>
<button id="refresh">Refresh</button>
</body>
<script>
function send(id, value) {
var path = ''+id;
fetch(path, {method:"PUT", body:value});
}
var refresh = [];
function sendoninput(id) {
var init = function() {
fetch(id).then(r => r.text()).then(v => {
document.getElementById(id).value = v;
});
}
init();
refresh.push(init);
document.getElementById(id).oninput = function(e) {
send(id, e.target.value);
};
}
sendoninput("volume");
sendoninput("brightness");
document.getElementById("refresh").onclick = function() {
refresh.forEach(f => f());
};
setInterval(function() {
refresh.forEach(f => f());
}, 20000);
</script>
</html>
#!/usr/bin/env python3
import os
import subprocess
import argparse
try:
import http.server as server
except ImportError:
# Handle Python 2.x
import SimpleHTTPServer as server
class Script:
def __init__(self, set, get):
self.set_script = set
self.get_script = get
def set(self, v):
return Script.run(self.set_script(v))
def get(self):
return Script.run(self.get_script)
@staticmethod
def run(cmd):
return subprocess.check_output(cmd).decode('utf-8').strip()
class OSAScript(Script):
def __init__(self, set, get):
self.set_script = set
self.get_script = get
def set(self, v):
return OSAScript.run(self.set_script(v))
def get(self):
return OSAScript.run(self.get_script)
@staticmethod
def run(cmd):
return Script.run(["osascript","-e",cmd])
methods = {
"/volume": OSAScript(
lambda v: "set volume output volume %s" % v,
"output volume of (get volume settings)",
),
# brew install brightness
"/brightness": Script(
lambda v: ["brightness", str(v)],
["bash", "-c", "brightness -l | grep brightness | sed -E \"s/display 0: brightness ([0-9.]+)/\\1/g\""],
)
}
class HTTPRequestHandler(server.SimpleHTTPRequestHandler):
"""Extend SimpleHTTPRequestHandler to handle PUT requests"""
def end_headers(self):
self.send_my_headers()
server.SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
self.send_header("Pragma", "no-cache")
self.send_header("Expires", "0")
def do_GET(self):
try:
method = methods[self.path]
reply_body = method.get().encode('utf-8')
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(reply_body))
self.end_headers()
self.wfile.write(reply_body)
return
except KeyError:
server.SimpleHTTPRequestHandler.do_GET(self)
def do_PUT(self):
try:
method = methods[self.path]
file_length = int(self.headers['Content-Length'])
content = self.rfile.read(file_length).decode('utf-8')
reply_body = method.set(content).encode('utf-8')
self.send_response(201, 'Set')
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(reply_body))
self.end_headers()
self.wfile.write(reply_body)
except KeyError:
self.send_response(404, 'Not found')
self.end_headers()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
help='Specify alternate bind address '
'[default: all interfaces]')
parser.add_argument('port', action='store',
default=8000, type=int,
nargs='?',
help='Specify alternate port [default: 8000]')
args = parser.parse_args()
try:
server.test(HandlerClass=HTTPRequestHandler, port=args.port, bind=args.bind)
except TypeError:
server.test(HandlerClass=HTTPRequestHandler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment