diff options
author | dakkar <dakkar@thenautilus.net> | 2021-12-22 15:02:39 +0000 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2021-12-22 15:02:39 +0000 |
commit | f673ed7ed761635e5efe3bc393c9299a35e0a1a7 (patch) | |
tree | 46ffebf42880711faf2b5b9f5359b1a2a2daacdd | |
parent | nicer error handling (diff) | |
download | media-control-f673ed7ed761635e5efe3bc393c9299a35e0a1a7.tar.gz media-control-f673ed7ed761635e5efe3bc393c9299a35e0a1a7.tar.bz2 media-control-f673ed7ed761635e5efe3bc393c9299a35e0a1a7.zip |
intergrated IR control
* PWA files
* lirc wrapper
* lircd config files
-rw-r--r-- | lib/App/MediaControl.rakumod | 27 | ||||
-rw-r--r-- | lib/Lirc/Commands.rakumod | 54 | ||||
-rw-r--r-- | lircd.conf.d/amplifier.conf | 35 | ||||
-rw-r--r-- | lircd.conf.d/bluray.conf | 208 | ||||
-rw-r--r-- | lircd.conf.d/projector.conf | 58 | ||||
-rw-r--r-- | media-control.raku | 4 | ||||
-rw-r--r-- | resources/index.html | 181 | ||||
-rw-r--r-- | resources/ir.png | bin | 0 -> 106247 bytes | |||
-rw-r--r-- | resources/ir.webmanifest | 15 |
9 files changed, 564 insertions, 18 deletions
diff --git a/lib/App/MediaControl.rakumod b/lib/App/MediaControl.rakumod index 238ae53..e4b5024 100644 --- a/lib/App/MediaControl.rakumod +++ b/lib/App/MediaControl.rakumod @@ -2,20 +2,16 @@ use v6.d; use Cro::HTTP::Server; use Cro::HTTP::Router; use Vlc::Client; -use Lirc::Client; +use Lirc::Commands; class App::MediaControl { has Vlc::Client $.vlc is required; - has Lirc::Client $.lirc is required; + has Lirc::Commands $.lirc is required; has Int $.port = 8080; has Cro::Service $!service handles <stop>; method start() { - my $application = route { - resources-from %?RESOURCES; - - get -> { resource 'index.html' } - + my $vlc = route { post -> 'play' { await self.vlc.command('pl_play') } post -> 'pause' { await self.vlc.command('pl_pause') } post -> 'stop' { await self.vlc.command('pl_stop') } @@ -24,11 +20,28 @@ class App::MediaControl { my $status = await self.vlc.status(); content 'application/json', $status; } + } + + my $ir = route { + post -> $thing, $arg { + await self.lirc.send($thing, $arg); + } + } + + my $application = route { + resources-from %?RESOURCES; + + get -> { resource 'index.html' } + get -> 'ir.png' { resource 'ir.png' } + get -> 'ir.webmanifest' { resource 'ir.webmanifest' } + + include :$vlc, :$ir; around -> &handler { handler(); CATCH { default { + note "BOOM $_"; response.status = 500; content 'application/json', %( error => "$_" ); } diff --git a/lib/Lirc/Commands.rakumod b/lib/Lirc/Commands.rakumod new file mode 100644 index 0000000..a274bdc --- /dev/null +++ b/lib/Lirc/Commands.rakumod @@ -0,0 +1,54 @@ +use v6.d; +use Lirc::Client; + +class Lirc::Commands { + has Lirc::Client $.client is required; + + sub hdmi-seq($input) { + return [ + <amplifier power>, + <projector power>, + ('amplifier', "hdmi{$input}"), + ] + } + sub stop-seq() { + return [ + <projector suspend>, + <amplifier hdmi1>, + <amplifier power>, + ]; + } + my %sequences = ( + 'start bluray' => [ + <amplifier power>, + <amplifier hdmi2>, + <projector power>, + <bluray power>, + ], + 'stop bluray' => [ + |stop-seq(), + <bluray power>, + ], + 'start hdmi1' => hdmi-seq(1), + 'start hdmi2' => hdmi-seq(2), + 'start hdmi3' => hdmi-seq(3), + 'stop hdmi' => stop-seq(), + ); + + method send($thing, $arg) { + if %sequences{"$thing $arg"} -> @seq { + for @seq -> @command { + await self.send(|@command); + sleep 1; + } + return Promise.kept(); + } + else { + note "irsend $thing $arg"; + return self.client.send( + remote => $thing, + keysym => "KEY_{$arg.uc}", + ); + } + } +} diff --git a/lircd.conf.d/amplifier.conf b/lircd.conf.d/amplifier.conf new file mode 100644 index 0000000..85b8cdb --- /dev/null +++ b/lircd.conf.d/amplifier.conf @@ -0,0 +1,35 @@ +begin remote + + name amplifier + bits 32 + flags SPACE_ENC|CONST_LENGTH + eps 30 + aeps 100 + + header 8903 4489 + one 558 1646 + zero 558 546 + ptrail 560 + repeat 8901 2256 + gap 107251 + toggle_bit_mask 0x0 + + begin codes + KEY_VOLUMEDOWN 0x5EA1D827 + KEY_VOLUMEUP 0x5EA158A7 + KEY_POWER 0x7E8154AB + KEY_HDMI1 0x5EA1E21C + KEY_HDMI2 0x5EA152AC + KEY_HDMI3 0x5EA1B24C + KEY_HDMI4 0x5EA10AF4 + KEY_AV1 0x5EA1CA34 + KEY_AV2 0x5EA16A94 + KEY_AV3 0x5EA19A64 + KEY_AV4 0x5EA13AC4 + KEY_AV5 0x5EA1FA04 + KEY_AUDIO1 0x5EA1A658 + KEY_AUDIO2 0x5EA116E8 + KEY_VAUX 0x5EA1AA55 + end codes + +end remote diff --git a/lircd.conf.d/bluray.conf b/lircd.conf.d/bluray.conf new file mode 100644 index 0000000..5478194 --- /dev/null +++ b/lircd.conf.d/bluray.conf @@ -0,0 +1,208 @@ +begin remote + name bluray + flags RAW_CODES + eps 30 + aeps 100 + frequency 40000 + min_repeat 3 + gap 12000 + begin raw_codes + + name KEY_UP + 2400 600 1200 600 600 600 600 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_MENU + 2400 600 600 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_CONTEXT_MENU + 2400 600 1200 600 600 600 600 600 + 1200 600 600 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_LEFT + 2400 600 1200 600 1200 600 600 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_OK + 2400 600 1200 600 600 600 1200 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_RIGHT + 2400 600 600 600 600 600 1200 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name BTN_BACK + 2400 600 1200 600 1200 600 600 600 + 600 600 600 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_DOWN + 2400 600 600 600 1200 600 600 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_OPTION + 2400 600 1200 600 1200 600 1200 600 + 1200 600 1200 600 1200 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_RED + 2400 600 1200 600 1200 600 1200 600 + 600 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_GREEN + 2400 600 600 600 600 600 600 600 + 1200 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_YELLOW + 2400 600 1200 600 600 600 600 600 + 1200 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_BLUE + 2400 600 600 600 1200 600 1200 600 + 600 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_HOME + 2400 600 600 600 1200 600 600 600 + 600 600 600 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_S + 2400 600 600 600 600 600 1200 600 + 1200 600 600 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_N + 2400 600 1200 600 1200 600 600 600 + 1200 600 600 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_PREVIOUS + 2400 600 1200 600 1200 600 600 600 + 1200 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_PLAY + 2400 600 600 600 1200 600 600 600 + 1200 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_NEXT + 2400 600 600 600 600 600 1200 600 + 1200 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_REWIND + 2400 600 1200 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_PAUSE + 2400 600 1200 600 600 600 600 600 + 1200 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_STOP + 2400 600 600 600 600 600 600 600 + 1200 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_FASTFORWARD + 2400 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_AUDIO + 2400 600 600 600 600 600 1200 600 + 600 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_DISPLAYTOGGLE + 2400 600 1200 600 600 600 600 600 + 600 600 600 600 600 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_SUBTITLE + 2400 600 1200 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_EJECTCD + 2400 600 600 600 1200 600 1200 600 + 600 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + name KEY_POWER + 2400 600 1200 600 600 600 1200 600 + 600 600 1200 600 600 600 600 600 + 600 600 1200 600 600 600 1200 600 + 1200 600 600 600 1200 600 600 600 + 600 600 600 600 1200 600 1200 600 + 1200 + end raw_codes +end remote
\ No newline at end of file diff --git a/lircd.conf.d/projector.conf b/lircd.conf.d/projector.conf new file mode 100644 index 0000000..f681c98 --- /dev/null +++ b/lircd.conf.d/projector.conf @@ -0,0 +1,58 @@ +begin remote + name projector + + bits 16 + flags SPACE_ENC|CONST_LENGTH + eps 30 + aeps 100 + + header 9043 4415 + one 623 1604 + zero 623 504 + ptrail 623 + pre_data_bits 16 + pre_data 0xC1AA + gap 107401 + toggle_bit_mask 0x0 + + begin codes + KEY_POWER 0x09F6 + KEY_SUSPEND 0x8976 # Standby + KEY_PLAY 0x7A85 + KEY_PAUSE 0xDA25 + KEY_STOP 0x9A65 + KEY_MUTE 0xB54A + KEY_VOLUMEUP 0x19E6 + KEY_VOLUMEDOWN 0x9966 + KEY_FORWARD 0xFA05 # >>| + KEY_BACK 0xBA45 # |<< + KEY_FRAMEFORWARD 0x3AC5 # >> + KEY_FRAMEBACK 0x5AA5 # << + KEY_ESC 0x21DE + KEY_MENU 0x59A6 + KEY_F1 0x06F9 # Link Menu + KEY_F2 0x6A95 # HDMI Link + KEY_F3 0x9C63 # Default + KEY_UP 0x0DF2 + KEY_DOWN 0x4DB2 + KEY_LEFT 0xCD32 + KEY_RIGHT 0x8D72 + KEY_F10 0xCE31 # HDMI1 + KEY_F11 0xEE11 # HDMI2 + KEY_F12 0x1EE1 # WirelessHD + KEY_F13 0x6E91 # USB + KEY_F14 0x8E71 # Component + KEY_F15 0x0EF1 # Video + KEY_F16 0xB946 # PC + KEY_F4 0xC43B # 2D/3D + KEY_F5 0xF10E # Colour Mode + KEY_F6 0xD12E # Memory + KEY_F7 0xA45B # Auto Iris + KEY_F8 0xBC43 # RGBCMY + KEY_F9 0x51AE # Aspect + KEY_F17 0x41BE # Split + KEY_F18 0x6996 # Pattern + KEY_F19 0xF906 # User + end codes + +end remote diff --git a/media-control.raku b/media-control.raku index 38517eb..879a11f 100644 --- a/media-control.raku +++ b/media-control.raku @@ -4,6 +4,7 @@ use lib 'inst#local','file#lib'; use Config::TOML; use Vlc::Client; use Lirc::Client; +use Lirc::Commands; use App::MediaControl; my $config = from-toml(file=>'config.toml'); @@ -13,7 +14,8 @@ my Vlc::Client $vlc .= new( base-uri => $config<vlc><base-uri>, ); -my Lirc::Client $lirc .= new(); +my Lirc::Client $lirc-client .= new(); +my Lirc::Commands $lirc .= new(client=>$lirc-client); my App::MediaControl $app .= new( port => $config<server><port>, diff --git a/resources/index.html b/resources/index.html index e33ac9a..cbf0a75 100644 --- a/resources/index.html +++ b/resources/index.html @@ -2,11 +2,12 @@ <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> - <title>vlc</title> + <link rel="manifest" href="ir.webmanifest"> + <link rel="icon" href="ir.png"> + <title>IR</title> <script> "use strict" - - function vlcCall(method,path,args) { + function call(method,path,args) { args ||= {}; let url=new URL(path,location.href); for (let a in args) { @@ -19,11 +20,15 @@ } function vlcCommand(command,args) { - vlcCall('post',command,args); + call('post',`vlc/${command}`,args); } + function irCommand(thing,arg) { + call('post',`ir/${thing}/${arg}`); + } + async function updateView() { - const status = (await (await vlcCall('get','status')).json()).status; + const status = (await (await call('get','vlc/status')).json()).status; const currentPos = document.querySelector('#current-pos'); if (status.state != 'playing') { @@ -47,12 +52,168 @@ } }) </script> + <style> + body { font-size: 12vw } + * { font-size: inherit } + + div.thing { + padding: 0.2em 0.1em 0.2em 0.1em; + margin-top: 0.5em; + margin-bottom: 1em; + border: solid 0.05em black; + border-radius: 0.5em; + position: relative; + } + div.thing label { + font-size: 0.8em; + line-height: 0.5em; + position: absolute; + top: -0.5em; + left: 1em; + background-color: white; + } + div.thing table { + width: 100%; + table-layout: fixed; + } + td button { + border-radius: 0.5em; + width: calc(100% - 0.2em); + margin: 0.1em; + } + + .power { color: white } + .power.on { background-color: green } + .power.off { background-color: red } + + .volume { background-color: lightblue } + .input { background-color: darkorange } + .control { background-color: black; color: white; filter: grayscale(100%) } + .bd-red { background-color: red } + .bd-yellow { background-color: yellow } + .bd-blue { background-color: blue; color: white } + </style> </head> <body> - <button onclick="vlcCommand('play')">play</button> - <button onclick="vlcCommand('pause')">pause</button> - <button onclick="vlcCommand('stop')">stop</button> - <button onclick="updateView()">update</button> - <input type="range" id="current-pos"> + <div class="thing"> + <label>Vlc</label> + <table> + <tr> + <td><button onclick="irCommand('start','hdmi3')" class="power on">start</button></td> + <td><button onclick="irCommand('stop','hdmi')" class="power off">stop</button></td> + </tr> + </table> + <details> + <summary>controls</summary> + <button onclick="vlcCommand('play')">play</button> + <button onclick="vlcCommand('pause')">pause</button> + <button onclick="vlcCommand('stop')">stop</button> + <button onclick="updateView()">update</button> + <input type="range" id="current-pos"> + </details> + </div> + <div class="thing"> + <label>Laptop</label> + <table> + <tr> + <td><button onclick="irCommand('start','hdmi1')" class="power on">start</button></td> + <td><button onclick="irCommand('stop','hdmi')" class="power off">stop</button></td> + </tr> + </table> + </div> + <div class="thing"> + <label>Bluray</label> + <table> + <tr> + <td><button onclick="irCommand('start','bluray')" class="power on">start</button></td> + <td><button onclick="irCommand('stop','bluray')" class="power off">stop</button></td> + </tr> + </table> + <details> + <summary>controls</summary> + <table> + <tr> + <td><button onclick="irCommand('bluray','ejectcd')" class="input">⏏</button></td> + <td> </td> + <td><button onclick="irCommand('bluray','power')" class="power on">ON</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','yellow')" class="bd-yellow">a</button></td> + <td><button onclick="irCommand('bluray','blue')" class="bd-blue">b</button></td> + <td><button onclick="irCommand('bluray','red')" class="bd-red">c</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','menu')" class="control">🔝</button></td> + <td><button onclick="irCommand('bluray','up')" class="control">↑</button></td> + <td><button onclick="irCommand('bluray','context_menu')" class="control">⎙</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','left')" class="control">←</button></td> + <td><button onclick="irCommand('bluray','ok')" class="control">ok</button></td> + <td><button onclick="irCommand('bluray','right')" class="control">→</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','back')" class="control">🔙</button></td> + <td><button onclick="irCommand('bluray','down')" class="control">↓</button></td> + <td><button onclick="irCommand('bluray','option')" class="control">opt</button></td> + </tr> + <tr> + <td colspan="3"><button onclick="irCommand('bluray','home')" class="control">home</button></td> + </tr> + + <tr> + <td><button onclick="irCommand('bluray','previous')" class="control">⏪</button></td> + <td><button onclick="irCommand('bluray','play')" class="control">▶</button></td> + <td><button onclick="irCommand('bluray','next')" class="control">⏩</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','review')" class="control">⏮</button></td> + <td><button onclick="irCommand('bluray','pause')" class="control">⏸</button></td> + <td><button onclick="irCommand('bluray','fastforward')" class="control">⏭</button></td> + </tr> + <tr> + <td><button onclick="irCommand('bluray','subtitle')" class="control">sub</button></td> + <td><button onclick="irCommand('bluray','stop')" class="control">⏹</button></td> + <td><button onclick="irCommand('bluray','audio')" class="control">aud</button></td> + </tr> + <tr> + <td> </td> + <td> </td> + <td><button onclick="irCommand('bluray','displaytoggle')" class="control">disp</button></td> + </tr> + </table> + </details> + </div> + <div class="thing"> + <label>Amp</label> + <table> + <tr> + <td><button onclick="irCommand('amplifier','power')" class="power on">ON</button></td> + <td><button onclick="irCommand('amplifier','power')" class="power off">OFF</button></td> + <td><button onclick="irCommand('amplifier','volumeup')" class="volume">↑</button></td> + </tr> + <tr> + <td> </td> + <td> </td> + <td><button onclick="irCommand('amplifier','volumedown')" class="volume">↓</button></td> + </tr> + <tr> + <td><button onclick="irCommand('amplifier','hdmi1')" class="input">Lap</button></td> + <td><button onclick="irCommand('amplifier','hdmi2')" class="input">BD</button></td> + <td><button onclick="irCommand('amplifier','hdmi3')" class="input">NAS</button></td> + </tr> + </table> + </div> + + <div class="thing"> + <label>Projector</label> + <table> + <tr> + <td><button onclick="irCommand('projector','power')" class="power on">ON</button></td> + <td><button onclick="irCommand('projector','suspend')" class="power off">OFF</button></td> + </tr> + </table> + </div> + </body> </html> diff --git a/resources/ir.png b/resources/ir.png Binary files differnew file mode 100644 index 0000000..43b1ebe --- /dev/null +++ b/resources/ir.png diff --git a/resources/ir.webmanifest b/resources/ir.webmanifest new file mode 100644 index 0000000..256b7ce --- /dev/null +++ b/resources/ir.webmanifest @@ -0,0 +1,15 @@ +{ + "background_color": "white", + "description": "Living room infrared control", + "display": "standalone", + "icons": [ + { + "src": "ir.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "name": "Infrared control", + "short_name": "IR", + "start_url": "/ir/" +} |