<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Things I&#039;ll Forget In A Month &#187; Hacks</title>
	<atom:link href="http://blog.zortrium.net/archives/category/hacks/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.zortrium.net</link>
	<description>Tech scratchpad and musings</description>
	<lastBuildDate>Wed, 07 Dec 2011 18:25:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>JSava: a Java bytecode interpreter in JavaScript</title>
		<link>http://blog.zortrium.net/archives/96?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jsava-a-java-bytecode-interpreter-in-javascript</link>
		<comments>http://blog.zortrium.net/archives/96#comments</comments>
		<pubDate>Mon, 21 Nov 2011 12:17:08 +0000</pubDate>
		<dc:creator>Sean Barker</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[JSava]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://blog.zortrium.net/?p=96</guid>
		<description><![CDATA[Here's another cool project I've been working on - it's an interpreter for Java bytecodes (i.e., like the JVM). What's more interesting about it, however, is that it's written in JavaScript. Furthermore, it runs on top of Mozilla Rhino, which means it's actually C code (the JVM) which runs Java code (Rhino) which runs JavaScript [...]]]></description>
			<content:encoded><![CDATA[<p>Here's another cool project I've been working on - it's an interpreter for Java bytecodes (i.e., like the JVM). What's more interesting about it, however, is that it's written in JavaScript. Furthermore, it runs on top of <a href="http://www.mozilla.org/rhino/">Mozilla Rhino</a>, which means it's actually C code (the JVM) which runs Java code (Rhino) which runs JavaScript code (the interpreter, JSava) which runs Java code (a user program). The double-interpreter thing does take a hit on speed, but the point isn't to beat the JVM for speed - it's to just accomplish something cool in a quirky language like JavaScript.</p>
<p>This may seem like deja vu to <a href="http://developers.slashdot.org/story/11/11/21/0454254/javascript-jvm-runs-java">Slashdot</a> readers, which is what prompted me to post this. I think JSava is particularly interesting, however, because it can handle many fairly advanced features of the JVM and is capable of executing much (most?) of the JDK standard library. Some feature highlights include:</p>
<ul>
<li>All 200 <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">JVM opcodes</a> are implemented.</li>
<li>All native Java types are supported, including 64-bit Longs, which are not natively supported by JavaScript. This is because JavaScript represents everything as 64-bit floating point numbers, which cannot store the full range of 64-bit integer values.</li>
<li>Full support for the Java threading model, including multithreading, synchronization between threads, and monitors (wait() and notify()). However, note that multithreading does not imply parallelism, which is at the moment effectively impossible in JavaScript - JSava provides threading support by timeslicing a single actual thread of execution.</li>
<li>JSava is complete enough to execute most major JDK library classes, such as java.util.HashMap and java.util.Random. Even some more exotic classes are mostly functional, such as java.util.concurrent.ExecutorService and company.</li>
<li>Substantial support for the <a href="http://download.oracle.com/javase/tutorial/reflect/">Reflection</a> API. This may seem like a weird thing to support, but reflection is heavily used in the JDK library classes, so supporting it is critical in enabling complete functionality.</li>
<li>All the usual Java goodness: exceptions, inheritance, interfaces, runtime error checking, etc... basically all the language features we know and love.</li>
<li>Native method handling capabilities for handing off to JavaScript implementations (e.g., System.arraycopy(), Thread.start() and lots of JDK support methods).</li>
<li>Rudimentary I/O support, accomplished through a lot of low-level trickery involving intercepting file descriptors and mapping them to native Java streams. JavaScript itself has effectively zero I/O support, but the only time Java is invoked to handle I/O is in the lowest level native methods (e.g., 'write these bytes to this file handle'). Everything above that (such as I/O buffering) is handled inside the interpreter.</li>
</ul>
<p>The JDK class files which JSava was developed with are taken from the Mac OS X 10.6 JDK (Java SE 6). The interpreter may work on Linux, but probably won't on Windows without a little bit of tweaking, particularly for I/O (it's on my todo list).</p>
<p>As usual, I've also created a new <a href="http://www.zortrium.net/programs/show.php?id=13">program page</a> for the project. The <a href="http://zortrium.net/programs/files/jsava-0.2.tar.gz">main download link</a> (or <a href="http://dl.dropbox.com/u/378562/jsava-0.2.tar.gz">Dropbox mirror</a>) provides the entire JSava runtime environment, including Rhino and JDK library classes (3.3M). If you have Java installed, running the interpreter is as easy as executing one command (no building required!). If you only want to look at the source code and not actually run the interpreter, you can also download <a href="http://zortrium.net/programs/files/jsava-0.2-src.tar.gz">the source only</a> (54K).</p>
<p>There were a lot of engineering tricks that went into JSava and I may write about some of them in the future. However, JSava is still very much a work in progress and I plan to extend it to handle even more than it already does.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zortrium.net/archives/96/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>plmtools for the iMeter Solo and/or the GuruPlug</title>
		<link>http://blog.zortrium.net/archives/75?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=plmtools-for-the-imeter-solo-andor-the-guruplug</link>
		<comments>http://blog.zortrium.net/archives/75#comments</comments>
		<pubDate>Mon, 25 Apr 2011 05:19:26 +0000</pubDate>
		<dc:creator>Sean Barker</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[plmtools]]></category>
		<category><![CDATA[Plug Computers]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://blog.zortrium.net/?p=75</guid>
		<description><![CDATA[Update (11/10/2011): I've posted an updated version of the code that fixes the issue with the new 1.15 iMeters: see my more recent post. Update (9/26/2011): Smarthome has come out with a new revision of the iMeter that breaks this utility -- the meter firmware seems to have changed, and the new one does not [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update (11/10/2011):</strong> I've posted an updated version of the code that fixes the issue with the new 1.15 iMeters: see my <a href="http://blog.zortrium.net/archives/88">more recent post</a>.</p>
<p><strong>Update (9/26/2011):</strong> Smarthome has come out with a new revision of the iMeter that breaks this utility -- the meter firmware seems to have changed, and the new one does not provide all the information of the old. To see if you have the old meter (that does work), look for a sticker on the back side of the iMeter. If you see a "<strong>V1.1</strong>", then you have the old one (good).  If you see a "<strong>Rev. 1.15</strong>", then you have the new one (bad). I'm working on figuring out the 1.15 protocol to get this utility working again with the new ones.</p>
<hr />
<p>One of my current research projects involves instrumenting a house with a lot of <a href="http://en.wikipedia.org/wiki/Insteon">Insteon</a> home-automation devices and collecting data from them.  I've been using the very useful Linux <a href="https://sourceforge.net/projects/plmtools/">plmtools</a> utilities to talk to the Insteon devices programmatically.  However, the plmtools suite has a few shortcomings for my purposes: one, the current release doesn't compile or run on ARM-based machines (such as the GuruPlugs I'm using) and two, it has no functionality for talking to the new Insteon power meter, the <a href="http://www.smarthome.com/2423A1/iMeter-Solo-INSTEON-Power-Meter-Plug-In/p.aspx">iMeter Solo</a>.  The iMeter Solo basically works exactly like a <a href="http://www.p3international.com/products/special/P4400/P4400-CE.html">Kill-A-Watt</a> meter, except that since it's an Insteon device it's possible to interface with it.</code></p>
<p>I've dealt with both of the above problems.  I've fixed the ARM-specific problems in the code so it runs great on the GuruPlug, and I've added functionality for querying the current wattage level from an iMeter Solo.  I imagine there are others who would like to use plmtools on ARM-based machines, and as far as I know there are no existing tools that allow you to query the iMeter from within Linux.  Now, you can query the current watt draw reported by the iMeter using a simple '<code>insteon mydevice meter</code>' command.</p>
<p>Also note that the iMeter Solo is frequently advertised alongside a special 'HouseLinc'-enabled version of the PLM that's required to use the HouseLinc software that can talk to the iMeter.  This is unnecessary for my solution, which works just fine on a regular PLM.</p>
<p>You can <a href="http://blog.zortrium.net/files/plmtools-0.0.3-r1-imeter-armfix.tar.gz">download the modified plmtools here</a>.  See the included README for details both on how the base plmtools utilities work as well as how the added meter functionality works.  I'm trying to get in touch with the original author of plmtools to see if I can get these changes integrated into a future release on SourceForge, but so far haven't had any luck.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zortrium.net/archives/75/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Toggling audio devices in Mac OS X</title>
		<link>http://blog.zortrium.net/archives/55?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=toggling-audio-devices-in-mac-os-x</link>
		<comments>http://blog.zortrium.net/archives/55#comments</comments>
		<pubDate>Thu, 25 Feb 2010 19:05:59 +0000</pubDate>
		<dc:creator>Sean Barker</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://blog.zortrium.net/?p=55</guid>
		<description><![CDATA[I frequently switch between my external computer speakers and my headphones. Repeatedly plugging and unplugging my headphones started wearing out my headphone jack, so I hooked up an iMic to a USB port to give myself a second headphone jack. This allows switching between them in software through the Sound preference pane, which is more [...]]]></description>
			<content:encoded><![CDATA[<p>I frequently switch between my external computer speakers and my headphones.  Repeatedly plugging and unplugging my headphones started wearing out my headphone jack, so I hooked up an <a href="http://www.griffintechnology.com/products/imic">iMic</a> to a USB port to give myself a second headphone jack.  This allows switching between them in software through the Sound preference pane, which is more convenient, but still takes too long.  So the next step is automating the switch.  <a href="http://www.macosxhints.com/article.php?story=20050614171126634">This thread</a> on Mac OS X Hints has people discussing various ways to do it.  The easiest GUI way to do the switch on Snow Leopard is just option-clicking the menu bar volume control and selecting the new output device (on Leopard, you can do effectively the same by installing <a href="http://www.rogueamoeba.com/freebies/download/SoundSource.zip">SoundSource</a>).</p>
<p>I'd like to avoid using the mouse at all, of course.  Someone got the sources to SoundSource and created a little command-line app called <a href="http://whoshacks.blogspot.com/2009/01/change-audio-devices-via-shell-script.html">audiodevice</a> that can do the switch without a GUI.  Making progress, but that still requires executing a custom command to switch from the headphones to speakers or vice versa.  As a final step, I threw together a quick script that uses audiodevice to toggle between the two without any arguments:<br />
<code>
<pre>#!/usr/bin/perl -w

use strict;

my $device1 = 'Headphones'; # my speakers, plugged into my computer's jack
my $device2 = 'iMic USB audio system'; # my headphones, plugged into my iMic's jack

foreach (`audiodevice`) {
  if (/output: (.*)/) {
    if ($1 eq $device1) {
      system("audiodevice output '$device2'");
      exit;
    } elsif ($1 eq $device2) {
      system("audiodevice output '$device1'");
      exit;
    } else {
      print "Unrecognized output device '$1'.\n";
      exit;
    }
  }
}

print "Failed to find output device.\n";
</pre>
<p></code><br />
I saved this script as audioswitch and added it to my LaunchBar index so I can call it from anywhere using only 4 or 5 keystrokes.  Works exactly as I'd like, and you can modify it to toggle between any two devices by substituting the name of the devices (in the Output tab of the Sound preference pane) into the script.</p>
<p>UPDATE (3/11/10):  I've fixed up the above script so that it automatically figures out what the two output devices are and switches between the two accordingly.  This means that it'll work for switching between the iMic and either internal or external speakers.  Also fixed a problem where system sounds would continue to play through the original device after switching and added a Growl notification with growlnotify.<br />
<code>
<pre>#!/usr/bin/perl -w

use strict;

my $device1;
my $device2;

foreach (`audiodevice output list`) {
  chomp;
  if (defined $device1) {
    $device2 = $_;
    last;
  } else {
    $device1 = $_;
  }
}

foreach (`audiodevice`) {
  if (/output: (.*)/) {
    if ($1 eq $device1) {
      activate($device2);
      exit;
    } else {
      activate($device1);
      exit;
    }
  }
}

print "Failed to find output device.\n";

sub activate {
  my $device = shift;
  system("audiodevice output '$device'");
  system("audiodevice system '$device'");
  system("growlnotify -n audioswitch -m 'switching to $device'");
}
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zortrium.net/archives/55/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Remote controlling an iSight</title>
		<link>http://blog.zortrium.net/archives/45?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=remote-controlling-an-isight</link>
		<comments>http://blog.zortrium.net/archives/45#comments</comments>
		<pubDate>Mon, 22 Feb 2010 20:48:02 +0000</pubDate>
		<dc:creator>Sean Barker</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://blog.zortrium.net/?p=45</guid>
		<description><![CDATA[One of the neat things to do with a remote Mac is to control the built-in iSight remotely to snap photos. There are several commercial applications to do this, but we're going for the low-tech approach: taking pictures via command line over SSH. The free app iSightCapture is designed to do this, but hasn't been [...]]]></description>
			<content:encoded><![CDATA[<p>One of the neat things to do with a remote Mac is to control the built-in iSight remotely to snap photos.  There are several commercial applications to do this, but we're going for the low-tech approach: taking pictures via command line over SSH.  The free app <a href="http://www.intergalactic.de/pages/iSight_files/isightcapture1_1.dmg">iSightCapture</a> is designed to do this, but hasn't been updated in awhile and doesn't work as-is on anything after 10.4.9 (including 10.5 and 10.6) due to new security restrictions.  I put together a little script that basically wraps iSightCapture so that it works as designed on an up-to-date system.</p>
<p>You'll need to have iSightCapture installed and in your $PATH -- you can either do that by manually installing the binary at the above link or via MacPorts with 'sudo port install isightcapture'.  Then create a new file in /usr/local/bin (or wherever) and put in the following Perl snippet:<br />
<code>
<pre>#!/usr/bin/perl -w

use strict;

foreach (split(/\n/, `ps aux | grep loginwindow`)) {
  if (/^\w+\s+(\d+).+?loginwindow\.app/) {
    my $sudo = ($> == 0) ? '' : 'sudo ';
    exec("$sudo launchctl bsexec $1 isightcapture @ARGV");
    exit;
  }
}

print "Failed to find loginwindow process.\n";
</pre>
<p></code></p>
<p>I called the new binary 'snap', so at the command-line, I just type 'snap image.jpg' instead of 'isightcapture image.jpg'.  The only real difference from isightcapture is that you need sudo -- that's an intentional Mac OS X security restriction that can't be circumvented (and probably shouldn't) as far as I know.  All the iSightCapture command-line options should work as-is, so just refer to its documentation for those.  The wrapper script is definitely a hack that might break with a future OS update, but has worked flawlessly for me on several different machines running a variety of Mac OS X versions.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zortrium.net/archives/45/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

