{"id":7,"date":"2007-02-24T13:24:41","date_gmt":"2007-02-24T19:24:41","guid":{"rendered":"http:\/\/www.goodjobsucking.com\/?p=7"},"modified":"2007-02-24T13:35:16","modified_gmt":"2007-02-24T19:35:16","slug":"web-remote-control","status":"publish","type":"post","link":"http:\/\/www.goodjobsucking.com\/?p=7","title":{"rendered":"Web Remote Control"},"content":{"rendered":"<p>The words &#8220;web&#8221; and &#8220;remote control&#8221; are used together to describe all manner of things, but here I&#8217;m talking about a remote control of a PVR, using a web page.  In these days of wireless connectivity, and distributed video, it&#8217;s almost a natural thing to want to be able to control stationary equipment from a roaming laptop or tablet computer.  It seems that this is the sort of thing that many people would have done before, but my searches were fruitless.<\/p>\n<p>It turns out this sort of thing isn&#8217;t all that difficult to brew from scratch, although there are a lot of little pieces that need to be properly strung together.  Starting from the PVR itself, an infrared emitter is necessary that&#8217;s compatible with <a href=\"http:\/\/www.lirc.org\/\" title=\"LIRC\">lirc<\/a>.  (Consult the lirc documentation for a list of compatible emitters, and instructions for rolling your own.)<\/p>\n<p>Lirc itself needs to be installed and working properly; I won&#8217;t attempt to duplicate the documentation, which is fairly straightforward, but I ran into two snags.  First, lirc on gentoo requires a USE flag to be set in order to transmit at all &#8212; Gentoo has some excellent supplemental documentation <a href=\"http:\/\/gentoo-wiki.com\/HOWTO_LIRC\" title=\"Gentoo's LIRC Howto\">here<\/a>.  Second, not all the buttons were represented on my remote.  This was easy enough to rectify s<em>tarting with the lircd.conf closest to my equipment<\/em> using the <a href=\"http:\/\/www.lirc.org\/html\/irrecord.html\" title=\"irrecord\">irrecord<\/a> tool and some hexidecimal math.  (Obviously, this required that I also get lirc working as a <em>receiver<\/em>, but all I really used it for was adding additional codes.)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.baddomain.com\/6.2remote.jpg\" title=\"My Remote\" alt=\"My Remote\" align=\"right\" height=\"416\" width=\"136\" \/> Next, I located a picture of my remote.   The basic interface idea is to have a web page  where the user can simply poke each button.  They&#8217;re a little hard to read in this image, so this could be considerably improved, but realistically, after using the physical remote for a while, the positions and functions of the buttons become second nature.\u00a0 In addition, rolling over each button gives its function (albeit in an ugly way; this can be improved, too, of course.)<\/p>\n<p>A standard image map is used to make each button clickable.  To prevent annoying refresh and latency issues, simple AJAX techniques are employed to send each button press to the web server behind the scenes.<\/p>\n<p>Here&#8217;s the actual code of the pages:<\/p>\n<blockquote><p><font face=\"Courier New, Courier, mono\" size=\"-2\">pushbutton.php &#8212;<br \/>\n&lt;?php<br \/>\necho &#8216;irsend SEND_ONCE dish2 &#8216; . $_GET[&#8216;button&#8217;];<br \/>\nsystem(&#8216;\/usr\/bin\/irsend SEND_ONCE dish2 &#8216; . $_GET[&#8216;button&#8217;]);<br \/>\n?&gt;<\/font><\/p><\/blockquote>\n<p><!--more--><\/p>\n<p>And<\/p>\n<blockquote><p><font face=\"Courier New, Courier, mono\" size=\"-2\">dishremote.php &#8211;&lt;!DOCTYPE HTML PUBLIC &#8220;-\/\/W3C\/\/DTD HTML 4.01 Transitional\/\/EN&#8221; &#8220;<a href=\"http:\/\/www.w3.org\/TR\/html4\/loose.dtd\" class=\"linkification-ext\" title=\"Linkification: http:\/\/www.w3.org\/TR\/html4\/loose.dtd\">http:\/\/www.w3.org\/TR\/html4\/loose.dtd<\/a>&#8220;&gt;<br \/>\n&lt;html&gt;<br \/>\n&lt;head&gt;<br \/>\n&lt;title&gt;PVR Control&lt;\/title&gt;<br \/>\n&lt;meta http-equiv=&#8221;Content-Type&#8221; content=&#8221;text\/html; charset=iso-8859-1&#8243;&gt;<br \/>\n&lt;\/head&gt;<\/font><\/p>\n<p><font face=\"Courier New, Courier, mono\" size=\"-2\">&lt;script type=&#8221;text\/javascript&#8221;&gt;<br \/>\nvar xmlhttp<br \/>\n\/*@cc_on @*\/<br \/>\n\/*@if (@_jscript_version &gt;= 5)<br \/>\ntry {<br \/>\nxmlhttp=new ActiveXObject(&#8220;Msxml2.XMLHTTP&#8221;);<br \/>\n} catch (e) {<br \/>\ntry {<br \/>\nxmlhttp=new ActiveXObject(&#8220;Microsoft.XMLHTTP&#8221;);<br \/>\n} catch (E) {<br \/>\nxmlhttp=false;<br \/>\n}<br \/>\n}<br \/>\n@else<br \/>\nxmlhttp=false<br \/>\n@end @*\/<br \/>\nif (!xmlhttp &amp;&amp; typeof XMLHttpRequest!=&#8217;undefined&#8217;) {<br \/>\ntry {<br \/>\nxmlhttp = new XMLHttpRequest();<br \/>\n} catch (e) {<br \/>\nxmlhttp=false;<br \/>\n}<br \/>\n}<br \/>\nif (!xmlhttp &amp;&amp; window.createRequest) {<br \/>\ntry {<br \/>\nxmlhttp = window.createRequest();<br \/>\n} catch (e) {<br \/>\nxmlhttp=false;<br \/>\n}<br \/>\n}<br \/>\nfunction button(the_button) {<br \/>\nxmlhttp.open(&#8220;GET&#8221;, &#8220;pushbutton.php?button=&#8221;+the_button,true);<br \/>\nxmlhttp.onreadystatechange=function() {<br \/>\nif (xmlhttp.readyState==4) {<br \/>\n\/*   alert(xmlhttp.responseText) *\/<br \/>\n}<br \/>\n}<br \/>\nxmlhttp.send(null)<br \/>\n}<br \/>\n&lt;\/script&gt;<\/font><\/p>\n<p><font face=\"Courier New, Courier, mono\" size=\"-1\"><font face=\"Courier New, Courier, mono\" size=\"-2\">&lt;body&gt;<br \/>\n&lt;img src=&#8221;6.2remote.jpg&#8221; width=&#8221;136&#8243; height=&#8221;416&#8243; border=&#8221;0&#8243; usemap=&#8221;#Map&#8221;&gt;<br \/>\n&lt;map name=&#8221;Map&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,30,8&#8243; href=&#8221;javascript:button(&#8216;power&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;45,288,7&#8243; href=&#8221;javascript:button(&#8216;1&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,287,7&#8243; href=&#8221;javascript:button(&#8216;2&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;90,287,7&#8243; href=&#8221;javascript:button(&#8216;3&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;46,308,7&#8243; href=&#8221;javascript:button(&#8216;4&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,309,7&#8243; href=&#8221;javascript:button(&#8216;5&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;91,308,7&#8243; href=&#8221;javascript:button(&#8216;6&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;46,328,7&#8243; href=&#8221;javascript:button(&#8216;7&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;67,328,7&#8243; href=&#8221;javascript:button(&#8216;8&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;90,329,7&#8243; href=&#8221;javascript:button(&#8216;9&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;27,70,6&#8243; href=&#8221;javascript:button(&#8216;menu&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;67,121,14&#8243; href=&#8221;javascript:button(&#8216;select&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;111,143,9&#8243; href=&#8221;javascript:button(&#8216;cancel&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;109,98,8&#8243; href=&#8221;javascript:button(&#8216;guide&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;91,162,8&#8243; href=&#8221;javascript:button(&#8216;view&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;poly&#8221; coords=&#8221;96,106,84,113,83,130,96,139,103,123&#8243; href=&#8221;javascript:button(&#8216;right&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;poly&#8221; coords=&#8221;52,132,52,112,37,105,32,122,37,138&#8243; href=&#8221;javascript:button(&#8216;left&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;poly&#8221; coords=&#8221;53,107,80,107,92,97,69,87,45,97&#8243; href=&#8221;javascript:button(&#8216;up&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;poly&#8221; coords=&#8221;55,136,80,135,92,146,70,158,44,147&#8243; href=&#8221;javascript:button(&#8216;down&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;25,143,7&#8243; href=&#8221;javascript:button(&#8216;recall&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,237,7&#8243; href=&#8221;javascript:button(&#8216;record&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,212,11&#8243; href=&#8221;javascript:button(&#8216;pause&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;46,228,9&#8243; href=&#8221;javascript:button(&#8216;stop&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;107,211,9&#8243; href=&#8221;javascript:button(&#8216;fwd&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;46,348,7&#8243; href=&#8221;javascript:button(&#8216;asterisk&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;68,349,7&#8243; href=&#8221;javascript:button(&#8216;0&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;91,348,7&#8243; href=&#8221;javascript:button(&#8216;pound&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;45,162,8&#8243; href=&#8221;javascript:button(&#8216;info&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;88,228,8&#8243; href=&#8221;javascript:button(&#8216;play&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;27,210,9&#8243; href=&#8221;javascript:button(&#8216;back&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;67,182,10&#8243; href=&#8221;javascript:button(&#8216;dvr&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;90,58,8&#8243; href=&#8221;javascript:button(&#8216;page_up&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;109,71,7&#8243; href=&#8221;javascript:button(&#8216;page_down&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;47,194,9&#8243; href=&#8221;javascript:button(&#8216;skip_back&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;88,193,9&#8243; href=&#8221;javascript:button(&#8216;skip_fwd&#8217;)&#8221;&gt;<br \/>\n&lt;area shape=&#8221;circle&#8221; coords=&#8221;107,247,8&#8243; href=&#8221;javascript:button(&#8216;dish&#8217;)&#8221;&gt;<br \/>\n&lt;\/map&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<\/font><\/font><\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The words &#8220;web&#8221; and &#8220;remote control&#8221; are used together to describe all manner of things, but here I&#8217;m talking about a remote control of a PVR, using a web page. In these days of wireless connectivity, and distributed video, it&#8217;s almost a natural thing to want to be able to \u2026 <a class=\"continue-reading-link\" href=\"http:\/\/www.goodjobsucking.com\/?p=7\"> Continue reading <span class=\"meta-nav\">&rarr; <\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,2],"tags":[],"_links":{"self":[{"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=\/wp\/v2\/posts\/7"}],"collection":[{"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7"}],"version-history":[{"count":0,"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=\/wp\/v2\/posts\/7\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodjobsucking.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}