<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6486847724120122589</id><updated>2012-02-03T08:40:28.318-08:00</updated><category term='linux'/><category term='lucid'/><category term='ubuntu'/><category term='gedit'/><category term='ted'/><category term='10.04'/><category term='ted2010'/><category term='jhbuild'/><category term='gnome'/><title type='text'>credentiality</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default?start-index=101&amp;max-results=100'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>210</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6590000187277198255</id><published>2012-02-01T12:00:00.000-08:00</published><updated>2012-02-01T12:00:19.645-08:00</updated><title type='text'>RobotShop sucks</title><content type='html'>robotshop.com's customer service sucks. &amp;nbsp;I paid extra for 2-day shipping, and 4 days later they emailed me back asking for my social security number. &amp;nbsp;I had to work out on my own that it (probably) wasn't an identity theft scam, but something to do with import duties (they ship from Canada), because they didn't give any reason why they wanted it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I sent them my company's taxpayer ID, and the next day I get a voicemail asking me for it once again. &amp;nbsp;So we're almost a week on, it still hasn't shipped, and they're apparently not even reading their email. &amp;nbsp;Ugh.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6590000187277198255?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6590000187277198255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6590000187277198255' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6590000187277198255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6590000187277198255'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2012/02/robotshop-sucks.html' title='RobotShop sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4900490442155510247</id><published>2012-01-27T23:27:00.000-08:00</published><updated>2012-01-27T23:27:58.017-08:00</updated><title type='text'>Repeated strings in bash</title><content type='html'>&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; line-height: 15px;"&gt;I just whipped up a little bar graph in bash using this trick:&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; line-height: 15px;"&gt;printf '=%.0s' $(seq 10)&lt;/span&gt;&lt;br style="background-color: white; line-height: 15px;" /&gt;&lt;br /&gt;A more complete example, u&lt;span style="background-color: white; line-height: 15px;"&gt;sing some file with lines containing a date string:&lt;/span&gt;&lt;br style="background-color: white; line-height: 15px;" /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;for d in {17..27} ; do&lt;br /&gt;&amp;nbsp; N=$(grep 2012_01_$d /tmp/somefile | wc -l)&lt;br /&gt;&amp;nbsp; echo -n "Jan $d: $N "&lt;br /&gt;&amp;nbsp; printf "=%.0s" $(seq $N)&lt;br /&gt;&amp;nbsp; echo&lt;br /&gt;done&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 17: 28 ============================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 18: 22 ======================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 19: 43 ===========================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 20: 32 ================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 21: 0 =&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 22: 0 =&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 23: 46 ==============================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 24: 50 ==================================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 25: 50 ==================================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 26: 51 ===================================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;Jan 27: 41 =========================================&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: white; line-height: 15px;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; line-height: 15px;"&gt;(Breaks for 0, as you can see)&lt;/span&gt;&lt;br style="background-color: white; line-height: 15px;" /&gt;&lt;br style="background-color: white; line-height: 15px;" /&gt;&lt;span style="background-color: white; line-height: 15px;"&gt;If you're doing it for constant numbers, you can use {1..10} instead of $(seq 10), but {1..$N} doesn't seem to work.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4900490442155510247?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4900490442155510247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4900490442155510247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4900490442155510247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4900490442155510247'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2012/01/repeated-strings-in-bash.html' title='Repeated strings in bash'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4844591081486885190</id><published>2012-01-06T16:31:00.000-08:00</published><updated>2012-01-06T16:31:19.089-08:00</updated><title type='text'>Creating spectrograms in Linux using a ColorMunki</title><content type='html'>&lt;br /&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;The software that comes with the ColorMunki Photo is windows-only and is only about calibrating displays and printers. &amp;nbsp;I wanted to get spectrograms out of it so that we can measure lighting and transmissive materials -- a chart of wavelength vs. intensity. &amp;nbsp;BTW, check the argyll docs before you buy a ColorMunki -- apparently several of the models are the same hardware priced differently.&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;Install the argyll ubuntu package, then use the spotread command to take readings. &amp;nbsp;The -S flag will display a graph after each reading. &amp;nbsp;Other flags let you set which mode to use -- it has its own light for lighting a surface and measuring the reflected color, or you can have it read ambient light through a diffuser, or do spot readings without the light. &amp;nbsp;I used -e to take spot readings.&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;It also prints out a list of intensities at regular wavelength intervals, so that should be easy to import into a spreadsheet for making your own charts.&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;Here's an example of a chart that spotread produced:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-S5FcQBys1s8/TweSJHSNqwI/AAAAAAAAiJM/xjXrKrIuqbM/s1600/spotread_chart.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://2.bp.blogspot.com/-S5FcQBys1s8/TweSJHSNqwI/AAAAAAAAiJM/xjXrKrIuqbM/s320/spotread_chart.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: white; font-family: arial; font-size: small;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4844591081486885190?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4844591081486885190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4844591081486885190' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4844591081486885190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4844591081486885190'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2012/01/creating-spectrograms-in-linux-using.html' title='Creating spectrograms in Linux using a ColorMunki'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-S5FcQBys1s8/TweSJHSNqwI/AAAAAAAAiJM/xjXrKrIuqbM/s72-c/spotread_chart.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2160611513722984963</id><published>2012-01-02T17:05:00.000-08:00</published><updated>2012-01-02T17:05:14.050-08:00</updated><title type='text'>Walmart / vudu video rental sucks</title><content type='html'>Just for the heck of it, we tried renting a video at walmart.com's vudu streaming service. &amp;nbsp;It was unwatchable, freezing every few seconds for buffering. &amp;nbsp;Checked our connection with speedtest.net, and the connection is fine.&lt;br /&gt;&lt;br /&gt;And of course they've taken netflix's nonexistent customer service approach, with no way to ask for a refund. &amp;nbsp;Thanks Walmart for wasting a half hour of my time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2160611513722984963?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2160611513722984963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2160611513722984963' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2160611513722984963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2160611513722984963'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2012/01/walmart-vudu-video-rental-sucks.html' title='Walmart / vudu video rental sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-145951094539572884</id><published>2011-11-20T02:16:00.001-08:00</published><updated>2012-02-02T23:55:11.181-08:00</updated><title type='text'>Untangling gdata</title><content type='html'>Update (2 Feb 2012): We got docs uploads working in GoogleCL with python gdata versions 2.0.15 and 2.0.16 after noticing a &lt;a href="http://translate.google.com/translate?hl=en&amp;amp;sl=ja&amp;amp;u=http://demon-lord.com/doku.php%3Fid%3Dvps:backup&amp;amp;ei=OzoqT7jeDMqriQKKudGmCg&amp;amp;sa=X&amp;amp;oi=translate&amp;amp;ct=result&amp;amp;resnum=8&amp;amp;ved=0CFQQ7gEwBw&amp;amp;prev=/search%3Fq%3D%2522docsentry%2522%2B2.0.15%26hl%3Den%26biw%3D1200%26bih%3D636%26prmd%3Dimvns"&gt;random page&lt;/a&gt; in Japanese (thanks Google Translate!) that mentioned changing all references of gdata.docs.data.DocsEntry to gdata.data.GDEntry.  Also, the gdata.docs.data.MIMETYPES variable that was provided "&lt;a href="http://code.google.com/apis/documents/docs/3.0/developers_guide_python.html"&gt;for your convenience&lt;/a&gt;" went missing in 2.0.15 and 2.0.16. &amp;nbsp;I've updated the table accordingly.&lt;br /&gt;&lt;br /&gt;A brief history of python-gdata to upload files to Google Docs. &amp;nbsp;(Much of this is also relevant to the other language interfaces to Google's gdata API.) &amp;nbsp;Coila from the "Let's Get Technical" blog (where she has &lt;a href="http://atechyblog.blogspot.com/2011/11/python-gdata.html"&gt;more details and links&lt;/a&gt;) and I worked all this out this evening trying to sort through some of the nastier open GoogleCL bugs.&lt;br /&gt;&lt;br /&gt;Versions of python-gdata (as it's known in debian/ubuntu, or gdata-python-client on the code.google.com site):&lt;br /&gt;&lt;br /&gt;2.0.0 .. 2.0.4: Uses old OAuth mechanism. &amp;nbsp;Supports uploading limited file types to docs.&lt;br /&gt;&lt;br /&gt;2.0.5: client.py interface added. &amp;nbsp;Uses a new OAuth mechanism.&lt;br /&gt;&lt;br /&gt;2.0.8: "Resumable upload" mechanism added.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;2 May 2011:&lt;br /&gt;&lt;div&gt;Google starts allowing uploading arbitrary files to Google Docs. &amp;nbsp;I believe this worked on versions 2.0.5 through 2.0.14 (2.0.15 wasn't released yet). &lt;br /&gt;&lt;div&gt;&lt;br /&gt;30 September 2011:&amp;nbsp;&lt;/div&gt;&lt;div&gt;Google servers start returning "403.4 SSL Required" errors for versions 2.0.5 through 2.0.9, and also 2.0.11 for some reason. &amp;nbsp;2.0.10, 2.0.12, 2.0.13 and 2.0.14 seem to be fine.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, "403 Files must be uploaded using the resumable upload mechanism" errors start appearing. &amp;nbsp;But only, apparently for versions 2.0.5 and later -- 2.0.0 through 2.0.5 still are able to upload limited file types.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One last wrinkle: GoogleCL is currently broken with version 2.0.15, failing due to gdata.docs.MIMETYPES having gone missing. &amp;nbsp;So I don't yet know anything more about it.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Got all that? &amp;nbsp;Here's a handy chart to help you keep it straight:&lt;br /&gt;&lt;br /&gt;&lt;b id="internal-source-marker_0.9404886283446103"&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;table style="border-bottom-style: none; border-collapse: collapse; border-color: initial; border-image: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial;"&gt;&lt;tbody&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;python-gdata version&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;OAuth&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;Can upload text files to docs as of 11/2011&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;Can upload arbitrary files to docs as of 11/2011&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;Arbitrary file upload without Resumable (5/2011 - 10/2011) ??&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;Supports Resumable Uploads&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;403: SSL error&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;403: Resumable upload required&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;Has gdata.docs.MIMETYPES&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry/GDEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.0&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;old&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.1&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;old&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.2&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;old&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.3&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;old&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.4&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;old&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.5&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.6&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.7&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.8&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.9&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.10&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.11&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.12&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.13&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.14&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;DocsEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.15&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;?&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;GDEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 0px;"&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;2.0.16&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;new&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;?&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;X&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(170, 170, 170); border-bottom-style: dotted; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(170, 170, 170); border-left-style: dotted; border-left-width: 1px; border-right-color: rgb(170, 170, 170); border-right-style: dotted; border-right-width: 1px; border-top-color: rgb(170, 170, 170); border-top-style: dotted; border-top-width: 1px; padding-bottom: 7px; padding-left: 7px; padding-right: 7px; padding-top: 7px; vertical-align: top;"&gt;&lt;span style="font-family: Arial; font-size: 12px; vertical-align: baseline; white-space: pre-wrap;"&gt;GDEntry&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-145951094539572884?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/145951094539572884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=145951094539572884' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/145951094539572884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/145951094539572884'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/11/untangling-gdata.html' title='Untangling gdata'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4850054142372781903</id><published>2011-10-28T21:19:00.000-07:00</published><updated>2011-10-28T21:19:57.214-07:00</updated><title type='text'>Flat bottom table saw cuts</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;If you've spent much time watching New Yankee Workshop, you've seen Norm cut a wide dado (slot) in a piece of wood by making multiple passes with the table saw, moving the wood a little to the side after each pass.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;But when I tried it, I found that my saw left a V-shaped profile at the bottom of the cut, like the one on the left here:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-q9AyDn5dmDM/Tqtxluq6gXI/AAAAAAAAhN0/jkLvmG0C2-g/s1600/IMG_20111028_201923.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-q9AyDn5dmDM/Tqtxluq6gXI/AAAAAAAAhN0/jkLvmG0C2-g/s320/IMG_20111028_201923.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;That's because my blade, like most table saw blades, has an Alternating Top Bevel (ATB) grind. &amp;nbsp;You can see a good picture at the bottom of&amp;nbsp;&lt;a href="http://www.rockler.com/articles/saw-blade-selection-guide.cfm"&gt;Rockler's blade selection page&lt;/a&gt;. &amp;nbsp;If you look carefully at a blade edge-on in the store, you can generally see the alternating profile, like you see on that page.&lt;br /&gt;&lt;br /&gt;What I needed was a blade with a flat top grind. &amp;nbsp;Apparently there are blades where &lt;i&gt;all&lt;/i&gt; the teeth have a flat (or "raker") grind, but I've only ever seen them on Dado sets. &amp;nbsp;(Ripping blades supposedly are ground this way, but I've never seen one that actually was.)&lt;br /&gt;&lt;br /&gt;So instead of having all flat top grinds, I wanted an ATB/R (Alternating Top Bevel with Raker) blade. &amp;nbsp;The rockler page calls this a "combination" grind. &amp;nbsp;Remarkably, only two of the 10" blades they sell have this grind.&lt;br /&gt;&lt;br /&gt;I ended up buying two blades: the &lt;a href="http://www.amazon.com/DEWALT-DW7150PT-10-Inch-Combination-8-Inch/dp/B000HCZ4JS/ref=sr_1_1?s=hi&amp;amp;ie=UTF8&amp;amp;qid=1319860124&amp;amp;sr=1-1"&gt;Dewalt 7150PT&lt;/a&gt;&amp;nbsp;($36.04) and the &lt;a href="http://www.rockler.com/product.cfm?page=2359"&gt;Freud LU84R011&lt;/a&gt;&amp;nbsp;($69.99). &amp;nbsp;Both are 50 tooth "combination" blades, designed to be good at both ripping and crosscutting.&lt;br /&gt;&lt;br /&gt;The Dewalt blade also happens to be a "thin kerf" blade -- it makes cuts that are 0.100" wide, compared to the 0.125" kerf of the Freud.&lt;br /&gt;&lt;br /&gt;Once the blades arrived, I took some test cuts in a piece of 3/4" MDF to see how they compared to my original 80-tooth Diablo ATB blade. &amp;nbsp;(Huh, turns out that's also a 0.100" thin-kerf blade. &amp;nbsp;I never noticed before!)&lt;br /&gt;&lt;br /&gt;I cut both single-pass and multi-pass slots:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-VgztK2A4EMM/TqtyAT6roBI/AAAAAAAAhOE/ai0bRk7bxhQ/s1600/IMG_20111028_201808.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-VgztK2A4EMM/TqtyAT6roBI/AAAAAAAAhOE/ai0bRk7bxhQ/s320/IMG_20111028_201808.jpg" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here you can see the profiles left by the blades in single-pass cuts:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Qc1fTvoeNGU/TqtxzoKxJUI/AAAAAAAAhN8/-EtAdxPzhOg/s1600/IMG_20111028_201911.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-Qc1fTvoeNGU/TqtxzoKxJUI/AAAAAAAAhN8/-EtAdxPzhOg/s320/IMG_20111028_201911.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The cut on the right is my ATB Diablo blade. &amp;nbsp;It leaves the deepest V-groove. &amp;nbsp;Measuring the groove in the wood with my calipers, it looks like the bottom of the groove is about 0.016" deeper than the top.&lt;br /&gt;&lt;br /&gt;The cut on the left is the Dewalt ATB/R blade. &amp;nbsp;Disappointingly, it also leaves a pretty significant V-profile, about 0.009". &lt;br /&gt;&lt;br /&gt;The wider middle groove is from the Freud. &amp;nbsp;It's the flattest, but still not perfect; I see about 0.005" difference between the top and bottom.&lt;br /&gt;&lt;br /&gt;On to the multi-pass cuts. &amp;nbsp;I should have been more careful to control the amount I moved between each pass, but the results agree pretty well with the single-pass tests.&lt;br /&gt;&lt;br /&gt;The photo at the top of the page shows the Diablo ATB results. &amp;nbsp;Here's the slot left by the Dewalt:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-jNiauwwGTCM/TqtxZqJBe8I/AAAAAAAAhNs/JbgS9nW2KEs/s1600/IMG_20111028_201937.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-jNiauwwGTCM/TqtxZqJBe8I/AAAAAAAAhNs/JbgS9nW2KEs/s320/IMG_20111028_201937.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;And here's the slot left by the Freud:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-CKZ6yQqhZeE/TqtxMuhXcRI/AAAAAAAAhNk/MV-dFNjtDQg/s1600/IMG_20111028_201946.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-CKZ6yQqhZeE/TqtxMuhXcRI/AAAAAAAAhNk/MV-dFNjtDQg/s320/IMG_20111028_201946.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Conclusion&lt;/b&gt;: I'm not particularly satisfied with the dadoes from the Dewalt blade. &amp;nbsp;The main reason I considered replacing my existing blade was to get flat bottomed channels, and the slots it leaves are bumpy enough that I'd still want to clean them out by hand with a chisel. &amp;nbsp;On the other hand, it's half the price of the Freud, and cuts just as easily.&lt;br /&gt;&lt;br /&gt;The Freud blade is the one I'll keep on my saw (there's another table saw at work I'll use with the Dewalt). &amp;nbsp;I was hoping for completely flat slots, but these are good enough for my needs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4850054142372781903?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4850054142372781903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4850054142372781903' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4850054142372781903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4850054142372781903'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/10/flat-bottom-table-saw-cuts.html' title='Flat bottom table saw cuts'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-q9AyDn5dmDM/Tqtxluq6gXI/AAAAAAAAhN0/jkLvmG0C2-g/s72-c/IMG_20111028_201923.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-794644819244582070</id><published>2011-10-04T14:32:00.000-07:00</published><updated>2012-01-31T00:05:41.234-08:00</updated><title type='text'>linux-alsa-driver-modules not up to date</title><content type='html'>To get &lt;a href="http://credentiality2.blogspot.com/2011/07/nvidia-evga-g210-card-hdmi-audio-and.html"&gt;HDMI audio working on my lucid machine&lt;/a&gt;, I added some PPAs and then did:&lt;br /&gt;&lt;br /&gt;$ sudo apt-get install linux-alsa-driver-modules-$(uname -r)&lt;br /&gt;&lt;br /&gt;That fails currently, since the PPA hasn't kept up to date with the most recent kernel:&lt;br /&gt;&lt;br /&gt;E: Couldn't find package linux-alsa-driver-modules-2.6.32-34-generic-pae&lt;br /&gt;&lt;br /&gt;So for now, I've just downgraded to the old kernel. &amp;nbsp;I also removed linux-image-generic so that it wouldn't automatically upgrade my kernels in the future:&lt;br /&gt;&lt;br /&gt;$ sudo apt-get remove linux-image-generic-pae&lt;br /&gt;&lt;br /&gt;$ sudo apt-get remove linux-image-2.6.32-34-generic-pae&lt;br /&gt;&lt;br /&gt;Update (31 Jan 2012): Good grief, and now it's broken again. &amp;nbsp;The latest kernel is 2.6.32-38. &amp;nbsp;The fix this time was to add the lucid-proposed repository and install&amp;nbsp;linux-backports-modules-alsa-lucid-generic-pae. That installs&amp;nbsp;linux-backports-modules-alsa-2.6.32-38-generic-pae, which seems to take the place of&amp;nbsp;linux-alsa-driver-modules-2.6.32-38-generic-pae.&lt;br /&gt;&lt;br /&gt;To add lucid-proposed in synaptic, it's Settings... Software Sources... Updates... Pre-released updates. &lt;br /&gt;&lt;br /&gt;That adds this line to the /etc/apt/sources.list:&lt;br /&gt;&lt;br /&gt;deb http://us.archive.ubuntu.com/ubuntu/ lucid-proposed restricted main multiverse universe&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-794644819244582070?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/794644819244582070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=794644819244582070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/794644819244582070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/794644819244582070'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/10/linux-alsa-driver-modules-not-up-to.html' title='linux-alsa-driver-modules not up to date'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2510595519660875925</id><published>2011-09-28T02:53:00.000-07:00</published><updated>2011-09-28T02:53:59.380-07:00</updated><title type='text'>Viewing Step (STP) files in Linux</title><content type='html'>Mechanical engineers use step files to send their designs out for manufacturing. &amp;nbsp;FreeCAD is Free Software that will view them. So tonight all I had to do on my Ubuntu Lucid machine was "sudo apt-get install freecad", then run it. &amp;nbsp;It opened up the smaller step files in the&amp;nbsp;&lt;a href="http://code.google.com/p/liquid-galaxy/downloads/detail?name=Google%20Liquid%20Galaxy%203-1%20Mechanicals-Frames.rar&amp;amp;can=2&amp;amp;q=#makechanges"&gt;liquid galaxy mechanical drawings&lt;/a&gt;&amp;nbsp;just fine, although it did hang for quite a while when I tried the bigger ones (and I wasn't patient enough to see if it'd eventually figure it out).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2510595519660875925?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2510595519660875925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2510595519660875925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2510595519660875925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2510595519660875925'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/09/viewing-step-stp-files-in-linux.html' title='Viewing Step (STP) files in Linux'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3163034305533811641</id><published>2011-09-12T18:00:00.000-07:00</published><updated>2011-09-12T18:00:37.764-07:00</updated><title type='text'>The chasm between photo and video</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;One&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; of the reasons the web became so pop&lt;/span&gt;ular is that it made it easy to put photos and text together.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.nsf.gov/od/lpa/news/03/images/mosaic.6beta.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="298" src="http://www.nsf.gov/od/lpa/news/03/images/mosaic.6beta.jpg" width="320" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Now we're straining at the limits of static photos. &amp;nbsp;We want them to be more lifelike, not just paintings on a wall. &amp;nbsp;&lt;/span&gt;The sway of trees, our wandering gaze, the way we bob and turn our heads to get the shape of a thing. &amp;nbsp;We get none of that with a static image.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sure, it's getting a lot easier to embed video. &amp;nbsp;But videos are like movies: they demand our whole attention from start to finish, and then they're done. &amp;nbsp;Videos are entertainment, distractions. &amp;nbsp;I'm talking about ambiance, digitized memories.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Here's what I see happening at the edges of what an image is.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;Cinemagraphs&lt;/b&gt; are just animated GIFs, adding a tiny amount of motion to a scene to give it life.&amp;nbsp;&amp;nbsp;&lt;a href="http://www.fastcodesign.com/1663683/far-better-than-3-d-animated-gifs-that-savor-a-passing-moment"&gt;Cinematograph gallery&lt;/a&gt;,&amp;nbsp;&lt;a href="http://fromme-toyou.tumblr.com/tagged/cinemagraph"&gt;another one&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;a href="http://images.fastcompany.com/upload/barber-pole-615.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="320" src="http://images.fastcompany.com/upload/barber-pole-615.gif" style="cursor: move;" width="229" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;Google Street View was one of the earlier players, showing&amp;nbsp;&lt;b&gt;panoramic photos&lt;/b&gt;&amp;nbsp;on a map. &amp;nbsp;Here's "indoor street view" from the&amp;nbsp;&lt;a href="http://www.theiraqmuseum.com/index.php/pages/floorplan"&gt;Iraq Museum&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.google.com/help/hc/images/earth_user_guide/street_view.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" src="http://www.google.com/help/hc/images/earth_user_guide/street_view.jpg" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Lytro has an after-the-fact&amp;nbsp;&lt;b&gt;refocusable&lt;/b&gt;&amp;nbsp;lightfield camera. &amp;nbsp;They call their photos "living pictures". &amp;nbsp;&lt;a href="http://www.lytro.com/picture_gallery"&gt;Lytro gallery&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.lytro.com/media/lytro/lyt-4/lyt-4.preview.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="320" src="http://www.lytro.com/media/lytro/lyt-4/lyt-4.preview.jpg" width="320" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Several news outlets have been playing with&amp;nbsp;&lt;b&gt;before/after&lt;/b&gt;&amp;nbsp;photos of natural disasters. &amp;nbsp;&lt;a href="http://www.theatlantic.com/infocus/2011/09/japan-earthquake-six-months-later/100146/"&gt;Click-to-toggle before/after&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="http://www.nytimes.com/interactive/2011/03/13/world/asia/satellite-photos-japan-before-and-after-tsunami.html"&gt;Slide before/after&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://cdn.theatlantic.com/static/infocus/jpq6mo091211/s_b02_RTR2QWKI.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="211" src="http://cdn.theatlantic.com/static/infocus/jpq6mo091211/s_b02_RTR2QWKI.jpg" width="320" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;"&lt;b&gt;360 views&lt;/b&gt;" for products are gradually spreading through the online marketplace. &amp;nbsp;Click "360 view" to see an example here:&amp;nbsp;&lt;a href="http://www.ford.com/cars/focus/?intcmp=fv-hpbb-dflt-40mpg-focus"&gt;http://www.ford.com/cars/focus/?intcmp=fv-hpbb-dflt-40mpg-focus&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-atP5jeAbmNI/Tm6eDenGvSI/AAAAAAAAg7c/sKxm7YUX-mk/s1600/360view.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;img border="0" height="274" src="http://2.bp.blogspot.com/-atP5jeAbmNI/Tm6eDenGvSI/AAAAAAAAg7c/sKxm7YUX-mk/s320/360view.png" width="320" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;A sackful of kludges&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Except for the GIFs, every one of these innovative trends has something in common: somebody had to write code to make them work. &amp;nbsp;&lt;/span&gt;Street View and Lytro, and many of the 360-degree product viewers require Flash. &amp;nbsp;The before/after photos seem to have been one-off projects by the news outlets.&lt;br /&gt;&lt;br /&gt;That's why the images I linked to are just static pictures -- only the .gif actually "works" without clicking on the links. &amp;nbsp;(And the .GIFs themselves are also a huge kludge -- it's an ancient image format that only supports 256 colors, and has been a headache for browser vendors for years). &lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;So none of them are really embeddable; you can't easily save a local copy of them, email them to your friends, or put them into a slide presentation. &amp;nbsp;You can link to the pages where they live, but you're out of luck if the owners ever take the pages down.&lt;br /&gt;&lt;br /&gt;Even ordinary product photos suffer from this kludge problem. &amp;nbsp;How many times have you clicked on a product photo to "view bigger", only to get a popup window with the same image, at the same resolution? &amp;nbsp;Some sites use flash, some use popups, some use javascript abominations that obliterate the product's description with a zoomed in image any time your cursor drifts across the product thumbnail.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What does it all mean?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The experimentation is good. &amp;nbsp;People are exploring, seeing what catches on. &amp;nbsp;There's a lot of space in the spectrum between static photos and video, and we're not done exploring it yet.&lt;br /&gt;&lt;br /&gt;We don't even have good names yet. &amp;nbsp;"360 view" is starting to catch on for drag-to-swivel product photos, but there doesn't seem to be any standard way to talk about the before-and-after photos, or any mental framework that lets us explain how they relate to 360 views or cinemagraphs.&lt;br /&gt;&lt;br /&gt;And we need tools. &amp;nbsp;Lots of creative people don't have the programming skills needed to build prototypes like these. &amp;nbsp;And viewers get old and rickety quickly -- flash was the only way to do this stuff a few years ago, but everything you see here could be done just as well in html5. &lt;br /&gt;&lt;br /&gt;My humble contribution to the space is the &lt;a href="http://code.google.com/p/swivel-viewer/"&gt;swivel viewer&lt;/a&gt;, which actually could be coerced to work for most of the things I described here. &amp;nbsp;It proceeds from the notion that a set of images is better than a single one; drag your mouse to flip between images, scroll to zoom. &amp;nbsp;But it's not embeddable, awkward for cinemagraphs and useless for panoramas.&lt;br /&gt;&lt;br /&gt;Eventually we're going to need file formats that bundle these &lt;i&gt;things&lt;/i&gt;&amp;nbsp;-- whatever you call them -- into a single file, browsers that can embed them, and editors that let us create and tweak them.&lt;br /&gt;&lt;br /&gt;I have no idea what that's going to look like, but whoever creates it is going to enable the expression of a lot of pent-up creativity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3163034305533811641?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3163034305533811641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3163034305533811641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3163034305533811641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3163034305533811641'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/09/chasm-between-photo-and-video.html' title='The chasm between photo and video'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-atP5jeAbmNI/Tm6eDenGvSI/AAAAAAAAg7c/sKxm7YUX-mk/s72-c/360view.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6047529624421850077</id><published>2011-08-26T17:32:00.000-07:00</published><updated>2011-08-26T17:32:26.454-07:00</updated><title type='text'>Android ProgressDialog reappears and won't go away</title><content type='html'>You'd think it'd be easy to create a progress dialog in your android app, but as far as I can tell, it's completely broken. &amp;nbsp;Any number of things will cause it to reappear or never go away. &amp;nbsp;Here's an apparently-ignored bug report:&lt;br /&gt;&lt;a href="http://code.google.com/p/android/issues/detail?id=11953"&gt;http://code.google.com/p/android/issues/detail?id=11953&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6047529624421850077?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6047529624421850077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6047529624421850077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6047529624421850077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6047529624421850077'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/08/android-progressdialog-reappears-and.html' title='Android ProgressDialog reappears and won&apos;t go away'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7327710153805694154</id><published>2011-08-16T00:30:00.000-07:00</published><updated>2011-08-16T00:30:45.723-07:00</updated><title type='text'>GWS S125 1T servo</title><content type='html'>Acroname sells the "R298-1T-SERVO", which is actually a GWS S125 1T/2BB. &amp;nbsp;It's different from most servos in that you can tell it to set any angle from 0-360 degrees, whereas most ordinary servos only move 90-180 degrees.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It has a 25-tooth spline, which should make it compatible with futaba arms.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pololu sells it under the correct part number.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7327710153805694154?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7327710153805694154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7327710153805694154' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7327710153805694154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7327710153805694154'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/08/gws-s125-1t-servo.html' title='GWS S125 1T servo'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-240171953234231979</id><published>2011-08-09T01:25:00.000-07:00</published><updated>2011-08-09T01:25:38.622-07:00</updated><title type='text'>Arduino pro mini + bluesmirf + FTDI basic</title><content type='html'>&lt;span class="Apple-style-span" style="background-color: white; color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;Tonight I got my Ubuntu Lucid machine to program a 3.3v Arduino Pro Mini using a 3.3v FTDI Basic USB-&amp;gt;TTL serial interface, and then got them both to talk to a BlueSmirf bluetooth-&amp;gt;TTL serial board.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;To get the bluetooth board to work, I wired it to the USB board so that I could talk to it from both ends: its serial lines and over bluetooth. &amp;nbsp;(See photo)&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;img src="https://lh3.googleusercontent.com/-is5-BisQ_YQ/TkDtdUVRSkI/AAAAAAAAgDg/RZRqm1z8Xzs/s640/IMG_20110809_002117.jpg" /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;I ran minicom and connected to /dev/ttyUSB0, talking to the USB board and thus to the serial lines on the bluesmirf. &amp;nbsp;This bluesmirf was set up to communicate at 57600 baud, which I had to find by trial and error. &amp;nbsp;Once I got the right baud rate, typing "$$$" got me a "CMD" prompt as the manual suggests. &amp;nbsp;I switched it over, so now it uses 115200 baud.&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;On the bluetooth side,&amp;nbsp;I used these instructions to talk to the bluesmirf over bluetooth from my glaptop:&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;a href="http://pratyeka.org/rfcomm/" style="color: #67753a;" target="_blank"&gt;http://pratyeka.org/rfcomm/&lt;/a&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;Once I ran this:&amp;nbsp;sudo rfcomm connect 0 00:06:66:04:B1:C2 1&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;I thought it was going to let me type to the bluetooth device, but really it's just creating /dev/rfcomm0 and then doing nothing. So with that command running in another window, I ran minicom and pointed it at /dev/rfcomm0, at which point I was able to type and see it in the other minicom window (pointed at /dev/ttyUSB0), and vice versa.&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;So that's how I knew the bluesmirf board was working.&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;To get the arduino running on my lucid machine, I had to apt-get install gcc-avr and avr-libc, make sure my JAVA_HOME was set right (because I have sun-java6-jre installed):&amp;nbsp;export JAVA_HOME=/usr/lib/jvm/java-6-&lt;wbr&gt;&lt;/wbr&gt;sun/jre&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;Then I downloaded the 64-bit linux install from here:&amp;nbsp;&lt;a href="http://arduino.cc/en/Main/Software" style="color: #67753a;" target="_blank"&gt;http://arduino.cc/en/&lt;wbr&gt;&lt;/wbr&gt;Main/Software&lt;/a&gt;&amp;nbsp;and unpacked it into a folder in my home directory. &amp;nbsp;Then I cd'ed into it and ran ./arduino. &amp;nbsp;I tried the&amp;nbsp;&lt;a href="http://arduino.cc/en/Tutorial/Blink" style="color: #67753a;" target="_blank"&gt;http://arduino.cc/en/&lt;wbr&gt;&lt;/wbr&gt;Tutorial/Blink&lt;/a&gt;&amp;nbsp;example, and it worked great.&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;Next, I wired the arduino to the bluesmirf as shown here:&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;img src="https://lh3.googleusercontent.com/-A1rw7gC21Eo/TkDtdimg-UI/AAAAAAAAgDg/Y4-v3wbvCOA/s512/IMG_20110809_005053.jpg" /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;I left the bluesmirf TX unconnected to the arduino RX so that it wouldn't interfere when I programmed the arduino. &amp;nbsp;I&amp;nbsp;used the "arduino" IDE to compile the following program, which just dumps some stuff over the serial port any time the reset button is hit. &amp;nbsp;The only change from the stock arduino "ASCII table" example is the change to 115200 baud, and pulling pin 13 high to assert the CTS hardware flow control line on the bluesmirf. &amp;nbsp;(I could also just as easily have run a wire from VCC to that line):&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; ASCII table&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Prints out byte values in all possible formats: &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;* as raw binary values&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;* as ASCII-encoded decimal, hex, octal, and binary values&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;The circuit: &amp;nbsp;No external hardware needed.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;created 2006&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;by Nicholas Zambetti&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;modified 18 Jan 2009&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;by Tom Igoe&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;This example code is in the public domain.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;http: www.zambetti.com=""&gt;&amp;nbsp;&lt;/http:&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;*/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;void setup()&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;{&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.begin(115200);&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; pinMode(13, OUTPUT);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; digitalWrite(13, HIGH);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints title with ending line break&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.println("ASCII Table ~ Character Map");&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;}&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;// first visible ASCIIcharacter '!' is number 33:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;int thisByte = 33;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;// you can also write ASCII characters in single quotes.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;// for example. '!' is the same as 33, so you could also use this:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;//int thisByte = '!'; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;void loop()&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;{&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints value unaltered, i.e. the raw binary version of the&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // byte. The serial monitor interprets all bytes as&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // ASCII, so 33, the first number, &amp;nbsp;will show up as '!'&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.write(thisByte); &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(", dec: ");&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints value as string as an ASCII-encoded decimal (base 10).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // Decimal is the &amp;nbsp;default format for Serial.print() and Serial.println(),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // so no modifier is needed:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(thisByte); &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // But you can declare the modifier for decimal if you want to.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; //this also works if you uncomment it:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // Serial.print(thisByte, DEC); &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(", hex: ");&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints value as string in hexadecimal (base 16):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(thisByte, HEX); &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(", oct: ");&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints value as string in octal (base 8);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(thisByte, OCT); &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.print(", bin: ");&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // prints value as string in binary (base 2)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // also prints ending line break:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Serial.println(thisByte, BIN); &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // if printed last visible character '~' or 126, stop:&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; if(thisByte == 126) { &amp;nbsp; &amp;nbsp; // you could also use if (thisByte == '~') {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; // This loop loops forever and does nothing&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; while(true) {&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; continue;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; }&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; }&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; // go on to the next character&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; thisByte++; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: #202020; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: #202020; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"&gt;Once I flashed the arduino, I connected from my laptop to the bluesmirf over bluetooth, hit the reset button, and saw the table as expected in the minicom window connected to /dev/rfcomm0. &amp;nbsp;First try, even. :)&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-240171953234231979?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/240171953234231979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=240171953234231979' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/240171953234231979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/240171953234231979'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/08/arduino-pro-mini-bluesmirf-ftdi-basic.html' title='Arduino pro mini + bluesmirf + FTDI basic'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh3.googleusercontent.com/-is5-BisQ_YQ/TkDtdUVRSkI/AAAAAAAAgDg/RZRqm1z8Xzs/s72-c/IMG_20110809_002117.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1983209448615076414</id><published>2011-07-26T17:26:00.000-07:00</published><updated>2011-07-26T17:26:40.315-07:00</updated><title type='text'>Singleton bash script</title><content type='html'>Sometimes it's important to make sure only one copy of a shell script runs at any given time.  Here's an elegant way to find and kill any other processes running as the same name as your script:&lt;br /&gt;&lt;pre&gt;kill $(pidof -x -o '%PPID' $0) &gt;/dev/null 2&gt;/dev/null&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1983209448615076414?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1983209448615076414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1983209448615076414' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1983209448615076414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1983209448615076414'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/07/singleton-bash-script.html' title='Singleton bash script'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-506874235324637524</id><published>2011-07-25T22:25:00.000-07:00</published><updated>2011-07-25T22:25:13.091-07:00</updated><title type='text'>nVidia EVGA g210 card: HDMI audio and sync-to-vblank in lucid</title><content type='html'>To get the HDMI audio to work on &lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16814130605"&gt;this g210 video card&lt;/a&gt; in Ubuntu Lucid (10.04), I first had to add this PPA and install updated alsa modules:&lt;br /&gt;&lt;pre&gt;add-apt-repository ppa:team-iquik/alsa&lt;br /&gt;add-apt-repository ppa:ubuntu-audio-dev/ppa&lt;br /&gt;apt-get update&lt;br /&gt;apt-get upgrade&lt;br /&gt;apt-get install linux-alsa-driver-modules-$(uname -r) --force-yes&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then I had to set the module options correctly for my card:&lt;br /&gt;&lt;pre&gt;$ more /etc/modprobe.d/sound.conf &lt;br /&gt;options snd-hda-intel enable_msi=0 probe_mask=0xffff,0xfff2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once I did all that, I saw a single HDMI audio output:&lt;br /&gt;&lt;pre&gt;$ aplay -l&lt;br /&gt;**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;card 0: SB [HDA ATI SB], device 0: VT1828S Analog [VT1828S Analog]&lt;br /&gt;  Subdevices: 1/1&lt;br /&gt;  Subdevice #0: subdevice #0&lt;br /&gt;card 0: SB [HDA ATI SB], device 1: VT1828S Digital [VT1828S Digital]&lt;br /&gt;  Subdevices: 1/1&lt;br /&gt;  Subdevice #0: subdevice #0&lt;br /&gt;card 0: SB [HDA ATI SB], device 2: VT1828S HP [VT1828S HP]&lt;br /&gt;  Subdevices: 1/1&lt;br /&gt;  Subdevice #0: subdevice #0&lt;br /&gt;card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]&lt;br /&gt;  Subdevices: 1/1&lt;br /&gt;  Subdevice #0: subdevice #0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And could test it:&lt;br /&gt;&lt;pre&gt;speaker-test -c2 -twav -Dplughw:1,3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(Before I got the module options correct, I saw several HDMI audio outputs, and none of them would work.)&lt;br /&gt;&lt;br /&gt;To get it to work with flash (for things like youtube), I had to create an /etc/asound.conf:&lt;br /&gt;&lt;pre&gt;$ more /etc/asound.conf &lt;br /&gt;pcm.!default hdmi:NVidia&lt;br /&gt;pcm:iec958 hdmi:NVidia&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then audio worked all the way.  One annoyance is that the module hangs for ~5s when loading, so it increases my boot time.&lt;br /&gt;&lt;br /&gt;Now that I could hear the youtube videos, I just had to get rid of the annoying tearing artifacts by telling the graphics to sync to the vertical blank interval.  To do that, I enabled "Sync to VBlank" in "X Server XVideo Settings" and "OpenGL Settings", then installed compizconfig-settings-manager, ran "ccsm" and enabled it under General... General... Display Settings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-506874235324637524?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/506874235324637524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=506874235324637524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/506874235324637524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/506874235324637524'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/07/nvidia-evga-g210-card-hdmi-audio-and.html' title='nVidia EVGA g210 card: HDMI audio and sync-to-vblank in lucid'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3686502208490168900</id><published>2011-07-16T23:49:00.000-07:00</published><updated>2011-07-16T23:49:27.016-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gedit'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='jhbuild'/><category scheme='http://www.blogger.com/atom/ns#' term='lucid'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='gnome'/><category scheme='http://www.blogger.com/atom/ns#' term='10.04'/><title type='text'>Building gnome from git on Ubuntu Lucid</title><content type='html'>Lately I've been trying to build gedit from its source repository so that I can help improve it.&lt;br /&gt;&lt;br /&gt;It's been hugely painful, I'm sad to say.  Downloading from git and running autogen.sh, I got errors about my gnome libraries not being new enough.  Fair enough, so I installed Ubuntu Natty on a spare hard disk.  No luck, so I updated to the alpha of Ubuntu Oneiric.  That actually worked OK, except that Oneiric is so alpha that it's very unstable.&lt;br /&gt;&lt;br /&gt;Finally I asked on IRC, and the devs told me I needed to build with "jhbuild", the build manager for gnome.  That failed on my Hardy machine, but that's no big deal since Hardy is pretty ancient now.&lt;br /&gt;&lt;br /&gt;Lucid it is!  I did a clean install on a separate hard disk, and started in with jhbuild.  I used the sample.jhbuildrc file, pointing the install directories to my home directory instead of /opt.  It chugged along for a while, checking out and building all of gedit's dependencies.  Then it bombed while building gtk+/gdk with:&lt;br /&gt;&lt;pre&gt;/usr/share/gir-1.0/GdkPixbuf-2.0.gir: Incompatible version 1.0 (supported: 1.2)&lt;br /&gt;&lt;/pre&gt;The folks at irc.gnome.org helped me trace the problem to jhbuild/config.py, which sets XDG_DATA_DIRS around line 368.  Prepending /usr/share to XDG_DATA_DIRS means that the system data dirs take precedence, and thus the GdkPixbuf compiled by jhbuild doesn't get detected.&lt;br /&gt;&lt;br /&gt;Commenting out the XDG_DATA_DIRS stuff and adding this to my .jhbuildrc solved the problem:&lt;br /&gt;addpath('XDG_DATA_DIRS', os.path.join(prefix, 'share'))&lt;br /&gt;addpath('XDG_DATA_DIRS', os.path.join(prefix, 'usr/share'))&lt;br /&gt;&lt;br /&gt;Also, it looks to me like there's a bug in the XDG_CONFIG_DIRS around line 378, where it prepends /etc to XDG_DATA_DIRS instead of XDG_CONFIG_DIRS.&lt;br /&gt;&lt;br /&gt;Apart from that, I've had to babysit jhbuild as it builds NetworkManager, libproxy and just about everything else in gnome, occasionally bombing out until I track down the right -dev packages to install.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3686502208490168900?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3686502208490168900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3686502208490168900' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3686502208490168900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3686502208490168900'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/07/building-gnome-from-git-on-ubuntu-lucid.html' title='Building gnome from git on Ubuntu Lucid'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5446683433584862412</id><published>2011-07-15T00:50:00.000-07:00</published><updated>2011-07-15T00:50:14.187-07:00</updated><title type='text'>Oneiric Ocelot installer failure</title><content type='html'>Running the daily desktop build of the not-yet-released Ubuntu Oneiric (11.10), I kept getting install failures.  /var/log/syslog showed that the problem was in /usr/share/ubiquity/install.py line 372.  It was failing because the unlink / readlink / symlink wasn't working on /var/run and /var/lock.&lt;br /&gt;&lt;br /&gt;Editing it as root, I changed it to:&lt;br /&gt;&lt;pre&gt;try:&lt;br /&gt;  os.unlink(targetpath)&lt;br /&gt;except:&lt;br /&gt;  print "Can't unlink " + targetpath&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And:&lt;br /&gt;&lt;pre&gt;try:&lt;br /&gt;  linkto = os.readlink(sourcepath)&lt;br /&gt;  os.symlink(linkto, targetpath)&lt;br /&gt;except:&lt;br /&gt;  print "symlink " + sourcepath + linkto + targetpath&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And then it seemed to work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5446683433584862412?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5446683433584862412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5446683433584862412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5446683433584862412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5446683433584862412'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/07/oneiric-ocelot-installer-failure.html' title='Oneiric Ocelot installer failure'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6105934576124911530</id><published>2011-07-06T20:38:00.001-07:00</published><updated>2011-07-06T20:38:40.007-07:00</updated><title type='text'>Native android C program using ndk (update for android-ndk-r5c-linux-x86)</title><content type='html'>Back in August 2010, I posted &lt;a href="http://credentiality2.blogspot.com/2010/08/native-android-c-program-using-ndk.html"&gt;"Native android C program using ndk"&lt;/a&gt;, wherein I described how to compile C programs as native Android binaries.&lt;br /&gt;&lt;br /&gt;The paths changed a lot with android-ndk-r5c-linux-x86, so I updated agcc.pl and called it &lt;a href="http://android-cruft.googlecode.com/svn/trunk/agcc/agcc2.pl"&gt;agcc2.pl&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Make sure you update the path to your NDK install in that script, but then you should be able to use it to compile the "hello, world" program as described in the original blog post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6105934576124911530?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6105934576124911530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6105934576124911530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6105934576124911530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6105934576124911530'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/07/native-android-c-program-using-ndk.html' title='Native android C program using ndk (update for android-ndk-r5c-linux-x86)'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1657862702904078951</id><published>2011-06-21T22:37:00.000-07:00</published><updated>2011-06-21T22:37:49.287-07:00</updated><title type='text'>Google App Engine for Business error with appcfg.py</title><content type='html'>I have "App Engine for Business" access at work, which lets me create internal-only App Engine apps.  &lt;br /&gt;&lt;br /&gt;But upon creating a new internal app, I kept getting "Error 404" messages about "This application does not exist" when I tried to use appcfg update to upload it.&lt;br /&gt;&lt;br /&gt;Turns out there's a special syntax for the application name in the app.yaml file.  I changed the "application: myapp" line to "application: mycompany.com:myapp" and then it worked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1657862702904078951?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1657862702904078951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1657862702904078951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1657862702904078951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1657862702904078951'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/06/google-app-engine-for-business-error.html' title='Google App Engine for Business error with appcfg.py'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8568270442795200039</id><published>2011-06-15T22:03:00.000-07:00</published><updated>2011-06-15T22:03:43.817-07:00</updated><title type='text'>Regarding Bryce</title><content type='html'>My apologies in advance.&lt;br /&gt;&lt;br /&gt;Boyce: Bob, I'd like you to meet my brother, Bruce.&lt;br /&gt;Bruce: Bob, I'm Bruce Bryce.  It's a pleasure.&lt;br /&gt;Bob: Bob Bluth, Bruce.  Likewise.  Where are you from?&lt;br /&gt;Boyce: Bruce is from Blythe.&lt;br /&gt;Bruce: Yes, I'm a lumber man.  I grow Spruce in Blythe.&lt;br /&gt;Bob: Blue Spruce?&lt;br /&gt;Bruce: Both Blue and True Spruce.  And in fact, I'm working on a new variety that's a mix of the two.&lt;br /&gt;Bob: A True Blue Spruce?&lt;br /&gt;Bruce: Exactly.&lt;br /&gt;Bob: How's it going?&lt;br /&gt;Bruce: It's back-breaking work.  I lost half my trees this year to a blight.&lt;br /&gt;Bob: That's terrible!  What type of blight?&lt;br /&gt;Bruce: Nobody knows.  They're just calling it the Blythe Blight.&lt;br /&gt;Bob: How did the True Blue do?&lt;br /&gt;Bruce: It beat both the True and the Blue.  In fact, it did so well I had to rename it.  We're going to call it Bruce Bryce's Blythe Blight Beating True Blue Spruce.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8568270442795200039?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8568270442795200039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8568270442795200039' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8568270442795200039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8568270442795200039'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/06/regarding-bryce.html' title='Regarding Bryce'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4971954412758921431</id><published>2011-06-04T15:42:00.000-07:00</published><updated>2011-06-04T15:42:14.976-07:00</updated><title type='text'>Tax burden stats</title><content type='html'>Here are tables for &lt;a href="http://www.taxpolicycenter.org/taxfacts/displayafact.cfm?Docid=205"&gt;tax as a slice of GDP&lt;/a&gt; and &lt;a href="http://www.taxpolicycenter.org/taxfacts/displayafact.cfm?DocID=456&amp;Topic2id=20&amp;Topic3id=22"&gt;tax rates by income level&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;In terms of GDP, the last two years seem to be outliers, probably due to the economy tanking. The rest of the decade went from 8.0 to 10.2, pretty much exactly in line with the rest of the last 30 years.&lt;br /&gt;&lt;br /&gt;The table of tax rates by income level is much more striking: the poorest 20% saw their taxes cut nearly in half since 1980, while the richest 20% saw only about 10% reduction in tax burden. So basically, the tax system got a whole lot more progressive in the last 30 years. (Progressive = the more you make, the higher your tax rate.) That's interesting in context of the stuff I've been seeing from the left lately about how we need to raise taxes on the rich, since it appears the burden has been shifting that way already for the last few decades.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4971954412758921431?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4971954412758921431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4971954412758921431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4971954412758921431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4971954412758921431'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/06/tax-burden-stats.html' title='Tax burden stats'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6260566631168655339</id><published>2011-06-01T18:13:00.000-07:00</published><updated>2011-06-01T18:13:41.596-07:00</updated><title type='text'>Android "SetupTask cannot be found" error</title><content type='html'>I recently checked in an android project, and when I checked it out elsewhere to check it over, I got the following error when trying to build it with "ant debug" per the &lt;a href="http://developer.android.com/guide/developing/projects/projects-cmdline.html"&gt;command-line build instructions&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;taskdef class com.android.ant.SetupTask cannot be found&lt;br /&gt; using the classloader AntClassLoader&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The solution was to run "android update project --path ." to update the project to work in the new location.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6260566631168655339?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6260566631168655339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6260566631168655339' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6260566631168655339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6260566631168655339'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/06/android-setuptask-cannot-be-found-error.html' title='Android &quot;SetupTask cannot be found&quot; error'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-628023198482913891</id><published>2011-04-04T09:58:00.000-07:00</published><updated>2011-04-06T02:04:38.192-07:00</updated><title type='text'>Prepaid SIM in Spain</title><content type='html'>As far as I can tell, the best way to get cellular/internet service for your unlocked GSM phone while in Spain is to head down to one of the ubiquitous Carrefour supermarkets and get a prepaid SIM card.  I saw a variety of prices, like 10 Euro for a SIM card plus 10 Euro of credit on the account.  We ended up paying 1EUR for the SIM card and putting 5EUR credit on it.&lt;br /&gt;&lt;br /&gt;Calls are 0.08EUR/minute, but the best part is the internet access.  After adding a "carrefourinternet" APN to my phone, 3g internet came right up.  Their website has conflicting claims, but it appears that it costs either 0.50EUR/day for 20MB, or 1EUR/day for 100MB.  Above that, it still works, but the rate is capped at 128Kb/sec, which still isn't bad.  And for 19EUR, I can get 1GB of high speed connectivity on top of that, so that I don't hit the cap so much.&lt;br /&gt;&lt;br /&gt;http://www.carrefour.es/telecom/internet-movil/index.html&lt;br /&gt;&lt;br /&gt;Update: The Carrefour website is misleading.  Apparently the 19EUR/1GB deal is only for USB cell modems.  Instead I had to text "ALTA BONOPRE" to 22864, which buys 300MB for a month for 6EUR.  And if it runs out, I think I can text "BAJA BONOPRE" to go back to 20MB/day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-628023198482913891?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/628023198482913891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=628023198482913891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/628023198482913891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/628023198482913891'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/04/prepaid-sim-in-spain.html' title='Prepaid SIM in Spain'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-178663712841981400</id><published>2011-03-21T23:39:00.000-07:00</published><updated>2011-03-21T23:39:12.847-07:00</updated><title type='text'>Daily wtf</title><content type='html'>My wife is taking a shell programming class, and one of the questions on the homework was:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How would you use fgrep to replace this command? grep '[a-z]\{9\}'&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now, fgrep is grep without the regular expressions.  So this seems to be a very strange question.  Nevertheless, let us assume that there is some hidden wisdom the problem is designed to help us uncover.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Approach 1:&lt;/b&gt; can we turn regexes back on with a flag?  The manpage is unclear on this point; it tells us that fgrep is equivalent to grep -F, but doesn't specify what happens if we were to give, say, grep -F -E.  At least in ubuntu lucid, it produces "grep: conflicting matchers specified".&lt;br /&gt;&lt;br /&gt;Trying 'fgrep -E' produces 'fgrep: invalid option -- 'E'', which was my first hint that fgrep is /not/ in fact exactly equivalent to 'grep -F'. /bin/fgrep is in fact its own binary, about half the size of /bin/grep.&lt;br /&gt;&lt;br /&gt;Now, the paragraph talking about fgrep in the manpage looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;       In  addition,  three  variant  programs  egrep,  fgrep  and  rgrep  are&lt;br /&gt;       available.   egrep  is  the  same  as  grep -E.   fgrep  is the same as&lt;br /&gt;       grep -F.  rgrep is the same as grep -r.  Direct  invocation  as  either&lt;br /&gt;       egrep  or  fgrep  is  deprecated,  but  is provided to allow historical&lt;br /&gt;       applications that rely on them to run unmodified.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note the last sentence, which tells us that if we call grep as fgrep, it should behave like fgrep.  This turns out not to be the case.  Symlinking or simply copying grep to fgrep doesn't appear to change grep's behavior at all.  So that's a second bug in the manpage.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Approach 2:&lt;/b&gt; Perhaps the instructor really does want us to avoid regexes entirely.  The manpage has this as the description of -F:&lt;br /&gt;&lt;pre&gt;        -F, --fixed-strings&lt;br /&gt;              Interpret PATTERN as a  list  of  fixed  strings,  separated  by&lt;br /&gt;              newlines,  any  of  which is to be matched.  (-F is specified by&lt;br /&gt;              POSIX.)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Separated by newlines?  That's a little weird.  I can't actually figure out how to put a newline into a command line argument.  Inserting a literal one with ^V doesn't seem to do the trick, nor do things like fgrep 'a\nb'.  So as far as I can tell, that's another bug, although fgrep -e pattern1 -e pattern2 does seem to work.&lt;br /&gt;&lt;br /&gt;The other way to specify multiple patterns is to put them in a file, and then use fgrep -f pattern-file.&lt;br /&gt;&lt;br /&gt;So we could, in theory, enumerate all the possible matching strings in a file and thus avoid the regex.  A file with all 9-letter lowercase words, one per line, has 26^9 = 5.4T  lines of 10 characters each, for a total of 54TB.  Newegg currently has a 2TB disk for $69.99, so not counting tax, shipping, or filesystem overhead, a cool $1900.05 worth of disk would be enough to hold the pattern file.  There do also appear to be several options for transparently compressed filesystems in linux, which makes the problem much more manageable.&lt;br /&gt;&lt;br /&gt;You could also give fgrep -f - and let it read the patterns from stdin, piping in a list generated on the fly (although it's not clear if this would violate the terms of the question, since it requires more than just fgrep, unless you're a very determined typist).&lt;br /&gt;&lt;br /&gt;The next problem is what fgrep does with the patterns.  If it copies them into RAM or puts them into some sort of data structure (like, say, a search tree), you're going to need a whole lot of swap space.  But this limitation might in turn be overcome by compressed swap.&lt;br /&gt;&lt;br /&gt;And of course all of this assumes a 64-bit OS, and an implementation of fgrep that can handle trillions of patterns.&lt;br /&gt;&lt;br /&gt;So my answer to the question How would you use fgrep to replace this command? grep '[a-z]\{9\}' would have to be:&lt;br /&gt;&lt;br /&gt;Enumerate all 9-letter lowercase words to a 54 terabyte text file called 'patterns'.  Then run fgrep -f patterns, ensuring there's enough memory available to store the set of matching patterns.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-178663712841981400?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/178663712841981400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=178663712841981400' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/178663712841981400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/178663712841981400'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/03/daily-wtf.html' title='Daily wtf'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2953917240780390866</id><published>2011-03-18T18:14:00.000-07:00</published><updated>2011-03-18T18:14:12.333-07:00</updated><title type='text'>Xenarc 702tsv on Lucid with evtouch driver</title><content type='html'>I got a Xenarc touchscreen working pretty well, except that intermittently (and usually after a reboot), the mouse pointer would behave erratically, while other times the touch behavior would work just fine.&lt;br /&gt;&lt;br /&gt;The trick was to create an /etc/modprobe.d/xenarc.conf with:&lt;br /&gt;&lt;pre&gt;# Stop messing with my Xenarc touch screen&lt;br /&gt;blacklist usbtouchscreen&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(I found that suggestion on &lt;a href="http://samiux.blogspot.com/2010/07/howto-ubuntu-1004-on-gigabyte-touchnote.html"&gt;Samiux's blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now it seems to work consistently across reboots.  The rest of the process was to set up a /usr/lib/X11/xorg.conf.d/11-touchkit.conf with:&lt;br /&gt;&lt;pre&gt;Section "InputClass"&lt;br /&gt;       Identifier "Touchkit Touch"&lt;br /&gt;       MatchIsTablet   "on"&lt;br /&gt;       MatchDevicePath "/dev/input/event*"&lt;br /&gt;       Driver  "evtouch"&lt;br /&gt;       Option  "ReportingMode" "Raw"&lt;br /&gt;       Option  "Emulate3Buttons"&lt;br /&gt;       Option  "Emultate3Timeout"      "50"&lt;br /&gt;       Option  "SendCoreEvents"        "On"&lt;br /&gt;       Option  "TapTimer"              "200"&lt;br /&gt;       Option  "LongTouchTimer"        "400"&lt;br /&gt;       Option  "MinX"                  "140"&lt;br /&gt;       Option  "MinY"                  "193"&lt;br /&gt;       Option  "MaxX"                  "1550"&lt;br /&gt;       Option  "MaxY"                  "1750"&lt;br /&gt;EndSection&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that I've tried ~6 different 702TSV units, and they all seem to more or less work with these calibration parameters.&lt;br /&gt;&lt;br /&gt;And then this is my /etc/X11/xorg.conf:&lt;br /&gt;&lt;pre&gt;Section "ServerLayout"&lt;br /&gt;    Identifier     "Layout0"&lt;br /&gt;    Screen      0  "Screen0" 0 0&lt;br /&gt;    InputDevice    "Keyboard0" "CoreKeyboard"&lt;br /&gt;    InputDevice    "Mouse0" "CorePointer"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Files"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;    # generated from default&lt;br /&gt;    Identifier     "Mouse0"&lt;br /&gt;    Driver         "mouse"&lt;br /&gt;    Option         "Protocol" "auto"&lt;br /&gt;    Option         "Device" "/dev/psaux"&lt;br /&gt;    Option         "Emulate3Buttons" "no"&lt;br /&gt;    Option         "ZAxisMapping" "4 5"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "InputDevice"&lt;br /&gt;    # generated from default&lt;br /&gt;    Identifier     "Keyboard0"&lt;br /&gt;    Driver         "kbd"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Monitor"&lt;br /&gt;    Identifier     "Xenarc700"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Device"&lt;br /&gt;    Identifier     "Device0"&lt;br /&gt;    Driver         "nvidia"&lt;br /&gt;    VendorName     "NVIDIA Corporation"&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "Screen"&lt;br /&gt;    Identifier     "Screen0"&lt;br /&gt;    Device         "Device0"&lt;br /&gt;    Monitor        "Xenarc700"&lt;br /&gt;    DefaultDepth    24&lt;br /&gt;    SubSection     "Display"&lt;br /&gt;        Depth       24&lt;br /&gt;        # The native resolution of a Xenarc 702TSV is 800x480, but&lt;br /&gt;        # I couldn't find any modes that'd work.&lt;br /&gt;        Modes       "800x600"&lt;br /&gt;    EndSubSection&lt;br /&gt;EndSection&lt;br /&gt;&lt;br /&gt;Section "ServerFlags"&lt;br /&gt;    Option         "BlankTime" "0"&lt;br /&gt;    Option         "StandbyTime" "0"&lt;br /&gt;    Option         "SuspendTime" "0"&lt;br /&gt;    Option         "OffTime" "0"&lt;br /&gt;EndSection&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2953917240780390866?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2953917240780390866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2953917240780390866' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2953917240780390866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2953917240780390866'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/03/xenarc-702tsv-on-lucid-with-evtouch.html' title='Xenarc 702tsv on Lucid with evtouch driver'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4816927826810228793</id><published>2011-02-27T15:00:00.000-08:00</published><updated>2011-02-27T15:00:04.272-08:00</updated><title type='text'>Shopbot dresser plans</title><content type='html'>A few weeks ago I built a pair of 5-drawer dressers using the shopbot.  &lt;br /&gt;I used apple-backed MDF for one set, and pecan-backed for the other.&lt;br /&gt;&lt;br /&gt;You can find all the sketchup, partworks and shopbot files in the .zip file on this &lt;a href="https://docs.google.com/leaf?id=0B8R6VSvTZHZWOTRiN2ExYzYtZjgwMS00YTA0LWExNDEtMTM4YjRhNWZkZWY5&amp;hl=en"&gt;download page&lt;/a&gt;.  Public domain, use them however you like.  Note how I use wrapper.sbp files to control the feeds, speeds and depth of cut.&lt;br /&gt;&lt;br /&gt;I cut the whole project with a 1/4" end mill, then chamfered the sides of the drawer fronts on the table saw.  Tolerancing was the trickiest part of this project for me; I kept having to trim pieces or expand slots slightly.  I improved things by the second dresser, but it still may not be perfect.&lt;br /&gt;&lt;br /&gt;I believe &lt;a href="http://www.homedepot.com/h_d1/N-5yc1v/R-202200643/h_d2/ProductDisplay?langId=-1&amp;storeId=10051&amp;catalogId=10053"&gt;these&lt;/a&gt; are the drawer slides I got from Home Depot.  They're nice and smooth once I got the tolerances right.&lt;br /&gt;&lt;br /&gt;&lt;img src="https://lh4.googleusercontent.com/_oXIW_jM0QDA/TWrTmSnERGI/AAAAAAAAXDk/jUVhCgmagxQ/s640/IMG_20110103_212421.jpg"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://lh5.googleusercontent.com/_oXIW_jM0QDA/TWrTsj9ICMI/AAAAAAAAXDw/Slm1LZj42WE/s640/IMG_20110103_212500.jpg"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://lh3.googleusercontent.com/_oXIW_jM0QDA/TWrUT4QhmfI/AAAAAAAAXD8/GdRHKp9LTQQ/s640/IMG_20110103_212532.jpg"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://lh3.googleusercontent.com/_oXIW_jM0QDA/TWrUuFYISTI/AAAAAAAAXEU/FlVA5649YgY/s640/IMG_20110105_132718.jpg"/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4816927826810228793?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4816927826810228793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4816927826810228793' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4816927826810228793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4816927826810228793'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/02/shopbot-dresser-plans.html' title='Shopbot dresser plans'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh4.googleusercontent.com/_oXIW_jM0QDA/TWrTmSnERGI/AAAAAAAAXDk/jUVhCgmagxQ/s72-c/IMG_20110103_212421.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5351086114047408053</id><published>2011-02-25T15:22:00.000-08:00</published><updated>2011-02-25T15:22:37.497-08:00</updated><title type='text'>Using rsync to copy only certain extensions</title><content type='html'>I had a directory structure like this:&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;a/foo/bar/baz.txt&lt;br /&gt;b/bar/asdf.jpg&lt;br /&gt;c/qwerty/bletch.txt&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;and I wanted to rsync only the .txt files to my local machine:&lt;br /&gt;&lt;pre&gt;a/foo/bar/baz.txt&lt;br /&gt;c/qwerty/bletch.txt&lt;br /&gt;&lt;/pre&gt;There are lots of search results for the topic, but most didn't work right -- rsync -vv kept telling me that my --exclude="*" rule was excluding everything.  &lt;a href="http://masstransmit.com/garage_blog/rsync-quirks/"&gt;This post&lt;/a&gt; gives the correct details.  You need to explicitly include the directories you want, or just --include='*/', then --include='*.txt', then --exclude='*'.  You may end up with a bunch of empty directories; I haven't figured out how to efficiently avoid that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5351086114047408053?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5351086114047408053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5351086114047408053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5351086114047408053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5351086114047408053'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/02/using-rsync-to-copy-only-certain.html' title='Using rsync to copy only certain extensions'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7236209427476990174</id><published>2011-02-15T23:23:00.000-08:00</published><updated>2011-06-25T13:21:04.991-07:00</updated><title type='text'>ant 1.8 on ubuntu lucid (10.04)</title><content type='html'>UPDATE: Note the comment below which points out that you can simply "apt-get install ant1.8".&lt;br /&gt;&lt;br /&gt;Trying to build a "Hello, World" app in Android, I built a skeletal project per &lt;a href="http://developer.android.com/guide/developing/other-ide.html"&gt;Developing In Other IDEs&lt;/a&gt; page:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;android create project \&lt;br /&gt;--target 1 \&lt;br /&gt;--name MyAndroidApp \&lt;br /&gt;--path ./MyAndroidAppProject \&lt;br /&gt;--activity MyAndroidAppActivity \&lt;br /&gt;--package com.example.myandroid&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After "apt-get install ant", I tried to build, but got this error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ ant debug&lt;br /&gt;Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-openjdk/lib/tools.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Android seems to want the sun version of the JDK, which I had installed earlier, but ant was pointed at the openjdk version.  I fixed that error with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.22&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The next obstacle was:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ ant debug&lt;br /&gt;Buildfile: build.xml&lt;br /&gt;&lt;br /&gt;BUILD FAILED&lt;br /&gt;/home/jholt/android-sdk-linux_x86/asdf/MyAndroidAppProject/build.xml:82: The Android Ant-based build system requires Ant 1.8.0 or later. Current version is 1.7.1&lt;br /&gt;&lt;br /&gt;Total time: 0 seconds&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;a href="https://launchpad.net/ubuntu/maverick/amd64/ant/1.8.0-4"&gt;ant 1.8 package from Maverick&lt;/a&gt; seems to install just fine.  Don't forget the &lt;a href="https://launchpad.net/ubuntu/maverick/i386/ant-optional/1.8.0-4"&gt;ant-optional&lt;/a&gt; package, or else you'll get errors like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ ant build&lt;br /&gt;Invalid implementation version between Ant core and Ant optional tasks.&lt;br /&gt; core    : 1.8.0 in file:/usr/share/ant/lib/ant.jar&lt;br /&gt; optional: 1.7.1 in file:/usr/share/ant/lib/ant-nodeps.jar&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7236209427476990174?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7236209427476990174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7236209427476990174' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7236209427476990174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7236209427476990174'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2011/02/ant-18-on-ubuntu-lucid-1004.html' title='ant 1.8 on ubuntu lucid (10.04)'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2270514914713827645</id><published>2010-12-23T15:52:00.000-08:00</published><updated>2010-12-23T15:52:48.146-08:00</updated><title type='text'>If you need newgrp, you dun goofed (and "setuidgid" may be the culprit)</title><content type='html'>Recently, on a machine with custom upstart init scripts, I couldn't figure out why I couldn't access serial ports or USB devices, even though my username was in the dialout and plugdev groups in /etc/group.&lt;br /&gt;&lt;br /&gt;Running the "groups" command, I could see that my groupset only contained my own personal group:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ groups&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I found that I could run "newgrp dialout" to get it added to my groupset:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ newgrp dialout&lt;br /&gt;$ groups&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;dialout credentiality&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And looking online, I found various tricks people would use to run the commands they needed using newgrp. &amp;nbsp;(It's not trivial, since newgrp insists on creating a subshell).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But I kept getting the sense that newgrp should almost never be necessary anymore, now that modern unix systems have the notion of a groupset.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Turns out the culprit was "setuidgid", which we were using in the upstart scripts to run programs as me. &amp;nbsp;They said things like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;exec setuidgid credentiality startx&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now that I know to look for it, setuidgid's manpage points out that it "remov[es] all supplementary groups". &amp;nbsp;Which isn't very helpful if, for instance, a process needs to access files from both the "dialout" and "plugdev" groups.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fortunately, there are several alternatives to setuidgid that preserve the group memberships you expect, and you can use the "groups" command to verify that:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# setuidgid credentiality groups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# su -c groups credentiality&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality adm disk dialout cdrom floppy sudo audio dip video plugdev&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# sudo -u credentiality groups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality adm disk dialout cdrom floppy sudo audio dip video plugdev&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# start-stop-daemon -c credentiality -S --exec /usr/bin/groups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality adm disk dialout cdrom floppy sudo audio dip video plugdev&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# # chpst is in package runit (yet another init system, ugh.), and lets you specify a list of groups explicitly:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;# chpst -u credentiality:credentiality:plugdev:dialout groups&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;credentiality plugdev dialout&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2270514914713827645?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2270514914713827645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2270514914713827645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2270514914713827645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2270514914713827645'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/12/if-you-need-newgrp-you-dun-goofed-and.html' title='If you need newgrp, you dun goofed (and &quot;setuidgid&quot; may be the culprit)'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4394320096398963965</id><published>2010-12-02T14:13:00.000-08:00</published><updated>2010-12-04T04:29:13.519-08:00</updated><title type='text'>Carmichael numbers and Fermat primality</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;I did some recreational mathematics today, and created this plot, showing the number of values for which a^(n-1) = 1 (mod n), for all composite n in the range [3..10000]:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_oXIW_jM0QDA/TPgYrMHiH3I/AAAAAAAAW2k/1u8HphQg8wM/s1600/mystery1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="http://2.bp.blogspot.com/_oXIW_jM0QDA/TPgYrMHiH3I/AAAAAAAAW2k/1u8HphQg8wM/s320/mystery1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The formula a^(n-1) mod n appears in &lt;a href="http://en.wikipedia.org/wiki/Fermat's_little_theorem"&gt;Fermat's Little Theorem&lt;/a&gt;, which says that for prime values of n, the result will always be 1, no matter what a you choose. &amp;nbsp;If you get a value other than 1, you know that n is composite.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;That's neat because it lets us test whether a given n is composite much more quickly than by trying to factor it. &amp;nbsp;We call that the &lt;a href="http://en.wikipedia.org/wiki/Fermat_primality_test"&gt;Fermat Primality Test&lt;/a&gt;. &amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;However, the converse doesn't always hold: sometimes a^(n-1)=1 (mod n) even if n is composite. &amp;nbsp;When &amp;nbsp;that happens for some a and n, we say that a is a false witness for n, since it incorrectly suggests that n might be prime.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;And that's what the above graph shows: how many false witnesses there are for each value n up to 10,000. &amp;nbsp;In particular, I scaled the y axis so that it shows the percentage of relatively prime a values that are false witnesses.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Carmichael Numbers&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Most interesting are the vertical lines in the graph that reach all the way to the top. &amp;nbsp;Those are the falsest of the pseudoprimes (with respect to the Fermat test). &amp;nbsp;They're called the &lt;a href="http://en.wikipedia.org/wiki/Carmichael_number"&gt;Carmichael Numbers&lt;/a&gt;, and I've always found them fascinating, because the smallest of them is 561! &amp;nbsp;That's the leftmost line in the graph that reaches all the way to the top.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Just how prime are you?&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The other thing I was surprised to find in this graph are what we might call the halfway-prime numbers -- numbers for which half of the witnesses will suggest primality with the Fermat test. &amp;nbsp;And there are one-third-prime numbers, and so on.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Merry Christmas!&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;All that graphing got me wondering how often a^(n-1) produces numbers other than 1. &amp;nbsp;So I created this image, which shows increasing values of n as you work downward, and shows how often we get a remainder r. &amp;nbsp;r is shown on the X axis, while the number of times it came up is shown as a color:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&amp;nbsp;0=black, 1=dark gray, 2=light gray, 3=blue, 4=orange, 5=red, 6 or more = white&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The other trick is that in number theory, we sometimes talk about negative remainders. &amp;nbsp;If you're working (mod 5), you might get remainders of 0,1,2,3,4, but since the next remainder after 4 is 0 again, sometimes it's easier to think of a remainder of 4 as -1. &amp;nbsp;So instead of 0,1,2,3,4, we call them 0,1,2,-2,-1, and that's what I've done here.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_oXIW_jM0QDA/TPon3xKB2-I/AAAAAAAAW3E/4bVPCM649ZM/s1600/fermat_residue_32_640x640.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_oXIW_jM0QDA/TPon3xKB2-I/AAAAAAAAW3E/4bVPCM649ZM/s320/fermat_residue_32_640x640.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Consider the topmost orange pixel in the above image. &amp;nbsp;It's the 5th pixel from the top, so that whole row represents n=5. &amp;nbsp;The orange pixel (and all the ones below it) are the "remainder=1" column. &amp;nbsp;The column to the left of it is the "remainder=0" column, and the one to the right is "remainder=2". &amp;nbsp;Since 5 is prime, we expect a^4 to be 1 (mod 5) for all 4 possible values of a: 1,2,3 and 4. &amp;nbsp;And indeed, orange is the color for 4.&lt;br /&gt;&lt;br /&gt;Two pixels down, you'll see a white pixel telling us that 7 is prime, since a^6=1 (mod 7) for a=1,2,3,4,5,6. &amp;nbsp;In the above image, you can keep counting down from the orange pixel at n=5 and see all the primes as white pixels, with 31 at the very bottom.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Give me one of everything&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;One surprise to me was row 6 (just below the topmost orange pixel). &amp;nbsp;It has a solid dark gray line extending all the way across. &amp;nbsp;That means that the five values of a: 1,2,3,4,5 in the equation a^5 (mod 6) produced... the values 1,2,3,4,5! &amp;nbsp;(Try it: 2^5=32, mod 6=2. &amp;nbsp;3^5=243, mod 6=3.)&lt;br /&gt;&lt;br /&gt;And you can see that lots of other numbers have this behavior: 10, 14, (but not 18!), 22, 26, 30 and so on.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;I need a bigger tree&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Here's how the image looks if we keep going all the way to 100:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_oXIW_jM0QDA/TPon4PvwS-I/AAAAAAAAW3I/SPC4JeN4Y-s/s1600/fermat_residue_100_800x800.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_oXIW_jM0QDA/TPon4PvwS-I/AAAAAAAAW3I/SPC4JeN4Y-s/s320/fermat_residue_100_800x800.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;img src="file:///home/jholt/src/fermat_residue/fermat_residue_32_640x640.png" /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;img src="file:///home/jholt/src/fermat_residue/fermat_residue_32_640x640.png" /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;And if you really have a tall living room, you can &lt;a href="http://lunkwill.org/src/carmichael/"&gt;see the numbers up to 1000, as well as the python source code I used to generate the images&lt;/a&gt;.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4394320096398963965?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4394320096398963965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4394320096398963965' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4394320096398963965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4394320096398963965'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/12/guess-mystery-plot.html' title='Carmichael numbers and Fermat primality'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_oXIW_jM0QDA/TPgYrMHiH3I/AAAAAAAAW2k/1u8HphQg8wM/s72-c/mystery1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6769276349375284556</id><published>2010-10-03T01:52:00.000-07:00</published><updated>2010-10-03T01:52:39.758-07:00</updated><title type='text'>Bechdel Test: Aeon Flux</title><content type='html'>I had forgotten what a great movie Aeon Flux was.&amp;nbsp; I can't think of a more Bechdel-compliant action movie, it's visually stunning, and has a creative plot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6769276349375284556?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6769276349375284556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6769276349375284556' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6769276349375284556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6769276349375284556'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/10/bechdel-test-aeon-flux.html' title='Bechdel Test: Aeon Flux'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6201699232348325840</id><published>2010-08-23T23:02:00.000-07:00</published><updated>2010-08-23T23:02:58.089-07:00</updated><title type='text'>Escalation</title><content type='html'>The answer was in the stars.  For some reason, Earthlings had founded universities, and those universities had supported thousands of astronomers for hundreds of years.  They refined their techniques over the centuries, collecting databases of statistics on distant stars which no human could ever visit.&lt;br /&gt;&lt;br /&gt;And then a grad student in cryptography had gotten fed up with her adviser and switched to astronomy.  To familiarize herself with the star database, Li had fed the coordinates of all the known stars in the galaxy into a PRNG test suite used to assess the predictability of cryptographic random number generators.&lt;br /&gt;&lt;br /&gt;She hadn't been surprised when the database failed the test; stars aren't randomly distributed, and as they later found, at least 7 different astronomical techniques had also added artificial patterns to the database.  However, Li thought it amusing when the test suite claimed the values were generated by a Linear Feedback Shift Register, the simplistic random number generator included in most programming libraries. It had even helpfully produced the LFSR parameters which, with a few lines of code, would generate a sequence of numbers that the test suite thought were somehow related to the database values.&lt;br /&gt;&lt;br /&gt;Li had shown it to her advisor, and over a few months they had toyed with the results at odd hours, musing on a publication about systemic errors in sky survey techniques, or perhaps uncovering evidence of fabrication by some unscrupulous astronomer.  When Li's model started predicting locations of stars before they were discovered, they worked full time on it for 18 months before telling another soul: surely it would be seen as plagiarism, not prediction.&lt;br /&gt;&lt;br /&gt;But in the end, the systemic errors were identified and eliminated, and Li was confirmed to have made the greatest scientific discovery in all of history: the universe they lived in was incontrovertibly a simulation.  And moreover, whatever Gods had placed the stars in their galaxies had been lazy in their choice of random number generators, just as human programmers are.  (This did create a certain smugness among the kind of cryptographers who used cryptograpic-strength PRNGs to shuffle music playlists.)&lt;br /&gt;&lt;br /&gt;As news-show pundits spouted absurdities and mankind came to grips with the hand of God, scientists in all fields now knew what to look for, and found bugs aplenty.&lt;br /&gt;&lt;br /&gt;And as the fabric of the universe resolved under our microscopes, it was the cryptographers once again who made a profoundly disturbing hypothesis.  The universe was made of bits, and manipulated by algorithms.  Far more bits than our computers had, and running algorithms more complex than mankind had ever managed.  But we knew there were bugs.  What if some of those bugs were also security holes?&lt;br /&gt;&lt;br /&gt;Teenagers had been exploiting complex systems for years. A carefully crafted string of a few hundred unexpected characters could cause a buggy subroutine to turn a user into an administrator.  Or, if the string was slightly off, crash the server.  This was normally no concern to the budding hackers. But then, they usually weren't hacking their own life support.&lt;br /&gt;&lt;br /&gt;When the politicians finally understood, the strictest laws were passed.  But studying really isn't much different than hacking, and eventually we learned all about our host machine.  And several of the shortcomings of our universe started looking tantalizingly exploitable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6201699232348325840?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6201699232348325840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6201699232348325840' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6201699232348325840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6201699232348325840'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/escalation.html' title='Escalation'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5166736009591445489</id><published>2010-08-22T16:49:00.000-07:00</published><updated>2010-08-22T16:49:37.676-07:00</updated><title type='text'>Ubuntu Lucid running alongside android on my phone</title><content type='html'>At first I thought running ubuntu on my phone would require blowing away the android OS, but that's not the case.  Instead, an ubuntu filesystem gets mounted on the SD card, with all the system files set up right so that things like apt-get work.  Some things don't work, I think because the android kernel isn't quite what the ubuntu apps expect, but you know you're doing well when firefox runs!&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://nexusonehacks.net/nexus-one-hacks/how-to-install-ubuntu-on-your-nexus-oneandroid/#comment-4029"&gt;nexusonehacks&lt;/a&gt; Ubuntu disk image worked great for me, but took forever to download and had a ton of stuff that I didn't need, like firefox and openoffice.org.&lt;br /&gt;&lt;br /&gt;So I stripped it down to bare bones and upgraded it to lucid. Check it out: &lt;a href="http://code.google.com/p/android-cruft/wiki/LucidWithAndroid"&gt;run a bare-bones Ubuntu Lucid filesystem alongside android&lt;/a&gt; on a froyo phone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5166736009591445489?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5166736009591445489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5166736009591445489' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5166736009591445489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5166736009591445489'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/ubuntu-lucid-running-alongside-android.html' title='Ubuntu Lucid running alongside android on my phone'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7834061965225611873</id><published>2010-08-20T23:35:00.000-07:00</published><updated>2010-09-04T16:21:11.552-07:00</updated><title type='text'>Native vim for android</title><content type='html'>Update: The vim binary has moved to the &lt;a href="http://code.google.com/p/android-cruft/downloads/list"&gt;downloads page&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;Update: Created a &lt;a href="http://code.google.com/p/android-cruft/"&gt;code.google.com&lt;/a&gt; project to keep stuff like this.  Also, I got color syntax hilighting to work.  See the &lt;a href="http://code.google.com/p/android-cruft/source/browse/trunk/vim/README.txt"&gt;README.txt&lt;/a&gt; in the vim/ directory of the repository.&lt;br /&gt;&lt;p&gt;Tonight I managed to compile vim to run natively on my android phone!  My phone is rooted and running cyanogenmod CM6 rc3.  Rooting is necessary to run vim, but cyanogen probably isn't necessary.&lt;br /&gt;&lt;p&gt;First I had to &lt;a href="http://credentiality2.blogspot.com/2010/08/compile-ncurses-for-android.html"&gt;compile ncurses&lt;/a&gt; using the ndk.  Follow that link and compile ncurses the way I did if you want to have any hope of compiling vim using these instructions.&lt;br /&gt;&lt;p&gt;Once I had ncurses built, I had to make just a few changes to vim to get it to work.&lt;br /&gt;&lt;p&gt;I downloaded &lt;a href="http://www.vim.org/mercurial.php"&gt;vim from the mercurial archive&lt;/a&gt;, which as of today is pretty much the same as the 7.3 release, I think.  I figured out how to call configure by trial and error:&lt;br /&gt;&lt;pre&gt;vim_cv_memcpy_handles_overlap=no \&lt;br /&gt;vim_cv_bcopy_handles_overlap=no \&lt;br /&gt;vim_cv_memmove_handles_overlap=no \&lt;br /&gt;vim_cv_stat_ignores_slash=no \&lt;br /&gt;vim_cv_getcwd_broken=no \&lt;br /&gt;vim_cv_tty_group=world \&lt;br /&gt;vim_cv_terminfo=yes \&lt;br /&gt;LDFLAGS="-L/path/to/ncurses-5.7/lib" \&lt;br /&gt;CFLAGS="-I/path/to/ncurses-5.7/lib" \&lt;br /&gt;vim_cv_toupper_broken=no \&lt;br /&gt;CC=agcc.pl \&lt;br /&gt;./configure --host=arm-eabi --with-tlib=ncurses&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I got this error message: "&lt;a href="http://groups.google.com/group/vim_dev/browse_thread/thread/66c02efd1523554b"&gt;could not compile program using uint32_t&lt;/a&gt;", and manually patched the configure script because I couldn't remember how to regenerate the script from the configure.in:&lt;br /&gt;&lt;pre&gt;$as_echo_n "checking uint32_t is 32 bits... " &amp;gt;&amp;amp;6; }&lt;br /&gt;if test "$cross_compiling" = yes; then :&lt;br /&gt;  true&lt;br /&gt;#  as_fn_error "could not compile program using uint32_t." "$LINENO" 5&lt;br /&gt;else&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I also got an "undefined reference to sysinfo" error due to an android bug that omitted the sysinfo() call.  So I commented out the HAVE_SYSINFO and HAVE_SYSINFO_MEM_UNIT lines in src/auto/config.h.&lt;br /&gt;&lt;p&gt;I think that was it!  Once it finished compiling, I copied over the runtime/ directory and the src/vim binary to /data/vim on my phone.  I did an "export VIMRUNTIME=/data/vim/runtime", and vim worked great!&lt;br /&gt;&lt;p&gt;Once I got my VIMRUNTIME set, I was able to ":syntax on", although I'm not getting any color.  But otherwise it seems to work great!&lt;br /&gt;&lt;p&gt;You can find a tarball of vim for android on the &lt;a href="http://code.google.com/p/android-cruft/downloads/list"&gt;Downloads page&lt;/a&gt;: look for vim-7.3-android-binary.tar.gz.  There's also a tarred-up copy of my build directory, although I'm not sure why anyone would want that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7834061965225611873?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7834061965225611873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7834061965225611873' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7834061965225611873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7834061965225611873'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/native-vim-for-android.html' title='Native vim for android'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8412624064002023145</id><published>2010-08-20T23:11:00.000-07:00</published><updated>2011-01-24T21:57:25.367-08:00</updated><title type='text'>Compile ncurses for android</title><content type='html'>Update: The tarball of my ncurses build directory has moved to the &lt;a href="http://code.google.com/p/android-cruft/downloads/list"&gt;downloads page&lt;/a&gt;. &amp;nbsp;(Also, agcc -&amp;gt; agcc.pl thanks to Interarticle)&lt;br /&gt;&lt;br /&gt;I got the crazy notion to try to &lt;a href="http://credentiality2.blogspot.com/2010/08/native-vim-for-android.html"&gt;compile a native vim binary for android&lt;/a&gt;, and one of its dependencies is libncurses.&lt;br /&gt;&lt;br /&gt;Make sure you have the &lt;a href="http://credentiality2.blogspot.com/2010/08/native-android-c-program-using-ndk.html"&gt;ndk installed and working&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You'll need the agcc wrapper, a perl script that creates appropriate command line arguments for arm-eabi-gcc.  I learned today that the order of arguments to gcc can be quite significant while linking.  I kept getting errors about the "__aeabi_unwind_cpp_pr0" symbol and common functions like printf not being found when it tried to link.&lt;br /&gt;&lt;br /&gt;So I hacked &lt;a href="http://v-lad.org/Filez/agcc"&gt;Vlad's hacked agcc&lt;/a&gt; to make sure that libgcc.a and libc.a get put at the end of the command line, which seems to be necessary for static linking.  Here's my &lt;a href="https://docs.google.com/leaf?id=0B8R6VSvTZHZWODMzNDJlOTAtYTIzMS00ZTFjLTg1MzItZDY4NGM5YTNkNGI5&amp;amp;hl=en&amp;amp;authkey=CKGVi8AO"&gt;hacked version of Vlad's agcc&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Make sure both agcc and arm-eabi-gcc are in your path.&lt;br /&gt;&lt;br /&gt;Download &lt;a href="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.7.tar.gz"&gt;ncurses-5.7.tar.gz&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Run configure:&lt;br /&gt;&lt;pre&gt;CC=agcc.pl ./configure --host=arm-eabi --without-cxx-binding&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When I tried to build, I got errors saying "'struct lconv' has no member named 'decimal_point'"", because android has a broken locale implementation.&lt;br /&gt;&lt;br /&gt;So I commented out the HAVE_LOCALE_H line from include/ncurses_cfg.h.  (Is there a better way to force configure to set a value like that during the ./configure process?)&lt;br /&gt;&lt;br /&gt;It might be possible to build ncurses with the C++ binding, but I didn't try.&lt;br /&gt;&lt;br /&gt;Once I had all that fixed, the make ran just fine, and I ended up with lib/libncurses.a.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8412624064002023145?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8412624064002023145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8412624064002023145' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8412624064002023145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8412624064002023145'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/compile-ncurses-for-android.html' title='Compile ncurses for android'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8313061465169493009</id><published>2010-08-20T01:01:00.000-07:00</published><updated>2010-08-20T01:01:04.538-07:00</updated><title type='text'>Extract boot.img from an android phone</title><content type='html'>(I did this on my rooted, boot-unlocked nexus one (HTC Passion) running cyanogen cm6.  Cyanogen is probably not necessary, but boot-unlocking and rooting are).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images"&gt;This tutorial&lt;/a&gt; pointed me in the right direction.&lt;br /&gt;&lt;br /&gt;I did:&lt;br /&gt;&lt;pre&gt;$ adb pull /dev/mtd/mtd2 boot.img-from-phone&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then put it right back using:&lt;br /&gt;&lt;pre&gt;$ adb reboot bootloader&lt;br /&gt;[wait for bootloader to come up]&lt;br /&gt;$ sudo ./fastboot flash boot boot.img-from-phone&lt;br /&gt;$ sudo ./fastboot reboot&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I could have also &lt;a href="http://credentiality2.blogspot.com/2010/08/nexus-one-htc-passion-compile-and-flash.html"&gt;taken it apart and replaced the kernel with my own&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8313061465169493009?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8313061465169493009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8313061465169493009' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8313061465169493009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8313061465169493009'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/extract-bootimg-from-android-phone.html' title='Extract boot.img from an android phone'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8499515963758367574</id><published>2010-08-18T23:06:00.000-07:00</published><updated>2010-08-20T01:01:58.792-07:00</updated><title type='text'>Nexus One (HTC Passion): compile and flash a kernel</title><content type='html'>Update 2: my camera doesn't work with the custom kernel.  no idea why.  Also, I figured out how to &lt;a href="http://credentiality2.blogspot.com/2010/08/extract-bootimg-from-android-phone.html"&gt;extract the boot.img from the phone directly&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Update: mention how to update the bcm4329.ko wifi driver so that wifi will work again.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://atechyblog.blogspot.com/2010/08/enabling-serial-port-on-nexus-one.html"&gt;This page&lt;/a&gt; will tell you how to download and compile the android kernel, and try it out on your phone temporarily (without writing it to flash) using "fastboot boot zImage".&lt;br /&gt;&lt;br /&gt;Assuming that worked, here's how to actually write the kernel to the phone's flash.  &lt;br /&gt;&lt;br /&gt;By this point you should already have &lt;a href="http://developer.htc.com/adp.html"&gt;fastboot&lt;/a&gt;.  You'll also need a phone with an unlocked bootloader and probably rooted as well.&lt;br /&gt;&lt;br /&gt;You'll also need the boot.img from your phone.  It seems to be possible to pull it off a working phone, but I didn't try that.  I'm running cyanogen 6, and the boot.img was in the &lt;a href="http://mirror.kanged.net/cm/stable/nexus/testing/update-cm-6.0.0-N1-RC3-signed.zip"&gt;update-cm-6.0.0-N1-RC3-signed.zip&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Next you need to unpack it using the &lt;a href="http://android-dls.com/files/linux/split_bootimg.zip"&gt;split_bootimg&lt;/a&gt; perl script which I found in &lt;a href="http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images"&gt;this tutorial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;That produced output like this:&lt;br /&gt;&lt;pre&gt;$ ./split_bootimg.pl boot.img&lt;br /&gt;Page size: 2048 (0x00000800)&lt;br /&gt;Kernel size: 2206592 (0x0021ab80)&lt;br /&gt;Ramdisk size: 167182 (0x00028d0e)&lt;br /&gt;Second size: 0 (0x00000000)&lt;br /&gt;Board name: &lt;br /&gt;Command line: no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5&lt;br /&gt;Writing boot.img-kernel ... complete.&lt;br /&gt;Writing boot.img-ramdisk.gz ... complete.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, you need mkbootimg.  Supposedly you can use "fastboot flash:raw" to avoid this, but it didn't work for me.  mkbootimg comes with the (multi-gigabyte) android sources, so I ended up downloading a &lt;a href="http://code.google.com/p/zen-droid/downloads/detail?name=mkbootimg"&gt;pre-compiled mkbootimg binary&lt;/a&gt;, which made me feel dirty, but saved me many hours of downloading and compiling.&lt;br /&gt;&lt;br /&gt;Constructing the right command line for mkbootimg was a pain, but eventually I was able to build a my-boot.img identical to the original:&lt;br /&gt;&lt;br /&gt;./mkbootimg --kernel boot.img-kernel --ramdisk boot.img-ramdisk.gz -o my-boot.img  --cmdline 'no_console_suspend=1 msmsdcc_sdioirq=1 wire.search_count=5' --base 0x20000000&lt;br /&gt;&lt;br /&gt;The boot.img-kernel and boot.img-ramdisk.gz came from split_bootimg, as did the --cmdline string.  The "--base 0x20000000" is specific to the N1 (aka nexus one aka HTC passion).&lt;br /&gt;&lt;br /&gt;Once you get the boot.img constructed properly, reboot into the bootloader by holding down the trackball while you boot (or use "adb reboot-bootloader").  Then:&lt;br /&gt;&lt;pre&gt;$ sudo ./fastboot flash boot my-boot.img&lt;br /&gt;$ sudo ./fastboot reboot&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you get it wrong, your phone will hang at the screen with the unlocked padlock forever.  Pull the battery to cold boot and reboot into the bootloader again.&lt;br /&gt;&lt;br /&gt;(Nexus One / HTC Passion): If that worked, you may find that "wifi" under Settings... on the phone just says "error".  That's because the bcm4329.ko kernel module doesn't match the kernel version.&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://lunkwill.org/android/bcm4329.ko"&gt;bcm4329.ko&lt;/a&gt; that matches this &lt;a href="http://lunkwill.org/zImage-serial-second-pass"&gt;2.6.32&lt;/a&gt; kernel (which has the serial port enabled).&lt;br /&gt;&lt;br /&gt;The kernel module lives in /system/lib/modules/.  The /system filesystem was mounted read-only on my phone, so from the root shell on my phone (adb shell) I remounted it read-write and then backed up the original kernel module, so that I can switch back to the old kernel if I need to:&lt;br /&gt;&lt;pre&gt;# mount -oremount,rw /system&lt;br /&gt;# cp /system/lib/modules/bcm4329.ko /sdcard/bcm4329.ko-orig&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then I copied over the file with "adb push bcm4329.ko /system/lib/modules/", then remounted /system back to read-only:&lt;br /&gt;&lt;pre&gt;# mount -oremount,ro /system&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It started working immediately.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8499515963758367574?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8499515963758367574/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8499515963758367574' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8499515963758367574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8499515963758367574'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/nexus-one-htc-passion-compile-and-flash.html' title='Nexus One (HTC Passion): compile and flash a kernel'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7030726403423532665</id><published>2010-08-15T22:22:00.000-07:00</published><updated>2010-09-24T21:41:26.701-07:00</updated><title type='text'>Giving native Android C apps access to the Android API through SL4A</title><content type='html'>UPDATE: this is slightly more mature now.  Check out &lt;a href="http://code.google.com/p/android-cruft/wiki/SL4AC"&gt;http://code.google.com/p/android-cruft/wiki/SL4AC&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today I played around with the Android NDK, a C compiler for Android.  The Android folks make it very clear that it's only intended for making ordinary Java-based Android apps faster, by running a few selected functions down at the bare metal.&lt;br /&gt;&lt;br /&gt;So it only comes with a few basic libraries which don't support things like reading the sensors and taking photos.&lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://code.google.com/p/android-scripting/"&gt;SL4A, Scripting Languages for Android&lt;/a&gt; (formerly "ASE", the Android Scripting Environment).  SL4A is a neat Android app that makes it very easy to write simple Android apps in many popular scripting languages like Python, Perl, Ruby and TCL.  SL4A exposes a useful subset of the Android API in a clever way: by setting up a JSON RPC server.  That way, each language only needs to implement a thin RPC client layer to access the whole SL4A API.&lt;br /&gt;&lt;br /&gt;So today I managed to get the excellent &lt;a href="http://www.digip.org/jansson/"&gt;Jansson&lt;/a&gt; C-language JSON library to compile with the NDK, making it possible for native C apps to access the Android API through SL4A, just as its normally supported languages can.&lt;br /&gt;&lt;br /&gt;It works just fine as either a native Android binary or from a host machine, so you could also use it to control your phone from a C program running on a host computer.&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://docs.google.com/leaf?id=0B8R6VSvTZHZWOGQzYzE2ZmYtOTdiZS00NmM1LWFlMTQtZTM2MTBlNjIyNTA5&amp;amp;hl=en"&gt;ndk-to-sl4a.c source code&lt;/a&gt;, public domain.  See the comments in the header for instructions on how to compile and run it.&lt;br /&gt;&lt;br /&gt;If you're the trusting sort, you can also download a &lt;a href="http://docs.google.com/leaf?id=0B8R6VSvTZHZWOWFiMWQ0MDAtMzVjOS00NGZmLTgzYjAtODVkNTkxZDU1Y2Ew&amp;amp;hl=en"&gt;binary for froyo&lt;/a&gt; or for &lt;a href="http://docs.google.com/leaf?id=0B8R6VSvTZHZWMTA0Mzc4NjQtODY2OS00Y2VlLWFmZmQtNjdiMTVmOThmZDA1&amp;amp;hl=en"&gt;(ubuntu/lucid) linux&lt;/a&gt;.  But you should still go through the comments in the source file to see how to set up SL4A first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7030726403423532665?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7030726403423532665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7030726403423532665' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7030726403423532665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7030726403423532665'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/giving-native-android-c-apps-access-to.html' title='Giving native Android C apps access to the Android API through SL4A'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8105910655434843967</id><published>2010-08-15T18:11:00.000-07:00</published><updated>2011-07-06T20:42:40.005-07:00</updated><title type='text'>Native android C program using ndk</title><content type='html'>Big update: I updated agcc.pl to work with the latest NDK release, and called it agcc2.pl.  &lt;a href="http://credentiality2.blogspot.com/2011/07/native-android-c-program-using-ndk.html"&gt;Here is the new blog post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Update: link to agcc.pl works now.  Update 2: link to agcc.pl *actually* works now?&lt;br /&gt;&lt;br /&gt;The Android NDK isn't really intended to write standalone binaries, but &lt;a href="http://android-tricks.blogspot.com/2009/02/hello-world-c-program-on-using-android.html"&gt;this tutorial&lt;/a&gt; got me most of the way there.  But some path changes in android-ndk-r4b broke the agcc wrapper, so I had to modify it to point to the right includes and libraries.&lt;br /&gt;&lt;br /&gt;Here's what should be a complete HOWTO for linux.  It probably requires a &lt;a href="http://blog.makezine.com/archive/2009/08/root_an_android_phone_the_easy_way.html"&gt;rooted&lt;/a&gt;  phone at the least, in order to upload and run arbitrary binaries.  I'm running a pre-release of &lt;a href="http://www.cyanogenmod.com/"&gt;cyanogenmod&lt;/a&gt; CM6.&lt;br /&gt;&lt;br /&gt;1. Download and unpack &lt;a href="http://dl.google.com/android/android-sdk_r06-linux_86.tgz"&gt;android-sdk_r06-linux_x86.tgz&lt;/a&gt; and &lt;a href="http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip"&gt;android-ndk-r4b-linux-x86.zip&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;2. Add android-ndk-r4b/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin and android-sdk-linux_86/tools/ to your PATH.  (cd into each of those directories and then run "export PATH=$PATH:`pwd`")&lt;br /&gt;&lt;br /&gt;3. Plug your phone in via USB and run "sudo adb start-server" to start the daemon in the background (as root so that it can access the USB device.  If you accidentally start the daemon as yourself and can't talk to your phone, run "adb kill-server" to kill it, then "sudo adb start-server" to restart it as root.)&lt;br /&gt;&lt;br /&gt;4. Make sure you can run "adb" (from the SDK) and "arm-eabi-gcc" (from the NDK) so that you know your PATH is set up right.&lt;br /&gt;&lt;br /&gt;5. Grab my copy of the &lt;a href="http://android-cruft.googlecode.com/svn/trunk/agcc/agcc.pl"&gt;agcc wrapper hacked for android-ndk-r4b&lt;/a&gt;.  "chmod 755" it so you can run it.&lt;br /&gt;&lt;br /&gt;6. Create the "hello, world" .c file:&lt;br /&gt;&lt;pre&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;  printf("Hello, world!\n");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;7. Ready to compile! "$ agcc.pl -o hello hello.c"&lt;br /&gt;&lt;br /&gt;8. Copy the binary to /data: "adb push hello /data/"&lt;br /&gt;&lt;br /&gt;9. Run it!  I did that by &lt;a href="http://wiki.cyanogenmod.com/index.php?title=Connect_to_Your_Android_Device_with_SSH&amp;direction=prev&amp;oldid=2990"&gt;SSHing into the phone&lt;/a&gt;, but you can also just "adb shell".&lt;br /&gt;&lt;pre&gt;# cd /data&lt;br /&gt;# ./hello&lt;br /&gt;Hello, world!&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8105910655434843967?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8105910655434843967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8105910655434843967' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8105910655434843967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8105910655434843967'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/native-android-c-program-using-ndk.html' title='Native android C program using ndk'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3889135007539556564</id><published>2010-08-06T00:59:00.000-07:00</published><updated>2010-08-06T00:59:39.180-07:00</updated><title type='text'>Simple kalman filter example</title><content type='html'>There are a ton of Kalman filter overviews online, and lots of them give a general overview of what they do, but then they all hit a wall of variables and matrices, and fail to give good simple examples.&lt;br /&gt;&lt;br /&gt;The best guide I found is a PDF scan of a much-faxed copy of Roger M. du Plessis' 1967 classic "&lt;a href="http://edge.rit.edu/content/P07106/public/Docs/Research/KalmanFilter/Poor_Mans_Explanation_of_Kalman_Filtering.pdf"&gt;Poor Man's Explanation of Kalman Filtering&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;His paper is great because he starts with a single-variable filter (no matrices!) with no control component and no prediction algorithm.  I'm going to try to give an even simpler example with softer terminology and more hand-waving.&lt;br /&gt;&lt;br /&gt;Kalman filters are a way to take a bunch of noisy measurements of something, and perhaps also some predictions of how that something is changing, and maybe even some forces we're applying to that something, and to efficiently compute an accurate estimate of that something's true value.&lt;br /&gt;&lt;br /&gt;Let's say we want to measure the temperature in a room.  We think it's about 72 degrees, plus or minus 2 degrees.  And we have a thermometer that gives uniformly random results within a range of +/-5 degrees of the true temperature.&lt;br /&gt;&lt;br /&gt;We take a measurement with the thermometer and it reads 75.  So what's our best estimate of the true temperature?  Kalman filters use a weighted average to pick a point somewhere between our 72 degree guess and the 75 degree measurement.  If the weight is large (approaching 1.0), we mostly trust our thermometer.  If the weight is small, we mostly trust our guess and ignore the thermometer.&lt;br /&gt;&lt;br /&gt;Here's how we choose the optimal weight, given the accuracy of our guess and the accuracy of the thermometer:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;weight = temperature_variance / (temperature_variance + thermometer_variance)&lt;br /&gt;0.29 = 2 / (2+5)&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;If temperature_variance were very large compared to thermometer_variance, weight would approach 1.0.  That is, we'd ignore our guess and just use the measured value.  Likewise, if thermometer_variance dominated, the weight would approach 0, and we'd put very little trust in our thermometer readings.&lt;br /&gt;&lt;br /&gt;29% weight means we'll trust our guess more than the thermometer, which makes sense, because we think our guess is good to +/-2 degrees, whereas the thermometer was only good to +/-5.&lt;br /&gt;&lt;br /&gt;Now we do the weighted average:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;estimate = guess + weight*(measurement - guess)&lt;br /&gt;72.87 = 72 + 0.29*(75-72)&lt;br /&gt;&lt;br /&gt;or equivalently&lt;br /&gt;&lt;br /&gt;estimate = (1-weight)*guess + weight*measurement&lt;br /&gt;72.87 = 0.71*72 + 0.29*75&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;That is, we went 29% of the way from 72 to 75, or equivalently, we took 71% of the guess plus 29% of the measurement.&lt;br /&gt;&lt;br /&gt;There's one last thing to compute: how confident we are in our estimate of 72.87 degrees.  That equation is:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;                      temperature_variance*thermometer_variance &lt;br /&gt;estimate_variance =   -----------------------------------------&lt;br /&gt;                    (temperature_variance + thermometer_variance)&lt;br /&gt;&lt;br /&gt;1.43 = 2*5 / (2+5)&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;So we think our estimate is correct to +/-1.43 degrees.&lt;br /&gt;&lt;br /&gt;Now we have a guess that the temperature in the room is 72.87 degrees, +/-1.43 degrees.  And we still have a thermometer that tells the temperature +/-5 degrees.&lt;br /&gt;&lt;br /&gt;That's basically the situation where we started, so we can run the whole algorithm again:&lt;br /&gt;&lt;br /&gt;First we compute the weight, using our new, more accurate guess confidence:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;weight = temperature_variance / (temperature_variance + thermometer_variance)&lt;br /&gt;0.22 = 1.43 / (1.43+5)&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;We take a measurement, and this time let's say it comes up as 71 degrees.&lt;br /&gt;&lt;br /&gt;Now we can compute the weighted average of our old guess and our new measurement:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;estimate = guess + weight*(measurement - guess)&lt;br /&gt;72.46 = 72.87 + 0.22*(71-72.87)&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;And the new confidence level:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;pre&gt;                      temperature_variance*thermometer_variance &lt;br /&gt;estimate_variance =   -----------------------------------------&lt;br /&gt;                    (temperature_variance + thermometer_variance)&lt;br /&gt;&lt;br /&gt;1.11 = 1.43*5 / (1.43+5)&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;So after the second measurement, we estimate that the actual temperature is 72.46 degrees, +/-1.11 degrees.&lt;br /&gt;&lt;br /&gt;Kalman filters are nice because we don't have to remember the whole history of measurements and estimates.  We just keep track of our most recent estimate and our confidence level in that estimate.&lt;br /&gt;&lt;br /&gt;If we decide to turn on the air conditioner, so that the temperature in the room starts decreasing, we can expand our calculations to include that "control" variable, and use it to update our estimates by "predicting" how much colder it'll be at each measurement.  Once I figure out how to do that, maybe I'll post a more complicated example :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3889135007539556564?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3889135007539556564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3889135007539556564' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3889135007539556564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3889135007539556564'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/08/simple-kalman-filter-example.html' title='Simple kalman filter example'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7203506381697380652</id><published>2010-07-27T02:25:00.000-07:00</published><updated>2010-07-27T02:25:17.103-07:00</updated><title type='text'>Plotting complex polynomials with octave and octaviz (vtk)</title><content type='html'>I got to wondering what happens when you feed complex numbers into polynomials, so I poked around and found the awesome vtk library binding for the octave language, called octaviz.&amp;nbsp; (octave is a free implementation of the MATLAB language).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_oXIW_jM0QDA/TE6k2q-UswI/AAAAAAAASlo/KyLaWnYofEg/s1600/polynomial.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_oXIW_jM0QDA/TE6k2q-UswI/AAAAAAAASlo/KyLaWnYofEg/s320/polynomial.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;When we plot z = f(x), where x and z are complex numbers, we get 4 dimensions to plot, so I shifted each point in the surface plot N units + or - in the Y direction, where N is the imaginary part of the output.&amp;nbsp; The color also indicates how far each point was stretched in the + or - Y direction.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/octave&lt;br /&gt;&lt;br /&gt;global a = 1&lt;br /&gt;global b = 0&lt;br /&gt;global c = 0&lt;br /&gt;&lt;br /&gt;function z = polynomial (i,j)&lt;br /&gt;  global a&lt;br /&gt;  global b&lt;br /&gt;  global c&lt;br /&gt;  x = i + (j * 1j);&lt;br /&gt;  z = a*x*x + b*x + c;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;[I,J] = meshgrid(-1:0.2:1);&lt;br /&gt;REAL = arrayfun(@real, arrayfun(@polynomial, I, J));&lt;br /&gt;IMAG = arrayfun(@imag, arrayfun(@polynomial, I, J));&lt;br /&gt;vtk_surf(I,J+IMAG,REAL, IMAG);&lt;br /&gt;&lt;br /&gt;input ("Orient it the way you want it before I save.");&lt;br /&gt;vtk_print('polynomial.jpg', '-djpeg');&lt;br /&gt;input ("Done!");&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7203506381697380652?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7203506381697380652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7203506381697380652' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7203506381697380652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7203506381697380652'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/plotting-complex-polynomials-with.html' title='Plotting complex polynomials with octave and octaviz (vtk)'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_oXIW_jM0QDA/TE6k2q-UswI/AAAAAAAASlo/KyLaWnYofEg/s72-c/polynomial.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3579489554751287005</id><published>2010-07-21T00:31:00.000-07:00</published><updated>2010-07-21T00:31:46.061-07:00</updated><title type='text'>Borges</title><content type='html'>The stoics teach that we should not complain of life--the door of the prison is open.&lt;br /&gt; -august 25, 1983&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3579489554751287005?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3579489554751287005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3579489554751287005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3579489554751287005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3579489554751287005'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/borges_21.html' title='Borges'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4329836208501507147</id><published>2010-07-15T18:25:00.001-07:00</published><updated>2010-07-15T18:32:02.454-07:00</updated><title type='text'>Things I hate: externalized costs in programming</title><content type='html'>Bob adds a feature to handle a situation that someday might arise.  Alice then discovers a production failure caused by that feature.  Good luck removing the feature: doing that might cause a production failure someday!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4329836208501507147?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4329836208501507147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4329836208501507147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4329836208501507147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4329836208501507147'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/things-i-hate-externalized-costs-in.html' title='Things I hate: externalized costs in programming'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7279555616493228758</id><published>2010-07-15T14:46:00.000-07:00</published><updated>2010-07-15T14:52:15.402-07:00</updated><title type='text'>python-tk: tkinter photo doesn't work inside a function</title><content type='html'>Wow, python-tk sucks.  When I create the photo inside a function, it gets garbage-collected because it's not smart enough to know that the label is using it.  So I have to manually keep it from being deallocated (in this case, by making it global).  Also, I'd really like to use after_idle instead of after, but it never gets around to actually updating the display.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/python&lt;br /&gt;&lt;br /&gt;import Tkinter&lt;br /&gt;import ImageTk,Image&lt;br /&gt;&lt;br /&gt;root = Tkinter.Tk()&lt;br /&gt;root.geometry('+640+480')&lt;br /&gt;&lt;br /&gt;old_label = None&lt;br /&gt;label = None&lt;br /&gt;photo = None&lt;br /&gt;def display_image(root, image):&lt;br /&gt;  global old_label&lt;br /&gt;  global label&lt;br /&gt;  global photo&lt;br /&gt;&lt;br /&gt;  root.geometry('%dx%d' % (image.size[0], image.size[1]))&lt;br /&gt;&lt;br /&gt;  photo = ImageTk.PhotoImage(image)&lt;br /&gt;&lt;br /&gt;  label = Tkinter.Label(root, image=photo)&lt;br /&gt;  label.place(x=0,y=0,width=image.size[0],height=image.size[1])&lt;br /&gt;&lt;br /&gt;  if old_label is not None:&lt;br /&gt;    old_label.destroy()&lt;br /&gt;&lt;br /&gt;  old_label = label&lt;br /&gt;&lt;br /&gt;def image_loop():&lt;br /&gt;  global root&lt;br /&gt;  print '.'&lt;br /&gt;  image = get_image()&lt;br /&gt;  display_image(root, image)&lt;br /&gt;  root.after(1000,image_loop)&lt;br /&gt;&lt;br /&gt;image_loop()&lt;br /&gt;&lt;br /&gt;root.mainloop()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7279555616493228758?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7279555616493228758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7279555616493228758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7279555616493228758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7279555616493228758'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/python-tk-tkinter-photo-doesnt-work.html' title='python-tk: tkinter photo doesn&apos;t work inside a function'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8491696538249127899</id><published>2010-07-15T12:58:00.001-07:00</published><updated>2010-07-15T14:06:33.335-07:00</updated><title type='text'>python plumbing: PIL Image from data string</title><content type='html'>Today I wanted to use netcat (nc) to send a JPEG image file over a network to a python script so that I can manipulate it with PIL, the python imaging library.&lt;br /&gt;&lt;br /&gt;PIL has fromstring and frombuffer methods, but I couldn't get them to work.  But I found the ImageFile module, which let me feed the data in as it came off the socket.&lt;br /&gt;&lt;br /&gt;To serve up the images, I did this from the shell:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;while true ; do nc -q 0 -l -p 12345 &amp;lt; foo.jpg  ; done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then this python script received and displayed an image:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/python&lt;br /&gt;&lt;br /&gt;import socket&lt;br /&gt;from PIL import ImageFile&lt;br /&gt;&lt;br /&gt;tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;br /&gt;tcp.connect(('127.0.0.1', 12345))&lt;br /&gt;tcp.send("1000 4")&lt;br /&gt;&lt;br /&gt;file = open("bar.jpg", "w")&lt;br /&gt;parser = ImageFile.Parser()&lt;br /&gt;&lt;br /&gt;while 1:&lt;br /&gt;  jpgdata = tcp.recv(65536)&lt;br /&gt;  if not jpgdata:&lt;br /&gt;    tcp.close()&lt;br /&gt;    break&lt;br /&gt;&lt;br /&gt;  parser.feed(jpgdata)&lt;br /&gt;  file.write(jpgdata)&lt;br /&gt;&lt;br /&gt;file.close()&lt;br /&gt;image = parser.close()&lt;br /&gt;image.show()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8491696538249127899?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8491696538249127899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8491696538249127899' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8491696538249127899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8491696538249127899'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/python-plumbing-pil-image-from-data.html' title='python plumbing: PIL Image from data string'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6911021301093237562</id><published>2010-07-10T15:48:00.000-07:00</published><updated>2010-07-10T16:05:21.260-07:00</updated><title type='text'>Xorg window redraw: workaround by forcing update</title><content type='html'>When using Sketchup in wine on my ubuntu linux machine, I find that it doesn't update the screen properly.  For instance, if I hit control-A to select everything, I don't see the selection until I do something else.  That is, the screen seems to be one update behind.&lt;br /&gt;&lt;br /&gt;Here's a workaround that works with Sketchup: in a separate terminal, I run:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ watch -n 0.3 xrefresh -geometry 1x1+500+500&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That uses xrefresh to create a 1x1 pixel x11 window at 500,500 on the screen every 0.3 seconds.  That's enough to get sketchup to redraw itself.&lt;br /&gt;&lt;br /&gt;If that's not enough, you can run xrefresh without the -geometry option to have it draw a window the size of the entire screen.  But that's a lot more distracting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6911021301093237562?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6911021301093237562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6911021301093237562' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6911021301093237562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6911021301093237562'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/xorg-window-redraw-workaround-by.html' title='Xorg window redraw: workaround by forcing update'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3206103696258397958</id><published>2010-07-08T21:40:00.001-07:00</published><updated>2010-07-08T21:47:52.713-07:00</updated><title type='text'>libgphoto2 / gphoto2 build from svn and install locally</title><content type='html'>Today I wanted to make a patch against gphoto2 (the command-line interface to libgphoto2) without overwriting the version installed by ubuntu.&lt;br /&gt;&lt;br /&gt;So I needed to download libgphoto2 and gphoto2 from subversion and then install it to a local directory.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo apt-get install automake autoconf libtool gettext pkg-config subversion build-essential&lt;br /&gt;$ mkdir gphoto-svn&lt;br /&gt;$ cd gphoto-svn&lt;br /&gt;$ svn checkout https://gphoto.svn.sourceforge.net/svnroot/gphoto/trunk/libgphoto2&lt;br /&gt;$ cd libgphoto2&lt;br /&gt;$ autoreconf -is&lt;br /&gt;$ mkdir -p /tmp/gphoto2/local&lt;br /&gt;$ ./configure --prefix=/tmp/gphoto2/local&lt;br /&gt;$ make&lt;br /&gt;$ make install&lt;br /&gt;$ # neat, libgphoto2 installed to /tmp/gphoto2/local&lt;br /&gt;$ cd ..&lt;br /&gt;$ svn checkout https://gphoto.svn.sourceforge.net/svnroot/gphoto/trunk/gphoto2&lt;br /&gt;$ cd gphoto2&lt;br /&gt;$ autoreconf -is&lt;br /&gt;$ ./configure --prefix=/tmp/gphoto2/local --with-libgphoto2=/tmp/gphoto2/local&lt;br /&gt;$ make&lt;br /&gt;$ # make install is optional; I just ran ./gphoto2/gphoto2 directly&lt;br /&gt;$ # edited files, then "make" to rebuild&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3206103696258397958?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3206103696258397958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3206103696258397958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3206103696258397958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3206103696258397958'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/libgphoto2-gphoto2-build-from-svn-and.html' title='libgphoto2 / gphoto2 build from svn and install locally'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4521906963953816779</id><published>2010-07-08T16:43:00.000-07:00</published><updated>2010-07-08T17:01:40.768-07:00</updated><title type='text'>Earth Source / pals4wood sucks</title><content type='html'>American business is doomed.  I needed to buy several thousand dollars worth of plywood.  My friend recommended "PALS", a local distributor.  Great, let's go to their website.&lt;br /&gt;&lt;br /&gt;Hm, no price list online.  That sucks.  I guess I'll email them a list of what I need.  Hm, the email bounced: mailbox full.  Let's try one of the other sales reps, and mention the bounce so they can fix it.  Nope, that one also bounces.  Okaaayyy, well at least one of them has a @yahoo.com address listed.  That's pretty sketchy, but maybe they just can't seem to get their mail service right.&lt;br /&gt;&lt;br /&gt;Weeks go by, no answer.  Thanks, guys.  Something that I was ready to take care of weeks ago, credit card in hand, has been on my mind ever since, while I wait to see if you'll ever get around to answering.&lt;br /&gt;&lt;br /&gt;I give up and order from their competitor.  They don't have prices online either, so I get to go back and forth with their sales guy about what I want and what they have over the course of a week or so.  And I finally give up on PALS, call in to the competitor, wait for him to pull up the email, give him my credit card info, and place the order.&lt;br /&gt;&lt;br /&gt;Now, out of some perverse sense of business ethics, I decide to try one last time to reach PALS and let them know how broken their website is.&lt;br /&gt;&lt;br /&gt;Searching again for "pals plywood", the first result is for "&lt;a href="http://www.earthsourcewood.com"&gt;earth source forest products&lt;/a&gt;", whose website makes no mention of &lt;a href="http://pals4wood.com"&gt;PALS&lt;/a&gt;.  Maybe everything's fixed now?&lt;br /&gt;&lt;br /&gt;I send them an email to info@pals4wood, the email address listed on the new website.  That message bounces back (mailbox full) too, but also sends me an autoresponse... telling me to call them.  Seriously, guys?&lt;br /&gt;&lt;br /&gt;Okay, sure, why not?  I'm already in it this far.  I call the toll-free number listed in the email.  Rings forever.  Whee!  Let's try the Oakland branch.  Ah ha, somebody answers!  Oops, wrong number.  &lt;br /&gt;&lt;br /&gt;That's right, the company with two websites, both of which list numerous email addresses, all broken, lists the wrong phone number to call when you email their info address.  FML.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4521906963953816779?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4521906963953816779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4521906963953816779' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4521906963953816779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4521906963953816779'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/earth-source-pals4wood-sucks.html' title='Earth Source / pals4wood sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1245001888967717974</id><published>2010-07-07T22:25:00.000-07:00</published><updated>2010-07-07T23:53:50.616-07:00</updated><title type='text'>Borges</title><content type='html'>The Secret Miracle&lt;br /&gt;&lt;br /&gt;The date was set for March 29, at 9:00 A.M. That delay ... was caused by the administrative desire to work impersonally and deliberately, as vegetables do, or planets.&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;The Aleph&lt;br /&gt;&lt;br /&gt;I do, however, recall these lines from a satire in which he lashed out vehemently against bad poets:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; This one fits the poem with a coat of mail&lt;br /&gt; Of erudition; that one, with gala pomps and circumstance.&lt;br /&gt; Both flail their absurd pennons to no avail,&lt;br /&gt; Neglecting, poor wretches, the factor sublime -- its LOVELINESS!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It was only out of concern that he might create an army of implacable and powerful enemies, he told me, that he did not fearlessly publish the poem.&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Aleph (1949)&lt;br /&gt;&lt;br /&gt;"I picture him," he said with an animation that was rather unaccountable, "in his study, as though in the watchtower of a great city, surrounded by telephones, telegraphs, phonographs, the latest in radio-telephone and motion-picture and magic-lantern equipment, and glossaries and calendars and timetables and bulletins..."&lt;br /&gt;&lt;br /&gt;He observed that for a man so equipped, the act of traveling was supererogatory; this twentieth century of ours had upended the fable Muhammad and the mountain -- mountains nowadays did in fact come to the modern Muhammad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1245001888967717974?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1245001888967717974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1245001888967717974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1245001888967717974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1245001888967717974'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/borges.html' title='Borges'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7776889650352147619</id><published>2010-07-03T16:12:00.000-07:00</published><updated>2010-07-03T16:16:56.277-07:00</updated><title type='text'>ubuntu hardy firefox 3.6.6 freezes</title><content type='html'>After today's apt-get dist-upgrade on my hardy (ubuntu 8.04) machine, firefox would freeze almost immediately and had to be killed.&lt;br /&gt;&lt;br /&gt;Turns out there are two copies of libflashplayer.so that can get installed, one by the flashplugin-nonfree package, and one by the adobe-flashplayer .deb package that adobe distributes.&lt;br /&gt;&lt;br /&gt;sudo apt-get remove flashplugin-nonfree and then a reinstall of the install_flash_player_10_linux.deb from adobe fixes the freeze, and also upgraded me from flash9 to flash10.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7776889650352147619?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7776889650352147619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7776889650352147619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7776889650352147619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7776889650352147619'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/ubuntu-hardy-firefox-366-freezes.html' title='ubuntu hardy firefox 3.6.6 freezes'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2238620488449962090</id><published>2010-07-02T17:02:00.000-07:00</published><updated>2010-07-02T17:17:57.309-07:00</updated><title type='text'>conservation of responsibility</title><content type='html'>Job descriptions usually specify that they want people with good teamwork skills.  That can be good, but often it means sending out lots of emails asking other people for opinions.  &lt;br /&gt;&lt;br /&gt;In my last blog post I claimed that &lt;a href="http://credentiality2.blogspot.com/2010/07/responsibility-as-bottleneck.html"&gt;capacity for responsibility is a scarce resource&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So lately I've been trying to reduce the number of interrupts and decisions required for decisions that come along.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;me: I'm in town.  Want to have lunch?&lt;br /&gt;Robert: sure!&lt;br /&gt;me: [checks calendar] How about Thursday or Friday?&lt;br /&gt;Robert: [checks calendar] Great, let's do Friday.&lt;br /&gt;me: [checks calendar] 1pm sound okay?&lt;br /&gt;Robert: sure&lt;br /&gt;me: [adds it to our calendars]&lt;br /&gt;&lt;br /&gt;Totals: 7 messages, 5 decisions, 4 uses of calendar.  And that's just to *schedule* it.  Without even talking about where to meet.  Both of us still have to check our calendars on Friday and meet at the right time.&lt;br /&gt;&lt;br /&gt;That could have been reduced to:&lt;br /&gt;me: [adds lunch to our calendars with "hey, I'm in town" to the description]&lt;br /&gt;&lt;br /&gt;Each time someone contacts us, we get a little anticipatory shot of stress as we get ready to read it and find out whether it's good, bad or boring.  Reducing that can free up a lot of responsibility for more important tasks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2238620488449962090?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2238620488449962090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2238620488449962090' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2238620488449962090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2238620488449962090'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/conservation-of-responsibility.html' title='conservation of responsibility'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2545038900376991011</id><published>2010-07-02T16:02:00.000-07:00</published><updated>2010-07-02T16:05:19.910-07:00</updated><title type='text'>code.google.com bugs</title><content type='html'>Trying to report a bug in code.google.com project hosting, I couldn't find anything by searching for "code.google.com bugs", "google code bugs", "code.google.com issues", etc.  Turns out the bug tracker is under the &lt;a href="http://code.google.com/p/support/issues/list"&gt;"support"&lt;/a&gt; project.  (Link goes to the issues page).&lt;br /&gt;&lt;br /&gt;Maybe this will make it more findable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2545038900376991011?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2545038900376991011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2545038900376991011' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2545038900376991011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2545038900376991011'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/codegooglecom-bugs.html' title='code.google.com bugs'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4911402362030720565</id><published>2010-07-02T15:12:00.000-07:00</published><updated>2010-07-02T15:54:59.279-07:00</updated><title type='text'>Responsibility as a bottleneck</title><content type='html'>I'm lucky enough to work at a company that tries give me all the resources I need to get my job done.  Yet I've felt overwhelmed a lot lately, even, no &lt;i&gt;especially&lt;/i&gt; when I find myself goofing off a lot.  And it's because I've exceeded my capacity for responsibility.&lt;br /&gt;&lt;br /&gt;I got the idea from &lt;a href="http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html"&gt;hyperbole and a half&lt;/a&gt;, and it explains a lot of phenomena in our society.&lt;br /&gt;&lt;br /&gt;Let's say I decide to take a for-fun class a the local college.  And it's time to go to class now.&lt;br /&gt;&lt;br /&gt;Oh wait, the car is parked at another building.  And it's low on gas; should I fill up before I go?  And my books are at home.  Do without them?  &lt;br /&gt;&lt;br /&gt;You now have 4 things to do or decisions to make, all before class starts.  Classes have about 16 - 48 class sessions.  If going to class each time involves 4 little tasks, that's up to 200 little obstacles you'll have to handle, just to get to all the classes.  Then there's registration, books, tests, and assignments.  No wonder people don't take more classes on their own.&lt;br /&gt;&lt;br /&gt;Calendars help, but how do you schedule keeping the gas tank full?  Or remembering where you parked?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Here's the point:&lt;/b&gt; there's a limit to the number of things I can keep track of, and the number of decisions I can make in a day.  And that holds me back more than my capacity to do the "actual" labor required to execute those decisions.&lt;br /&gt;&lt;br /&gt;I don't surf the internet like a zombie for hours because the internet is so interesting or addicting.  It's because it's &lt;i&gt;stateless&lt;/i&gt;.  I don't have to remember what I see, or take action on it in three days' time, or have it cascade into dozens of other pressing tasks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4911402362030720565?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4911402362030720565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4911402362030720565' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4911402362030720565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4911402362030720565'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/responsibility-as-bottleneck.html' title='Responsibility as a bottleneck'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2459170187683301531</id><published>2010-07-01T17:47:00.000-07:00</published><updated>2010-07-01T17:57:15.347-07:00</updated><title type='text'>"Unknown end tag for &lt;/a&gt;" error on code.google.com wiki page</title><content type='html'>See &lt;A href="http://code.google.com/p/support/issues/detail?id=4171"&gt;http://code.google.com/p/support/issues/detail?id=4171&lt;/a&gt;.  I was trying to link to an image, and it apparently wants a closing &amp;lt;img&amp;gt; before it can handle the &amp;lt;/a&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2459170187683301531?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2459170187683301531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2459170187683301531' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2459170187683301531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2459170187683301531'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/07/unknown-end-tag-for-error-on.html' title='&quot;Unknown end tag for &amp;lt;/a&amp;gt;&quot; error on code.google.com wiki page'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1452161526940906323</id><published>2010-06-30T17:35:00.000-07:00</published><updated>2010-06-30T17:49:46.667-07:00</updated><title type='text'>Space-filling fabric</title><content type='html'>I just got back my &lt;a href="http://www.spoonflower.com/fabric/246090"&gt;Hilbert Curve space-filling fabric&lt;/a&gt; from spoonflower, a site that'll print any image onto a variety of fabrics.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_oXIW_jM0QDA/TA1_UNzDAmI/AAAAAAAARZA/u55IhuSmdaw/s640/2010-06-07%2016.21.38.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Space-filling fabric is suitable for tiling any plain spots on your walls, or for topological application.  For storage, fold into a moebius strip and store in a &lt;a href="http://www.kleinbottle.com/"&gt;Klein Bottle&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(The “Hilbert Curve” is a recursive space-filling function. If we color the corners of each square instead instead of drawing lines between them, we get the pattern you see below.)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_oXIW_jM0QDA/TCvk451zrmI/AAAAAAAASHU/3_ecHfI1yzU/s1600/hilbert.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 270px; height: 252px;" src="http://4.bp.blogspot.com/_oXIW_jM0QDA/TCvk451zrmI/AAAAAAAASHU/3_ecHfI1yzU/s400/hilbert.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5488732237131394658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Source code and images available at &lt;a href="http://lunkwill.org/src/hilbert/"&gt;http://lunkwill.org/src/hilbert/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1452161526940906323?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1452161526940906323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1452161526940906323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1452161526940906323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1452161526940906323'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/space-filling-fabric.html' title='Space-filling fabric'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_oXIW_jM0QDA/TA1_UNzDAmI/AAAAAAAARZA/u55IhuSmdaw/s72-c/2010-06-07%2016.21.38.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-926295827652339598</id><published>2010-06-29T14:32:00.001-07:00</published><updated>2010-06-29T20:21:34.262-07:00</updated><title type='text'>Technical curriculum sucks</title><content type='html'>My wife just posted to her blog about how much she's enjoying the math classes she's taking at the community college.&lt;br /&gt;&lt;br /&gt;She always did well in math, and had a friend/rival in elementary school who she always competed with to be the best in her math studies.  Then in 6th grade, her teacher wouldn't let her move on to the fast track because she hadn't done enough homework to get an A, even though she was acing the tests.&lt;br /&gt;   &lt;br /&gt;Apart from feeling cheated, she was now also behind in the expected progression for technical fields.  She studied English in college, and never got past college algebra.&lt;br /&gt;&lt;br /&gt;Now she's back in school, thinking of doing a graduate degree in engineering. So she's at the community college, where she's supposed to take several years worth of prerequisites outside her final department, to get the math and science core she feels like she needs just to apply to a good grad school.&lt;br /&gt;&lt;br /&gt;Likewise, my cousin loved astronomy in high school, where they had a neat research-oriented pilot program.  Her project was to study historical photos of nebulas to see if expansion could be tracked over decades.&lt;br /&gt;&lt;br /&gt;I encouraged her to take more when she got to college, but when she saw how many math and other science classes she'd have to take as prerequisites, she also decided to major in English.&lt;br /&gt;&lt;br /&gt;One last related anecdote: I just met Sridhar Vembu last weekend.  He found such a brain drain from the indian universities that he had trouble hiring for his indian software company.  So he started a trade school.  He takes 17-year-old poor kids with interest and a cursory hint of aptitude, and teaches them programming (while giving them a stipend and feeding them).  The curriculum covers programming, english and math in that order of importance, and in that order of preference.  The kids hate abstraction and math notation, but later appreciate it more after they've spent a few months solving practical problems in web programming.  After 6-9 months, almost all of them start working for the company, and they do just as well as the college grads.  As he puts it, "math is the new sanskrit".  &lt;br /&gt;&lt;br /&gt;Oh, and I believe he's taking about half and half girls/boys.  (Except that more of the girls get recruited away by the colleges.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-926295827652339598?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/926295827652339598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=926295827652339598' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/926295827652339598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/926295827652339598'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/technical-curriculum-sucks.html' title='Technical curriculum sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-547389723813980737</id><published>2010-06-29T14:08:00.000-07:00</published><updated>2010-06-29T14:10:50.805-07:00</updated><title type='text'>spreadshirt sucks</title><content type='html'>You'd think that after 10 years of e-commerce, that shopping carts would be a solved problem.  I just sent this feedback to spreadshirt.com.&lt;br /&gt;&lt;br /&gt;Your shopping cart sucks.  I bought a shirt from you through reddit.com, and I'm pretty sure I told it to order 3 shirts, but you only shipped and billed me for 1.  So once I received it, I followed the link from the receipt to reorder.  But clicking on the order number did nothing.  My javascript console tells me that load_order() is undefined.  I very nearly gave up at that point.  So I went to spreadshirt.com directly, and clicked around until I found my order history there, and load_order() is defined from there.  So somebody screwed up the javascript includes.&lt;br /&gt;But it gets better.  I ordered 5 shirts this time, looked for an "update" button and didn't find one, and clicked to continue the order.  Only on the last page of the order process did I notice that the quantity was still at 1.&lt;br /&gt;&lt;br /&gt;So I clicked on my shopping cart to back up the process and fix it.  That showed me the item I was trying to order, and I clicked to proceed.  But you were actually showing me the last page of the process again, so clicking committed the order... for one shirt.&lt;br /&gt;&lt;br /&gt;Now on my fourth trip through the system, you at least gave me the option to cancel the order (thank you), and I once again repeated the process.  And this time I found the "refresh" arrows next to the quantity.  Protip: it's not actually that hard to have javascript code check the value of the quantity field when people click the button to go to the next page.  You're throwing away orders and pissing people off when you expect your customers to find and click a button to tell your page something it should already know.&lt;br /&gt;&lt;br /&gt;Finally, heading to the contact page, I get to enter a captcha (even though I'm already logged in) and type in a little tiny textbox to send you feedback, because you don't want to have to deal with the horrors of actually publishing an email address, even though you demand mine as part of the order process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-547389723813980737?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/547389723813980737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=547389723813980737' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/547389723813980737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/547389723813980737'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/spreadshirt-sucks.html' title='spreadshirt sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5441189772560553033</id><published>2010-06-18T02:05:00.000-07:00</published><updated>2010-06-18T02:08:01.408-07:00</updated><title type='text'>g++ error "does not exist in this scope" in karmic/lucid</title><content type='html'>g++-4.4 breaks backward compatibility for some stupid reason, so things that compiled just fine on earlier systems now break with errors like "stdout does not exist in this scope".&lt;br /&gt;&lt;br /&gt;To fix, sudo apt-get install g++-4.2, then make sure your Makefiles or whatever are set to use g++-4.2 instead of just g++.  You could probably also just apt-get remove g++-4.4, but I'm not sure if that'd break anything.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5441189772560553033?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5441189772560553033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5441189772560553033' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5441189772560553033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5441189772560553033'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/g-error-does-not-exist-in-this-scope-in.html' title='g++ error &quot;does not exist in this scope&quot; in karmic/lucid'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4124947707755188988</id><published>2010-06-17T17:53:00.000-07:00</published><updated>2010-06-17T17:58:47.617-07:00</updated><title type='text'>OS statistics from wikimedia</title><content type='html'>It's surprisingly hard to find statistics on linux distribution popularity by version number.&lt;br /&gt;&lt;br /&gt;But wikipedia to the rescue.  Their squid logs break down user-agent string statistics by OS.  Here's the May 2010 report:&lt;br /&gt;&lt;br /&gt;http://stats.wikimedia.org/archive/squid_reports/2010-05/SquidReportOperatingSystems.htm&lt;br /&gt;&lt;br /&gt;Linux seems to account for about 2% of all browsing.  It looks like some browsers just report "Linux" as their OS, unfortunately.  But among os-versioned browser strings, it looks like Ubuntu dominates linux distros by about 10:1, and almost all Ubuntu users are running either Lucid or Karmic (about 50/50).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4124947707755188988?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4124947707755188988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4124947707755188988' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4124947707755188988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4124947707755188988'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/os-statistics-from-wikimedia.html' title='OS statistics from wikimedia'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-9198805324475151369</id><published>2010-06-16T14:38:00.001-07:00</published><updated>2010-06-16T14:38:19.881-07:00</updated><title type='text'>GoogleCL rocks</title><content type='html'>indeed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-9198805324475151369?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/9198805324475151369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=9198805324475151369' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/9198805324475151369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/9198805324475151369'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/googlecl-rocks.html' title='GoogleCL rocks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3126000683742322624</id><published>2010-06-12T02:15:00.001-07:00</published><updated>2010-06-12T14:30:41.537-07:00</updated><title type='text'>Intuitively simple way to calculate sin and cos</title><content type='html'>A few years ago my brother in law asked how pi is calculated, and we found that it can be done as a &lt;a href="http://en.wikipedia.org/wiki/Numerical_approximations_of_%CF%80#Summing_a_circle.27s_area"&gt;reasonably intuitive algorithm&lt;/a&gt;, without any advanced math.  &lt;br /&gt;&lt;br /&gt;Ever since then, I've wondered if sines and cosines could also be calculated simply.  Here's what I came up with.  Please let me know if you know of a simpler way, where "simpler" means relying on fewer or more elementary mathematical principles.&lt;br /&gt;&lt;br /&gt;Sines and cosines let us translate an angle in a right triangle into the length of one of is sides.  But what is an angle?  Well, on a unit circle, a 45 degree slice cuts off an arc that's 45/360ths the length of the circumference.  We can cut that slice in half by finding the midpoint between the two ends of the arc, then extending that line out until it touches the edge of the circle.  That slice represents 22.5 degrees.  Since we have a point on the unit circle and we know its angle, the point's X and Y coordinates tell us the cosine and sine, respectively, of that angle.  (And since the points are on a circle with a radius of 1, we know the hypotenuse of the right triangles is always of length 1).&lt;br /&gt;&lt;br /&gt;Here's the same concept in pictures:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_oXIW_jM0QDA/TBNKnxiOF4I/AAAAAAAARbM/avVZk2eV6nc/s800/2010-06-12%2001.35.42.jpg"&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_oXIW_jM0QDA/TBNKoMQB2nI/AAAAAAAARbQ/rAqpFfSV5Ic/s800/2010-06-12%2001.35.53.jpg"&gt;&lt;br /&gt;&lt;br /&gt;And here's python code that starts with the two points shown in the pictures, and keeps finding midpoints between them (recursively) until it gets a close enough approximation to any angle you want.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/python&lt;br /&gt;"""&lt;br /&gt;Released into the public domain, 12 June 2010&lt;br /&gt;&lt;br /&gt;This program calculates the sine and cosine of an angle in a geometrically&lt;br /&gt;intuitive way.&lt;br /&gt;&lt;br /&gt;Here's how it works:&lt;br /&gt;&lt;br /&gt;Start with a unit circle and observe that the points (1,0) and (0,1) on the&lt;br /&gt;circumference of the circle are separated by 90 degrees.&lt;br /&gt;&lt;br /&gt;The midpoint between those two points, (0.5, 0.5), bisects that 90&lt;br /&gt;degree angle, forming two 45 degree angles.  We can extend the line from&lt;br /&gt;the origin through (0.5, 0.5) until it reaches the circumference of the unit&lt;br /&gt;circle (that is, until its distance from the origin is 1), and we get&lt;br /&gt;(0.707, 0.707).  Thus we know that the cosine and sine of 45 degrees are both&lt;br /&gt;0.707.&lt;br /&gt;&lt;br /&gt;Likewise, we can find the cosine and sine of 22.5 degrees by taking&lt;br /&gt;the midpoint between (0.707, 0.707) and (1,0), then scaling the line until&lt;br /&gt;it reaches the circumference.  And we can find the cosine and sine of&lt;br /&gt;67.5 degrees by taking the midpoint between (0.707, 0.707) and (0, 1).&lt;br /&gt;&lt;br /&gt;We can continue to bisect angles until we get arbitrarily close to any&lt;br /&gt;angle we choose.  The allowable angular error is set below as MAX_THETA_ERROR.&lt;br /&gt;&lt;br /&gt;Note that this method is agnostic to the angular units we use.  If we start off&lt;br /&gt;by telling the program that (0,1) and (1,0) are separated by an angle of 90,&lt;br /&gt;then the program will return a result measured in degrees.&lt;br /&gt;&lt;br /&gt;If instead we say that (0,1) and (1,0) are separated by pi/2, we'll get a&lt;br /&gt;result in radians.&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;import math&lt;br /&gt;&lt;br /&gt;MAX_THETA_ERROR=0.01&lt;br /&gt;&lt;br /&gt;def cos_sin(theta, x1,y1,theta1, x2,y2,theta2):&lt;br /&gt;  """cos_sin returns the (cosine,sine) of a value within MAX_THETA_ERROR&lt;br /&gt;  units of theta, given two points (x1,y1) and (x2,y2) that live&lt;br /&gt;  at angular posisions theta1 and theta2 on the unit circle.  theta,&lt;br /&gt;  theta1 and theta2 must all have the same kind of angular unit (degrees,&lt;br /&gt;  radians, etc.), but this function doesn't care what that unit is or&lt;br /&gt;  how many of them make up a circle.  &lt;br /&gt;&lt;br /&gt;  theta2 must be greater than theta1, and (x1,y1) and (x2,y2) must be&lt;br /&gt;  points on the circumference of the unit circle, less than 180 degrees&lt;br /&gt;  apart.&lt;br /&gt;&lt;br /&gt;  for example, cos_sin(30.0, 0.0,1.0,0.0, 1,0,0.0,90.0) returns&lt;br /&gt;  (0.866089312575, 0.499889290387), which are the cosine and sine of 30.&lt;br /&gt;  """&lt;br /&gt;&lt;br /&gt;  # Uncomment this to see the successive approximations&lt;br /&gt;  #print "target: %.2f.  (%.2f, %.2f)=%.2f (%.2f,%.2f)=%.2f" % \&lt;br /&gt;  #  (theta, x1, y1, theta1, x2, y2, theta2)&lt;br /&gt;&lt;br /&gt;  # if one of the points is close enough to theta, we're done!&lt;br /&gt;  if (abs(theta1 - theta) &amp;lt; MAX_THETA_ERROR):&lt;br /&gt;    return (x1,y1)&lt;br /&gt;  if (abs(theta2 - theta) &amp;lt; MAX_THETA_ERROR):&lt;br /&gt;    return (x2,y2)&lt;br /&gt;&lt;br /&gt;  # the midpoint is just the average of the two points&lt;br /&gt;  x_midpoint = (x1 + x2) / 2.0;&lt;br /&gt;  y_midpoint = (y1 + y2) / 2.0;&lt;br /&gt;&lt;br /&gt;  # scale (x_midpoint,y_midpoint) by 1/midpoint_length to get a point&lt;br /&gt;  # exactly 1 unit away from the origin&lt;br /&gt;  midpoint_length = math.sqrt(x_midpoint*x_midpoint + y_midpoint*y_midpoint)&lt;br /&gt;  x_midpoint = x_midpoint / midpoint_length&lt;br /&gt;  y_midpoint = y_midpoint / midpoint_length&lt;br /&gt;&lt;br /&gt;  # the midpoint bisects the angle between the two points&lt;br /&gt;  theta_midpoint = (theta1 + theta2) / 2.0;&lt;br /&gt;&lt;br /&gt;  # figure out which side of the midpoint our target value theta lives on,&lt;br /&gt;  # and bisect the extended midpoint with one of the original points to get&lt;br /&gt;  # closer to the target&lt;br /&gt;  if (theta &amp;gt;= theta_midpoint):&lt;br /&gt;    return cos_sin(theta, x_midpoint, y_midpoint, theta_midpoint, x2, y2, theta2)&lt;br /&gt;  else:&lt;br /&gt;    return cos_sin(theta, x1, y1, theta1, x_midpoint, y_midpoint, theta_midpoint)&lt;br /&gt;&lt;br /&gt;angle = 30.0&lt;br /&gt;(cosine, sine) = cos_sin(angle, 1.0,0.0,0.0,  0.0,1.0,90.0)&lt;br /&gt;print "The cosine of %.2f is %.2f" % (angle, cosine)&lt;br /&gt;print "The sine of %.2f is %.2f" % (angle, sine)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3126000683742322624?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3126000683742322624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3126000683742322624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3126000683742322624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3126000683742322624'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/few-years-ago-my-brother-in-law-asked.html' title='Intuitively simple way to calculate sin and cos'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_oXIW_jM0QDA/TBNKnxiOF4I/AAAAAAAARbM/avVZk2eV6nc/s72-c/2010-06-12%2001.35.42.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8208875648471496524</id><published>2010-06-03T17:08:00.000-07:00</published><updated>2010-06-03T18:50:15.106-07:00</updated><title type='text'>Going from odometry to position in a two-wheeled robot</title><content type='html'>My robot has two drive wheels on which I have odometry (plus some casters that we'll ignore).  I want to use the odometry from the wheel encoders to keep track of where I've gone since I started counting.&lt;br /&gt;&lt;br /&gt;Let's say the right wheel moves b inches while the left wheel moved a inches during some time interval.  Assume b &gt; a.  Then if we let the robot keep moving forever with those wheel speeds, the robot will make a big circle counterclockwise on the floor about some point X.  We want to find X so that we can use a and b to find the new wheel positions on the floor.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh6.ggpht.com/_oXIW_jM0QDA/TAg61rLvwBI/AAAAAAAARXU/vp5frqt1TVM/s576/2010-06-03%2016.28.17.jpg"&gt;&lt;br /&gt;&lt;br /&gt;We want to find ra, the distance from the left wheel to X.&lt;br /&gt;&lt;br /&gt;We start by imagining the circumference of the circle the left wheel would travel in: ca.  ca = 2*pi*ra.  The right wheel's circle will have a radius of ra+w, where w is the wheelbase of the robot.&lt;br /&gt;&lt;br /&gt;Since the two wheels are circling the same point on the floor with the axle always pointing toward the center of the circles, we know the distances a and b will constitute the same proportion of their respective circles.  (If a goes all the way around its circle, b must have gone all the way around its circle too.  Likewise if a goes 1/10th of the way around, etc.)&lt;br /&gt;&lt;br /&gt;So we know that a/ca = b/cb, which is also the proportion of the circle we traveled (if a/ca = 0.10 then we've gone 10% around the circle).  Substitute and solve and we get ra = w*a / (b-a).&lt;br /&gt;&lt;br /&gt;Great!  Now we know our radius of curvature.&lt;br /&gt;&lt;br /&gt;Next, we want to find X, the actual point on the floor that we're circling.  We start by finding theta, the angle we moved around the circle, by simply multiplying a/ca by 360 (for example, 0.10 * 360 = 36 degrees).  If we want it in radians instead of degrees, it's even simpler, since multiplying by 2*PI cancels out the 2*PI in ca, leaving just a/ra.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_oXIW_jM0QDA/TAg66v1-ecI/AAAAAAAARXc/UjRaJPAuJUE/s576/2010-06-03%2016.29.06.jpg"&gt;&lt;br /&gt;&lt;br /&gt;We know that the point X is ra inches to the left of Pa, along a line which also passes through Pb.  (X, Pa and Pb are 2-dimensional points).  We get a vector from Pb to Pa with (Pa-Pb), make it length 1 by dividing by w, then multiply by ra so it's the right length to reach from Pa to X.  Then we add it to Pa so that the vector ends at X.&lt;br /&gt;&lt;br /&gt;Now we can find the updated wheel locations on the floor by rotating Pa and Pb by theta degrees around the point X.  How do we do that?  Well, we translate everything so that X is at the origin, then use a rotation matrix to rotate by theta, then translate back so that X is where it started:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_oXIW_jM0QDA/TAg7HSPDZ_I/AAAAAAAARXk/qzQKYbMHOpg/s576/2010-06-03%2016.30.09.jpg"&gt;&lt;br /&gt;&lt;br /&gt;Here's code that implements all of that (with saner variable names), plus the case where both wheels move the same amount):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Just some math to turn wheel odometry into position updates&lt;br /&gt;// Released into the public domain 3 June 2010&lt;br /&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;math.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define PI (3.14159)&lt;br /&gt;&lt;br /&gt;#define WHEELBASE (12.0)&lt;br /&gt;&lt;br /&gt;// left wheel&lt;br /&gt;double Lx = -WHEELBASE/2.0;&lt;br /&gt;double Ly = 0.0;&lt;br /&gt;&lt;br /&gt;// right wheel&lt;br /&gt;double Rx = WHEELBASE/2.0;&lt;br /&gt;double Ry = 0.0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// given distances traveled by each wheel, updates the&lt;br /&gt;// wheel position globals&lt;br /&gt;void update_wheel_position(double l, double r) {&lt;br /&gt;&lt;br /&gt;  if (fabs(r - l) &amp;lt; 0.001) {&lt;br /&gt;    // If both wheels moved about the same distance, then we get an infinite&lt;br /&gt;    // radius of curvature.  This handles that case.&lt;br /&gt;&lt;br /&gt;    // find forward by rotating the axle between the wheels 90 degrees&lt;br /&gt;    double axlex = Rx - Lx;&lt;br /&gt;    double axley = Ry - Ly;&lt;br /&gt;&lt;br /&gt;    double forwardx, forwardy;&lt;br /&gt;    forwardx = -axley;&lt;br /&gt;    forwardy = axlex;&lt;br /&gt;&lt;br /&gt;    // normalize&lt;br /&gt;    double length = sqrt(forwardx*forwardx + forwardy*forwardy);&lt;br /&gt;    forwardx = forwardx / length;&lt;br /&gt;    forwardy = forwardy / length;&lt;br /&gt;&lt;br /&gt;    // move each wheel forward by the amount it moved&lt;br /&gt;    Lx = Lx + forwardx * l;&lt;br /&gt;    Ly = Ly + forwardy * l;&lt;br /&gt;&lt;br /&gt;    Rx = Rx + forwardx * r;&lt;br /&gt;    Ry = Ry + forwardy * r;&lt;br /&gt;    &lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  double rl; // radius of curvature for left wheel&lt;br /&gt;  rl = WHEELBASE * l / (r - l);&lt;br /&gt;&lt;br /&gt;  printf("Radius of curvature (left wheel): %.2lf\n", rl);&lt;br /&gt;&lt;br /&gt;  double theta; // angle we moved around the circle, in radians&lt;br /&gt;  // theta = 2 * PI * (l / (2 * PI * rl)) simplifies to:&lt;br /&gt;  theta = l / rl;&lt;br /&gt;&lt;br /&gt;  printf("Theta: %.2lf radians\n", theta);&lt;br /&gt;&lt;br /&gt;  // Find the point P that we're circling&lt;br /&gt;  double Px, Py;&lt;br /&gt;&lt;br /&gt;  Px = Lx + rl*((Lx-Rx)/WHEELBASE);&lt;br /&gt;  Py = Ly + rl*((Ly-Ry)/WHEELBASE);&lt;br /&gt;&lt;br /&gt;  printf("Center of rotation: (%.2lf, %.2lf)\n", Px, Py);&lt;br /&gt;&lt;br /&gt;  // Translate everything to the origin&lt;br /&gt;  double Lx_translated = Lx - Px;&lt;br /&gt;  double Ly_translated = Ly - Py;&lt;br /&gt;&lt;br /&gt;  double Rx_translated = Rx - Px;&lt;br /&gt;  double Ry_translated = Ry - Py;&lt;br /&gt;&lt;br /&gt;  printf("Translated: (%.2lf,%.2lf) (%.2lf,%.2lf)\n",&lt;br /&gt;    Lx_translated, Ly_translated,&lt;br /&gt;    Rx_translated, Ry_translated);&lt;br /&gt;&lt;br /&gt;  // Rotate by theta&lt;br /&gt;  double cos_theta = cos(theta);&lt;br /&gt;  double sin_theta = sin(theta);&lt;br /&gt;&lt;br /&gt;  printf("cos(theta)=%.2lf sin(theta)=%.2lf\n", cos_theta, sin_theta);&lt;br /&gt;&lt;br /&gt;  double Lx_rotated = Lx_translated*cos_theta - Ly_translated*sin_theta;&lt;br /&gt;  double Ly_rotated = Lx_translated*sin_theta + Ly_translated*sin_theta;&lt;br /&gt;&lt;br /&gt;  double Rx_rotated = Rx_translated*cos_theta - Ry_translated*sin_theta;&lt;br /&gt;  double Ry_rotated = Rx_translated*sin_theta + Ry_translated*sin_theta;&lt;br /&gt;&lt;br /&gt;  printf("Rotated: (%.2lf,%.2lf) (%.2lf,%.2lf)\n",&lt;br /&gt;    Lx_rotated, Ly_rotated,&lt;br /&gt;    Rx_rotated, Ry_rotated);&lt;br /&gt;&lt;br /&gt;  // Translate back&lt;br /&gt;  Lx = Lx_rotated + Px;&lt;br /&gt;  Ly = Ly_rotated + Py;&lt;br /&gt;&lt;br /&gt;  Rx = Rx_rotated + Px;&lt;br /&gt;  Ry = Ry_rotated + Py;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;main(int argc, char **argv) {&lt;br /&gt;  if (argc != 3) {&lt;br /&gt;    printf("Usage: %s left right\nwhere left and right are distances.\n",&lt;br /&gt;      argv[0]);&lt;br /&gt;    return 1;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  double left = atof(argv[1]);&lt;br /&gt;  double right = atof(argv[2]);&lt;br /&gt;&lt;br /&gt;  printf("Old wheel positions: (%lf,%lf) (%lf,%lf)\n",&lt;br /&gt;    Lx, Ly, Rx, Ry);&lt;br /&gt;  update_wheel_position(left, right);&lt;br /&gt;  printf("New wheel positions: (%lf,%lf) (%lf,%lf)\n",&lt;br /&gt;    Lx, Ly, Rx, Ry);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8208875648471496524?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8208875648471496524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8208875648471496524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8208875648471496524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8208875648471496524'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/going-from-odometry-to-position-in-two.html' title='Going from odometry to position in a two-wheeled robot'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_oXIW_jM0QDA/TAg61rLvwBI/AAAAAAAARXU/vp5frqt1TVM/s72-c/2010-06-03%2016.28.17.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4555105898445683283</id><published>2010-06-02T15:14:00.001-07:00</published><updated>2010-07-20T21:28:13.904-07:00</updated><title type='text'>atmel atmega32 avr-libc interrupt example</title><content type='html'>Edit: Fixed a bug in the example code where I tried to do _BV(foo|bar), which doesn't work at all.  Changed them to (_BV(foo) | _BV(bar)).  Also added a #define for _BV in case you don't already have it.  I think this code is correct, but I haven't tried it.&lt;br /&gt;&lt;br /&gt;I wanted to read a pair of quadrature encoders with my atmega32, so I needed to enable the INT0 and INT1 pins.  Incidentally, if you don't mind throwing away half the resolution of your encoder, you can get away with using only one interrupt per encoder.  (You put one of the pair of sensors on an interrupt, and the other one on a regular GPIO pin.  You get interrupts half as often, and the other sensor tells you which way you moved).&lt;br /&gt;&lt;br /&gt;Here's the code I used.  The compiler complained about using obsolete avr-libc identifiers, but it seems to work fine.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;&lt;br /&gt;// Just count the number of interrupts we see&lt;br /&gt;int interrupt_counter = 0;&lt;br /&gt;SIGNAL(SIG_INTERRUPT0) {&lt;br /&gt;interrupt_counter++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// I got lots of random resets until I added this handler.  So apparently you shouldn't enable&lt;br /&gt;// an interrupt unless you have a handler installed.&lt;br /&gt;SIGNAL(SIG_INTERRUPT1) {&lt;br /&gt;interrupt_counter++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;And then in my init code:&lt;br /&gt;&lt;br /&gt;#define _BV(x) (1 &lt;&lt; (x))&lt;br /&gt;&lt;br /&gt;// setup for servicing INT0, INT1 interrupt pins&lt;br /&gt;&lt;br /&gt;// generate an interrupt on any logical change&lt;br /&gt;MCUCR |= _BV(ISC10);&lt;br /&gt;MCUCR &amp;= ~_BV(ISC11);&lt;br /&gt;&lt;br /&gt;MCUCR |= _BV(ISC00);&lt;br /&gt;MCUCR &amp;= ~_BV(ISC01);&lt;br /&gt;&lt;br /&gt;// enable the interrupt pins&lt;br /&gt;GICR |= _BV(INT1) | _BV(INT0);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Set d2 and d3 to be inputs&lt;br /&gt;DDRD &amp;= ~(_BV(PD2) | _BV(PD3));&lt;br /&gt;&lt;br /&gt;// Pullups off&lt;br /&gt;PORTD &amp;= ~(_BV(PD2) | _BV(PD3));&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4555105898445683283?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4555105898445683283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4555105898445683283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4555105898445683283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4555105898445683283'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/06/atmel-atmega32-avr-libc-interrupt.html' title='atmel atmega32 avr-libc interrupt example'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1230046857294561425</id><published>2010-05-27T18:08:00.001-07:00</published><updated>2010-05-27T18:08:12.613-07:00</updated><title type='text'>Another test post</title><content type='html'>Wow, I love posting to blogger from the command line&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1230046857294561425?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1230046857294561425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1230046857294561425' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1230046857294561425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1230046857294561425'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/05/another-test-post_6613.html' title='Another test post'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7459670990292972437</id><published>2010-05-24T00:40:00.001-07:00</published><updated>2010-05-24T00:40:14.984-07:00</updated><title type='text'>Test post</title><content type='html'>This post generated via the gdata API&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7459670990292972437?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7459670990292972437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7459670990292972437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7459670990292972437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7459670990292972437'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/05/test-post.html' title='Test post'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8293279093978332008</id><published>2010-05-17T16:43:00.000-07:00</published><updated>2010-05-17T16:48:26.973-07:00</updated><title type='text'>Getting my ar5212 wifi card to search for an access point</title><content type='html'>On ubuntu karmic, I uninstalled network-manager and tried to configure my Thinkpad T41p's ar5212 wireless connection manually.&lt;br /&gt;&lt;br /&gt;iwconfig wlan0 essid MyEssid&lt;br /&gt;iwconfig wlan0 txpower auto&lt;br /&gt;&lt;br /&gt;When I run iwconfig, it says "not associated" and doesn't appear to be looking for an AP.  It'll stay like this forever.&lt;br /&gt;&lt;br /&gt;But if I run dhclient wlan0, within a few seconds it'll associate and get an address as expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8293279093978332008?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8293279093978332008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8293279093978332008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8293279093978332008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8293279093978332008'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/05/getting-my-ar5212-wifi-card-to-search.html' title='Getting my ar5212 wifi card to search for an access point'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7952613257515259536</id><published>2010-05-14T17:48:00.001-07:00</published><updated>2010-05-14T17:51:36.164-07:00</updated><title type='text'>sudo sucks</title><content type='html'>sudo helpfully won't let you do anything as root anymore if you disturb its precious 440 permissions. Because, you know, having root be able to write the file would be INSECURE.  FML.&lt;br /&gt;&lt;br /&gt;Edit: Whee!!  It even helpfully segfaults on karmic:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ sudo bash&lt;br /&gt;sudo: /etc/sudoers is mode 0640, should be 0440&lt;br /&gt;Segmentation fault&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7952613257515259536?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7952613257515259536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7952613257515259536' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7952613257515259536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7952613257515259536'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/05/sudo-sucks.html' title='sudo sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8991045667528985815</id><published>2010-05-10T21:09:00.000-07:00</published><updated>2010-05-10T21:11:00.653-07:00</updated><title type='text'>Avoiding the annoying "no write since last change" vim message</title><content type='html'>Whenever I'm on a new machine, it drives me nuts when the default vi install won't let me :bn without saving first.  Adding ":set hidden" to my .vimrc fixes that, letting me switch buffers without saving first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8991045667528985815?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8991045667528985815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8991045667528985815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8991045667528985815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8991045667528985815'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/05/avoiding-annoying-no-write-since-last.html' title='Avoiding the annoying &quot;no write since last change&quot; vim message'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2983839121752443452</id><published>2010-04-25T14:32:00.000-07:00</published><updated>2010-04-25T14:37:28.225-07:00</updated><title type='text'>Working with named pipes in tcl</title><content type='html'>Today I wanted to pipe lines of output from a C program into a TCL program using a named pipe, so that I didn't have to start them up at the same time.  First I created the pipe with mkfifo:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ mkfifo foo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then here's the magic incantation in TCL to open the pipe and run a function every time something comes in:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set fifo [open "foo" {RDWR NONBLOCK}]&lt;br /&gt;fconfigure $fifo -blocking 1&lt;br /&gt;proc read_fifo {} {&lt;br /&gt;  global fifo&lt;br /&gt;&lt;br /&gt;  gets $fifo x&lt;br /&gt;  puts "x is $x"&lt;br /&gt;}&lt;br /&gt;fileevent $fifo readable read_fifo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then when I write to the fifo, my program prints them:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ echo "asdf" &gt; foo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Make sure you write newlines when you write to the fifo so that gets doesn't block (or use read instead).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2983839121752443452?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2983839121752443452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2983839121752443452' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2983839121752443452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2983839121752443452'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/working-with-named-pipes-in-tcl.html' title='Working with named pipes in tcl'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3495660805944348300</id><published>2010-04-24T18:43:00.000-07:00</published><updated>2010-04-24T18:47:52.288-07:00</updated><title type='text'>Chicken tortilla casserole</title><content type='html'>Quick and easy.&lt;br /&gt;&lt;br /&gt;1 can cream of mushroom soup&lt;br /&gt;1 can cream of celery soup&lt;br /&gt;1 onion, chopped&lt;br /&gt;3 boneless chicken breasts, diced&lt;br /&gt;1 can chopped tomatoes (or use fresh tomatoes)&lt;br /&gt;1 small can green chiles (or fresh)&lt;br /&gt;1 small can olives&lt;br /&gt;4 or more corn tortillas, cut into strips&lt;br /&gt;8-16 ounces grated mozzarella or cheddar cheese&lt;br /&gt;1 cup salsa&lt;br /&gt;&lt;br /&gt;Mix up all the liquid and small stuff in a glass 9x13" casserole dish, then mix in the tortillas and chicken.  Top with cheese.  350F for one hour.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3495660805944348300?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3495660805944348300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3495660805944348300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3495660805944348300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3495660805944348300'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/chicken-tortilla-casserole.html' title='Chicken tortilla casserole'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4890737926884418763</id><published>2010-04-18T15:23:00.000-07:00</published><updated>2010-06-22T21:07:53.574-07:00</updated><title type='text'>v4l2 example</title><content type='html'>Update: Updated the &lt;a href="https://docs.google.com/leaf?id=0B8R6VSvTZHZWYjQxYzVmOTktZWEyOC00MWRkLWI1MjItMTFiOTBmMGM4MWRk&amp;hl=en"&gt;sample code&lt;/a&gt; to spit out a grayscale ASCII PGM on stdout so you can actually see what it's&lt;br /&gt;capturing.&lt;br /&gt;&lt;br /&gt;Looks like the video4linux project could use a convenience library for people who want to do simple things.  But at least they have good example code.&lt;br /&gt;&lt;br /&gt;The official &lt;a href="http://v4l2spec.bytesex.org/"&gt;v4l2 example&lt;/a&gt; worked pretty well for me.  It worked fine with my capture card, but I got "VIDIOC_S_FMT error 22, Invalid argument" errors when I tried it with my webcam.  Switching to "V4L2_PIX_FMT_YUV420" from "V4L2_PIX_FMT_YUYV" fixed it. I also simplified it a bit, taking out the command line options, MMAP code and the USERP (which didn't work for me anyway).  It gets the example down from 675 lines to a little under 300, and makes it a little closer to my purposes.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/*&lt;br /&gt; *  V4L2 video capture example&lt;br /&gt; *&lt;br /&gt; *  This program can be used and distributed without restrictions.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;        /* low-level i/o */&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;#include &amp;lt;malloc.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/mman.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;asm/types.h&amp;gt;    /* for videodev2.h */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;linux/videodev2.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define CLEAR(x) memset (&amp;amp;(x), 0, sizeof (x))&lt;br /&gt;&lt;br /&gt;struct buffer {&lt;br /&gt;  void *start;&lt;br /&gt;  size_t length;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;static int fd = -1;&lt;br /&gt;struct buffer *buffers = NULL;&lt;br /&gt;static unsigned int n_buffers = 0;&lt;br /&gt;&lt;br /&gt;static void errno_exit(const char *s) {&lt;br /&gt;  fprintf (stderr, "%s error %d, %s\n", s, errno, strerror (errno));&lt;br /&gt;&lt;br /&gt;  exit (EXIT_FAILURE);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int xioctl(int fd, int request, void * arg) {&lt;br /&gt;  int r;&lt;br /&gt;&lt;br /&gt;  do r = ioctl (fd, request, arg);&lt;br /&gt;  while (-1 == r &amp;amp;&amp;amp; EINTR == errno);&lt;br /&gt;&lt;br /&gt;  return r;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void process_image(const void *p) {&lt;br /&gt;  fputc ('.', stdout);&lt;br /&gt;  fflush (stdout);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int read_frame(void) {&lt;br /&gt;  struct v4l2_buffer buf;&lt;br /&gt;  unsigned int i;&lt;br /&gt;&lt;br /&gt;  if (-1 == read (fd, buffers[0].start, buffers[0].length)) {&lt;br /&gt;    switch (errno) {&lt;br /&gt;      case EAGAIN:&lt;br /&gt;          return 0;&lt;br /&gt;&lt;br /&gt;    case EIO:&lt;br /&gt;      /* Could ignore EIO, see spec. */&lt;br /&gt;      /* fall through */&lt;br /&gt;&lt;br /&gt;    default:&lt;br /&gt;      errno_exit ("read");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  process_image (buffers[0].start);&lt;br /&gt;&lt;br /&gt;  return 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void mainloop(void) {&lt;br /&gt;  unsigned int count;&lt;br /&gt;&lt;br /&gt;  count = 100;&lt;br /&gt;&lt;br /&gt;  while (count-- &amp;gt; 0) {&lt;br /&gt;    for (;;) {&lt;br /&gt;      fd_set fds;&lt;br /&gt;      struct timeval tv;&lt;br /&gt;      int r;&lt;br /&gt;&lt;br /&gt;      FD_ZERO (&amp;amp;fds);&lt;br /&gt;      FD_SET (fd, &amp;amp;fds);&lt;br /&gt;&lt;br /&gt;      /* Timeout. */&lt;br /&gt;      tv.tv_sec = 2;&lt;br /&gt;      tv.tv_usec = 0;&lt;br /&gt;&lt;br /&gt;      r = select (fd + 1, &amp;amp;fds, NULL, NULL, &amp;amp;tv);&lt;br /&gt;&lt;br /&gt;      if (-1 == r) {&lt;br /&gt;        if (EINTR == errno)&lt;br /&gt;          continue;&lt;br /&gt;&lt;br /&gt;        errno_exit ("select");&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      if (0 == r) {&lt;br /&gt;        fprintf (stderr, "select timeout\n");&lt;br /&gt;        exit (EXIT_FAILURE);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      if (read_frame ())&lt;br /&gt;            break;&lt;br /&gt;  &lt;br /&gt;      /* EAGAIN - continue select loop. */&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void uninit_device(void) {&lt;br /&gt;  unsigned int i;&lt;br /&gt;&lt;br /&gt;  free (buffers[0].start);&lt;br /&gt;  free (buffers);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void init_read(unsigned int buffer_size) {&lt;br /&gt;  buffers = calloc (1, sizeof (*buffers));&lt;br /&gt;&lt;br /&gt;  if (!buffers) {&lt;br /&gt;    fprintf (stderr, "Out of memory\n");&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  buffers[0].length = buffer_size;&lt;br /&gt;  buffers[0].start = malloc (buffer_size);&lt;br /&gt;&lt;br /&gt;  if (!buffers[0].start) {&lt;br /&gt;        fprintf (stderr, "Out of memory\n");&lt;br /&gt;        exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void init_device(char *dev_name) {&lt;br /&gt;  struct v4l2_capability cap;&lt;br /&gt;  struct v4l2_cropcap cropcap;&lt;br /&gt;  struct v4l2_crop crop;&lt;br /&gt;  struct v4l2_format fmt;&lt;br /&gt;  unsigned int min;&lt;br /&gt;&lt;br /&gt;  if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &amp;amp;cap)) {&lt;br /&gt;    if (EINVAL == errno) {&lt;br /&gt;      fprintf (stderr, "%s is no V4L2 device\n",&lt;br /&gt;         dev_name);&lt;br /&gt;      exit (EXIT_FAILURE);&lt;br /&gt;    } else {&lt;br /&gt;      errno_exit ("VIDIOC_QUERYCAP");&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!(cap.capabilities &amp;amp; V4L2_CAP_VIDEO_CAPTURE)) {&lt;br /&gt;    fprintf (stderr, "%s is no video capture device\n",&lt;br /&gt;       dev_name);&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!(cap.capabilities &amp;amp; V4L2_CAP_READWRITE)) {&lt;br /&gt;    fprintf (stderr, "%s does not support read i/o\n",&lt;br /&gt;       dev_name);&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /* Select video input, video standard and tune here. */&lt;br /&gt;&lt;br /&gt;  CLEAR (cropcap);&lt;br /&gt;&lt;br /&gt;  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;&lt;br /&gt;&lt;br /&gt;  if (0 == xioctl (fd, VIDIOC_CROPCAP, &amp;amp;cropcap)) {&lt;br /&gt;    crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;&lt;br /&gt;    crop.c = cropcap.defrect; /* reset to default */&lt;br /&gt;&lt;br /&gt;    if (-1 == xioctl (fd, VIDIOC_S_CROP, &amp;amp;crop)) {&lt;br /&gt;      switch (errno) {&lt;br /&gt;      case EINVAL:&lt;br /&gt;        /* Cropping not supported. */&lt;br /&gt;        break;&lt;br /&gt;      default:&lt;br /&gt;        /* Errors ignored. */&lt;br /&gt;        break;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  } else {  &lt;br /&gt;    /* Errors ignored. */&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  CLEAR (fmt);&lt;br /&gt;&lt;br /&gt;  fmt.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;&lt;br /&gt;  fmt.fmt.pix.width       = 640; &lt;br /&gt;  fmt.fmt.pix.height      = 480;&lt;br /&gt;&lt;br /&gt;// This worked with my capture card, but bombed with&lt;br /&gt;// "VIDIOC_S_FMT error 22, Invalid argument" on my Logitech QuickCam Pro 4000&lt;br /&gt;// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;&lt;br /&gt;// This worked on the logitech:&lt;br /&gt;  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;&lt;br /&gt;&lt;br /&gt;  fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;&lt;br /&gt;&lt;br /&gt;  if (-1 == xioctl(fd, VIDIOC_S_FMT, &amp;amp;fmt))&lt;br /&gt;    errno_exit("VIDIOC_S_FMT");&lt;br /&gt;&lt;br /&gt;  /* Note VIDIOC_S_FMT may change width and height. */&lt;br /&gt;&lt;br /&gt;  /* Buggy driver paranoia. */&lt;br /&gt;  min = fmt.fmt.pix.width * 2;&lt;br /&gt;  if (fmt.fmt.pix.bytesperline &amp;lt; min)&lt;br /&gt;    fmt.fmt.pix.bytesperline = min;&lt;br /&gt;  min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;&lt;br /&gt;  if (fmt.fmt.pix.sizeimage &amp;lt; min)&lt;br /&gt;    fmt.fmt.pix.sizeimage = min;&lt;br /&gt;&lt;br /&gt;  init_read (fmt.fmt.pix.sizeimage);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void close_device(void) {&lt;br /&gt;  if (-1 == close (fd))&lt;br /&gt;    errno_exit ("close");&lt;br /&gt;&lt;br /&gt;  fd = -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void open_device(char *dev_name) {&lt;br /&gt;  struct stat st; &lt;br /&gt;&lt;br /&gt;  if (-1 == stat (dev_name, &amp;amp;st)) {&lt;br /&gt;    fprintf (stderr, "Cannot identify '%s': %d, %s\n",&lt;br /&gt;       dev_name, errno, strerror (errno));&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!S_ISCHR (st.st_mode)) {&lt;br /&gt;    fprintf (stderr, "%s is no device\n", dev_name);&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);&lt;br /&gt;&lt;br /&gt;  if (-1 == fd) {&lt;br /&gt;    fprintf (stderr, "Cannot open '%s': %d, %s\n",&lt;br /&gt;       dev_name, errno, strerror (errno));&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;  char *dev_name = "/dev/video1";&lt;br /&gt;&lt;br /&gt;  open_device(dev_name);&lt;br /&gt;  init_device(dev_name);&lt;br /&gt;  mainloop();&lt;br /&gt;  uninit_device();&lt;br /&gt;  close_device();&lt;br /&gt;&lt;br /&gt;  exit(EXIT_SUCCESS);&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4890737926884418763?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4890737926884418763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4890737926884418763' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4890737926884418763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4890737926884418763'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/v4l2-example.html' title='v4l2 example'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-2817778583916915737</id><published>2010-04-16T13:21:00.000-07:00</published><updated>2010-04-17T15:17:49.675-07:00</updated><title type='text'>ubuntu karmic grub error: "no such device" uuid/search nonsense</title><content type='html'>After cloning my recent karmic koala (9.10) install to another machine, I was annoyed that it wouldn't boot.  It said:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;error: no such device: ....&lt;br /&gt;&lt;br /&gt;  Failed to boot default entries.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Karmic now locates disk by UUID instead of the more traditional /dev/sda notation, which sucks when you want to clone a disk.  But it's easy enough to fix.&lt;br /&gt;&lt;br /&gt;To get it to boot once, use "e" from the grub menu to edit the command line.  Remove the entire line that says:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;search --no-floppy --fs-uuid --set ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then change the root= option in the next line to use /dev/sda1 instead of mounting by UUID:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/libux/boot/vmlinuz-... root=/dev/sda1 ro quiet splash&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then hit control-x to boot with those settings.&lt;br /&gt;&lt;br /&gt;To fix it for good once the system boots, sudo gedit /etc/default/grub and uncomment this line:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux&lt;br /&gt;GRUB_DISABLE_LINUX_UUID=true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next, sudo gedit /etc/fstab and replace the UUID=... with /dev/sda1 for the / partition and /dev/sda5 for the swap partition (assuming you had ubuntu use the whole disk during install).&lt;br /&gt;&lt;br /&gt;Finally, sudo gedit /usr/lib/grub/grub-mkconfig_lib and find this line (line 174 for me):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    echo "search --no-floppy --fs-uuid --set ${fs_uuid}"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Change it to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    echo ""&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, sudo update-grub2 to write the changes to disk.  Then cross your fingers and reboot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-2817778583916915737?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/2817778583916915737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=2817778583916915737' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2817778583916915737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/2817778583916915737'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/ubuntu-karmic-grub-error-no-such-device.html' title='ubuntu karmic grub error: &quot;no such device&quot; uuid/search nonsense'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6980776935350211724</id><published>2010-04-14T21:06:00.000-07:00</published><updated>2010-04-14T21:08:16.426-07:00</updated><title type='text'>Running gnome applications over ssh</title><content type='html'>If you "ssh -X" into some machine and can run X apps fine, but can't run some gnome apps, and get errors about dbus sockets, run "export `dbus-launch`" from your ssh session to set up the environment variables you need.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6980776935350211724?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6980776935350211724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6980776935350211724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6980776935350211724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6980776935350211724'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/running-gnome-applications-over-ssh.html' title='Running gnome applications over ssh'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1239405147444054930</id><published>2010-04-11T18:16:00.000-07:00</published><updated>2010-08-09T15:10:03.966-07:00</updated><title type='text'>Ubuntu Linux Sketchup using Wine</title><content type='html'>Update2: I found a much more general solution to the &lt;a href="http://credentiality2.blogspot.com/2010/07/xorg-window-redraw-workaround-by.html"&gt;redraw problem&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Update: I'm not sure if that worked or not.  I think it improved the situation, but didn't fix the refresh problems entirely.&lt;br /&gt;&lt;br /&gt;I've been using Sketchup successfully for quite a while now in Ubuntu linux.  The trick was to install the &lt;a href="https://launchpad.net/~ubuntu-wine/+archive/ppa"&gt;wine PPA&lt;/a&gt; in order to get a more recent version of wine than Ubuntu distributes by default.&lt;br /&gt;&lt;br /&gt;However, at home I had screen update problems: for instance, when I'd mouse over a face with the push/pull tool, it wouldn't draw in the crosshatching until I left the face.  &lt;br /&gt;&lt;br /&gt;But today I figured out how to solve the refresh problems, thanks to a comment in the &lt;a href="http://appdb.winehq.org/objectManager.php?sClass=version&amp;iId=14562"&gt;wine appdb entry for sketchup 7&lt;/a&gt;.  I ran nvidia-settings, then set:&lt;br /&gt;&lt;br /&gt;NVIDIA X Server Settings manager checked &lt;br /&gt;Antialiasing Settings - Override Application - Off &lt;br /&gt;Anisotropic Filtering - Override Application - 1x &lt;br /&gt;&lt;br /&gt;The next time I started up sketchup, it worked fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1239405147444054930?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1239405147444054930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1239405147444054930' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1239405147444054930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1239405147444054930'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/ubuntu-linux-sketchup-using-wine.html' title='Ubuntu Linux Sketchup using Wine'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5532072636025812077</id><published>2010-04-10T13:17:00.000-07:00</published><updated>2010-04-10T13:32:22.626-07:00</updated><title type='text'>balancethebudget.com</title><content type='html'>This is a pretty neat site that shows how the federal budget breaks down and lets you try your hand at balancing the budget:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://balancethebudget.com/#"&gt;http://balancethebudget.com/#&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Seems to be unbiased. I was recently surprised by these numbers about state and local spending, which show, for instance, that we actually spend more on education tha...n defense. So it'd be interesting to see state and local budgets represented as well:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.usgovernmentspending.com/year2006_0.html"&gt;http://www.usgovernmentspending.com/year2006_0.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'd also like it to break down my own tax burden, since it's hard to contextualize billions and trillions. I'd rather see it as: "you spent $17 this year on farm subsidies, $7313 on defense, $7819 on public schools..."&lt;br /&gt;&lt;br /&gt;I also think it'd be neat to let people see what would happen if individual tax checks went directly to specific programs, until those programs filled up.  That is, I could enter my approximate income or how much my total tax burden was.  Then a roulette wheel would spin, and it'd have a N percent chance of landing in the "defense" category, since defense uses N% of the budget.  Then it'd drill down into the defense budget, making weighted-random choices until it tells me that my entire burden went to buying 8% of a single missile, for example.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5532072636025812077?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5532072636025812077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5532072636025812077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5532072636025812077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5532072636025812077'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/this-is-pretty-neat-site-that-shows-how.html' title='balancethebudget.com'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4202857862499198337</id><published>2010-04-09T19:59:00.000-07:00</published><updated>2010-04-09T20:03:08.002-07:00</updated><title type='text'>Android Scripting Environment: launch a script from adb</title><content type='html'>ASE is pretty slick; makes it very easy to do simple things in Android.  Here's how to launch a script from the command line after using "adb shell" to get a shell prompt:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Launch an activity in the background:&lt;br /&gt;$ am start -a com.google.ase.action.LAUNCH_SCRIPT -n com.google.ase/.activity.AseServiceLauncher -e com.google.ase.extra.SCRIPT_NAME test.py&lt;br /&gt;&lt;br /&gt;# Launch an activity in a new terminal:&lt;br /&gt;$ am start -a com.google.ase.action.LAUNCH_TERMINAL -n com.google.ase/.activity.AseServiceLauncher -e com.google.ase.extra.SCRIPT_NAME test.py&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here's the java file where they name &lt;a href="http://code.google.com/p/android-scripting/source/browse/android/AndroidScriptingEnvironment/src/com/google/ase/Constants.java?spec=svncef760c1e3e6d9948a2ba51bf0910c94fb8b9427&amp;r=cef760c1e3e6d9948a2ba51bf0910c94fb8b9427"&gt;all the intents in ASE&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4202857862499198337?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4202857862499198337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4202857862499198337' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4202857862499198337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4202857862499198337'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/04/android-scripting-environment-launch.html' title='Android Scripting Environment: launch a script from adb'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5566393031675718028</id><published>2010-03-16T18:23:00.000-07:00</published><updated>2010-03-16T18:35:30.938-07:00</updated><title type='text'>calcdeps.py "Missing provider" error</title><content type='html'>Today I was trying to use the Google Closure compiler to build a single .js file out of several source files and their closure library dependencies:&lt;br /&gt;&lt;br /&gt;closure-library-read-only/closure/bin/calcdeps.py -p closure-library-read-only -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar &gt; compiled.js&lt;br /&gt;&lt;br /&gt;I kept getting errors like this:&lt;br /&gt;&lt;br /&gt;Exception: Missing provider for (foo.Foo)&lt;br /&gt;&lt;br /&gt;That sucked, since foo.js with its goog.Provide("foo.Foo") was right in the same directory with bar.js, and I even specified it explicitly on the command line.&lt;br /&gt;&lt;br /&gt;Turns out I needed to specify "-p ." so that it'd look in the current directory for the dependency.  So with a command line of:&lt;br /&gt;&lt;br /&gt;closure-library-read-only/closure/bin/calcdeps.py -p . -p closure-library-read-only -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar &gt; compiled.js&lt;br /&gt;&lt;br /&gt;I got:&lt;br /&gt;&lt;br /&gt;Exception: Duplicate provide (goog.async.DeferredList) in ...&lt;br /&gt;&lt;br /&gt;That seemed even weirder.  Turns out calcdeps doesn't like having the same subdirectory show up twice in -p arguments.  That is, "-p ." and "-p closure-library-read-only" was causing it to find the closure library twice.  Okay, so we take out the second -p:&lt;br /&gt;&lt;br /&gt;closure-library-read-only/closure/bin/calcdeps.py -p . -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar &gt; compiled.js&lt;br /&gt;&lt;br /&gt;Now I get:&lt;br /&gt;&lt;br /&gt;ERROR - namespace "foo.Foo" cannot be provided twice&lt;br /&gt;&lt;br /&gt;Almost there: it doesn't like having foo.js explicitly provided.  This actually worked:&lt;br /&gt;&lt;br /&gt;closure-library-read-only/closure/bin/calcdeps.py -p . -i bar.js -o compiled -c closure-compiler/compiler.jar &gt; compiled.js&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5566393031675718028?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5566393031675718028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5566393031675718028' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5566393031675718028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5566393031675718028'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/03/calcdepspy-missing-provider-error.html' title='calcdeps.py &quot;Missing provider&quot; error'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3279377372767911151</id><published>2010-03-14T15:02:00.000-07:00</published><updated>2010-07-11T23:27:17.087-07:00</updated><title type='text'>Universal Muses</title><content type='html'>The universe halted.  This would have been traumatic for its inhabitants, had they been able to notice.  But their brains had halted along with everything else, so they didn't mind.&lt;br /&gt;&lt;br /&gt;"More elevator music.  I'm telling you, happiness doesn't make for good art," said Cyn.&lt;br /&gt;&lt;br /&gt;"I suppose you're right. I guess I just have a soft spot for them."  Fob sighed, twiddling the values in the configuration file.&lt;br /&gt;&lt;br /&gt;He pressed a button and erased the 10e80 particle simulation.  175 billion galaxies ceased to be simulated.&lt;br /&gt;&lt;br /&gt;Cyn softened.  "Look at it this way:the suffering is what gives their lives meaning.  No suffering means no art, and no art means there's no point wasting computer time on them."  Cyn and Fob shared time on a supercomputer with 10^73 gigabytes of memory, or about 100 times the number of particles in our universe.  It had been respectable when it was built, but was starting to show its age.&lt;br /&gt;&lt;br /&gt;"Yeah, I guess," said Fob, distracted.  "How about this?  I'm going to restore the water planet from the pre-life checkpoint, but turn up the resource saturation and sunlight, so they'll really eat each other alive."&lt;br /&gt;&lt;br /&gt;"If you really think that'll help.  At least turn up the quantum granularity so it doesn't take forever to run."&lt;br /&gt;&lt;br /&gt;Fob laughed. "Okay, okay. The poor physicists.  Maybe they'll start writing requiems."&lt;br /&gt;&lt;br /&gt;Life bloomed and ended.  Then bloomed again, and ended.  On the third try it caught.&lt;br /&gt;&lt;br /&gt;"Giant lizards. Cute."&lt;br /&gt;&lt;br /&gt;Cyn and Fob searched the history books, as soon as there were history books.  "Hey, some of this architecture is pretty good."&lt;br /&gt;&lt;br /&gt;Fob checked another result. "And check out the music.  There's a whole cluster of them right around 1800."&lt;br /&gt;&lt;br /&gt;"Meh, it's okay.  Make this one go deaf and see what happens."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3279377372767911151?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3279377372767911151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3279377372767911151' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3279377372767911151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3279377372767911151'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/03/universal-muses.html' title='Universal Muses'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6714989356434652241</id><published>2010-03-01T20:34:00.000-08:00</published><updated>2010-03-01T20:42:50.558-08:00</updated><title type='text'>XMPP / asmack / android / Google Talk</title><content type='html'>OK, I finally figured out how to send and receive XMPP instant messages from my gmail account using asmack with an Android 2.1 AVD.  For some reason, the event-driven message receive code doesn't work, but this &lt;a href="http://today.java.net/article/2006/10/04/instant-messaging-java-made-easy-smack-api"&gt;polling example code&lt;/a&gt; does.  Here's my latest source:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// DON'T FORGET TO INCLUDE THE INTERNET PERMISSION IN YOUR MANIFEST.XML&lt;br /&gt;&lt;br /&gt;package com.example.HelloFormStuff;&lt;br /&gt;&lt;br /&gt;import android.app.Activity;&lt;br /&gt;import android.os.Bundle;&lt;br /&gt;import android.util.Log;&lt;br /&gt;import android.view.View;&lt;br /&gt;import android.view.View.OnClickListener;&lt;br /&gt;import android.widget.Button;&lt;br /&gt;&lt;br /&gt;import org.jivesoftware.smack.Chat;&lt;br /&gt;import org.jivesoftware.smack.ChatManager;&lt;br /&gt;import org.jivesoftware.smack.MessageListener;&lt;br /&gt;import org.jivesoftware.smack.PacketCollector;&lt;br /&gt;import org.jivesoftware.smack.XMPPConnection;&lt;br /&gt;import org.jivesoftware.smack.XMPPException;&lt;br /&gt;import org.jivesoftware.smack.filter.AndFilter;&lt;br /&gt;import org.jivesoftware.smack.filter.FromContainsFilter;&lt;br /&gt;import org.jivesoftware.smack.filter.PacketFilter;&lt;br /&gt;import org.jivesoftware.smack.filter.PacketTypeFilter;&lt;br /&gt;import org.jivesoftware.smack.packet.Message;&lt;br /&gt;import org.jivesoftware.smack.packet.Packet;&lt;br /&gt;&lt;br /&gt;public class HelloFormStuffActivity extends Activity {&lt;br /&gt;    public int state = 0;&lt;br /&gt;    private static final String TAG = "HelloFormStuffActivity"; &lt;br /&gt;    &lt;br /&gt;    /** Called when the activity is first created. */&lt;br /&gt;    @Override&lt;br /&gt;    public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;        super.onCreate(savedInstanceState);       &lt;br /&gt;        &lt;br /&gt;        new Thread(new Runnable() {&lt;br /&gt;          public void run() {            &lt;br /&gt;            //XMPPConnection xmpp = new XMPPConnection("jabber.iitsp.com");&lt;br /&gt;            XMPPConnection xmpp = new XMPPConnection("gmail.com");&lt;br /&gt;            try {&lt;br /&gt;              xmpp.connect();&lt;br /&gt;&lt;br /&gt;              // for other jabber accounts, truncate after the @&lt;br /&gt;              //xmpp.login("username", "password"); &lt;br /&gt;&lt;br /&gt;              // for gtalk / gmail, include the @&lt;br /&gt;              xmpp.login("your-gmail-account@gmail.com", "your-gmail-password");&lt;br /&gt;&lt;br /&gt;            } catch (XMPPException e) {&lt;br /&gt;              Log.v(TAG, "Failed to connect to " + xmpp.getHost());&lt;br /&gt;              e.printStackTrace();&lt;br /&gt;            }&lt;br /&gt;            ChatManager chatmanager = xmpp.getChatManager();&lt;br /&gt;            Chat newChat = chatmanager.createChat("friend@gmail.com", new MessageListener() {&lt;br /&gt;              // THIS CODE NEVER GETS CALLED FOR SOME REASON&lt;br /&gt;              public void processMessage(Chat chat, Message message) {&lt;br /&gt;                try {&lt;br /&gt;                  Log.v(TAG, "Got:" + message.getBody());&lt;br /&gt;                  chat.sendMessage(message.getBody());&lt;br /&gt;                } catch (XMPPException e) {&lt;br /&gt;                  Log.v(TAG, "Couldn't respond:" + e);&lt;br /&gt;                }&lt;br /&gt;                Log.v(TAG, message.toString());&lt;br /&gt;              }&lt;br /&gt;            });&lt;br /&gt;                   &lt;br /&gt;            // Send something to friend@gmail.com&lt;br /&gt;            try {&lt;br /&gt;              newChat.sendMessage("OMNOMNOM");&lt;br /&gt;            } catch (XMPPException e) {&lt;br /&gt;              Log.v(TAG, "couldn't send:" + e.toString());&lt;br /&gt;            }&lt;br /&gt;           &lt;br /&gt;            // Accept only messages from friend@gmail.com&lt;br /&gt;            PacketFilter filter &lt;br /&gt;                = new AndFilter(new PacketTypeFilter(Message.class), &lt;br /&gt;                                new FromContainsFilter("friend@gmail.com"));&lt;br /&gt;&lt;br /&gt;            // Collect these messages&lt;br /&gt;            PacketCollector collector = xmpp.createPacketCollector(filter);&lt;br /&gt;            &lt;br /&gt;            while(true) {&lt;br /&gt;              Packet packet = collector.nextResult();&lt;br /&gt;                &lt;br /&gt;              if (packet instanceof Message) {&lt;br /&gt;                Message msg = (Message) packet;&lt;br /&gt;                // Process message&lt;br /&gt;                Log.v(TAG, "Got message:" + msg.getBody());&lt;br /&gt;              }&lt;br /&gt;            }&lt;br /&gt;              &lt;br /&gt;          }&lt;br /&gt;          &lt;br /&gt;        }).start();&lt;br /&gt;        &lt;br /&gt;        //setContentView(this);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6714989356434652241?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6714989356434652241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6714989356434652241' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6714989356434652241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6714989356434652241'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/03/xmpp-asmack-android-google-talk.html' title='XMPP / asmack / android / Google Talk'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-5027400451852579497</id><published>2010-02-26T16:53:00.000-08:00</published><updated>2010-03-01T20:43:41.799-08:00</updated><title type='text'>Android XMPP</title><content type='html'>Update: &lt;a href="http://credentiality2.blogspot.com/2010/03/xmpp-asmack-android-google-talk.html"&gt;working code for send/receive over XMPP from gtalk / non-gtalk accounts&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, apparently XMPP support was briefly part of the official android SDK, but they took it out again.&lt;br /&gt;&lt;br /&gt;There's a respected library called "smack", but it doesn't work with android out of the box.&lt;br /&gt;&lt;br /&gt;There's a hack of smack for android called asmack, and that seems to work for me, at least for sending messages.&lt;br /&gt;&lt;br /&gt;I haven't figured out how to make it work with talk.google.com, but I created an account at jabber.iitsp.com and was successful in sending an IM from my android.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.example.HelloFormStuff;&lt;br /&gt;&lt;br /&gt;import android.app.Activity;&lt;br /&gt;import android.media.MediaPlayer;&lt;br /&gt;import android.os.Bundle;&lt;br /&gt;import android.view.View;&lt;br /&gt;import android.view.View.OnClickListener;&lt;br /&gt;import android.widget.Button;&lt;br /&gt;import android.widget.Toast;&lt;br /&gt;&lt;br /&gt;import org.jivesoftware.smack.Chat;&lt;br /&gt;import org.jivesoftware.smack.ChatManager;&lt;br /&gt;import org.jivesoftware.smack.ConnectionConfiguration;&lt;br /&gt;import org.jivesoftware.smack.MessageListener;&lt;br /&gt;import org.jivesoftware.smack.XMPPConnection;&lt;br /&gt;import org.jivesoftware.smack.XMPPException;&lt;br /&gt;import org.jivesoftware.smack.packet.Message;&lt;br /&gt;&lt;br /&gt;public class HelloFormStuffActivity extends Activity {&lt;br /&gt;    public int state = 0;&lt;br /&gt;  &lt;br /&gt;    /** Called when the activity is first created. */&lt;br /&gt;    @Override&lt;br /&gt;    public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;        super.onCreate(savedInstanceState);&lt;br /&gt;        //setContentView(R.layout.main);&lt;br /&gt;        &lt;br /&gt;        XMPPConnection xmpp = new XMPPConnection("jabber.iitsp.com");&lt;br /&gt;        try {&lt;br /&gt;          xmpp.connect();&lt;br /&gt;          xmpp.login("username","password"); // just username, no @ sign&lt;br /&gt;        } catch (XMPPException e) {&lt;br /&gt;          // TODO Auto-generated catch block&lt;br /&gt;          System.out.println("Failed to connect to " + xmpp.getHost());&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;        ChatManager chatmanager = xmpp.getChatManager();&lt;br /&gt;        Chat newChat = chatmanager.createChat("destination@example.com", new MessageListener() {&lt;br /&gt;          public void processMessage(Chat chat, Message message) {&lt;br /&gt;            Toast.makeText(HelloFormStuffActivity.this, message.toString(), Toast.LENGTH_SHORT).show();&lt;br /&gt;          }&lt;br /&gt;        });&lt;br /&gt;        &lt;br /&gt;        try {&lt;br /&gt;          newChat.sendMessage("IMing from my android");&lt;br /&gt;        } catch (XMPPException e) {&lt;br /&gt;          Toast.makeText(HelloFormStuffActivity.this, "ERROR", Toast.LENGTH_SHORT).show();&lt;br /&gt;        }&lt;br /&gt;        ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Don't forget to add the INTERNET permission to the manifest.xml, or you'll get "not connected" exceptions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-5027400451852579497?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/5027400451852579497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=5027400451852579497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5027400451852579497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/5027400451852579497'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/02/android-xmpp.html' title='Android XMPP'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3177952405625685630</id><published>2010-02-17T23:11:00.000-08:00</published><updated>2010-02-17T23:18:26.838-08:00</updated><title type='text'>picasa gdata API and face recognition</title><content type='html'>Tonight I wanted to download a list of photos from picasaweb with a particular person in them, using the "subjectids" field.  I don't see any official way to do this, but here's how I managed it:&lt;br /&gt;&lt;br /&gt;In picasaweb (in my web browser), I loaded up the page showing all the photos my friend was in.  At the bottom, there was a little "RSS" link.  That link looked like this:&lt;br /&gt;&lt;br /&gt;http://picasaweb.google.com/data/feed/base/user/credentiality?alt=rss&amp;kind=photo&amp;subjectids=SOME_BIG_LONG_STRING_OF_CHARACTERS&amp;authkey=A_SHORTER_STRING&amp;hl=en_US&lt;br /&gt;&lt;br /&gt;I loaded that link in my browser, and it gave me the option to keep it as a live bookmark.&lt;br /&gt;&lt;br /&gt;Instead, I trimmed the URL down and plunked it in this little python gdata script:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/python&lt;br /&gt;&lt;br /&gt;import gdata.photos.service&lt;br /&gt;import gdata.media&lt;br /&gt;import gdata.geo&lt;br /&gt;&lt;br /&gt;gd_client = gdata.photos.service.PhotosService()&lt;br /&gt;&lt;br /&gt;gd_client.email = 'MY_EMAIL_ADDRESS'&lt;br /&gt;gd_client.password = 'MY_PASSWORD'&lt;br /&gt;gd_client.source = 'exampleCo-exampleApp-1'&lt;br /&gt;gd_client.ProgrammaticLogin()&lt;br /&gt;&lt;br /&gt;print "logged in"&lt;br /&gt;&lt;br /&gt;photos = gd_client.GetFeed('/data/feed/base/user/credentiality?kind=photo&amp;subjectids=THE_SAME_BIG_LONG_STRING')&lt;br /&gt;&lt;br /&gt;for photo in photos.entry:&lt;br /&gt;  print photo.content.src&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That printed out a list of URLs to the images I wanted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3177952405625685630?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3177952405625685630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3177952405625685630' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3177952405625685630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3177952405625685630'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/02/picasa-gdata-api-and-face-recognition.html' title='picasa gdata API and face recognition'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3242160905498986462</id><published>2010-02-11T15:04:00.001-08:00</published><updated>2010-02-11T15:07:54.694-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ted'/><category scheme='http://www.blogger.com/atom/ns#' term='ted2010'/><title type='text'>TED2010 Jane McGonigal on gamers</title><content type='html'>Jane puts a really positive spin on the time people spend gaming.  Games give us much more positive reinforcement than we get from real life, and people are consequently spending HUGE amounts of time gaming.  500 million gamers worldwide spend at least an hour a day gaming.  Serious gamers spend 10,000 hours gaming by the time they turn 21 -- the same time they spent in K-12 education.  People have spent 6 million man-years playing World of Warcraft.&lt;br /&gt;&lt;br /&gt;I have long felt that we need to find a way to give people in real life the kind of positive stimulus they get in games, and she puts it in a much more optimistic way than I could.  I'm really glad she's working on it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3242160905498986462?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3242160905498986462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3242160905498986462' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3242160905498986462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3242160905498986462'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/02/ted2010-jane-mcgonigal-on-gamers.html' title='TED2010 Jane McGonigal on gamers'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8194390852669625575</id><published>2010-02-10T12:50:00.000-08:00</published><updated>2010-02-10T12:56:48.755-08:00</updated><title type='text'>#TED Wednesday morning session</title><content type='html'>Very welcome scientific results on fighting poverty in Africa: handing out a kilogram of lentils with immunizations drasticaly increases rate of child innoculation.  Deworming, iron supplements vastly more effective at keeping kids in school than hiring more teachers or other more conventional approaches.&lt;br /&gt;&lt;br /&gt;Ukelele flamenco ftw. &lt;br /&gt;&lt;br /&gt;And some worthwhile arguments about why our race is evolved to believe things and find patters where there isn't anything, since it's safer to be think there's a lion in the bush and be wrong than to think there isn't and be wrong.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8194390852669625575?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8194390852669625575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8194390852669625575' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8194390852669625575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8194390852669625575'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/02/ted-wednesday-morning-session.html' title='#TED Wednesday morning session'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3314523578765156308</id><published>2010-02-09T01:09:00.000-08:00</published><updated>2010-02-09T01:10:37.943-08:00</updated><title type='text'>Nady USB-1C doesn't get recognized</title><content type='html'>I couldn't figure out why my Nady USB-1C USB mic didn't get detected in Linux.  It showed up in lsusb as 17a0:0001 as it should, but I got errors in dmesg.  Turns out it was the passive USB extension I was using with it.  Works fine with an active extension.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3314523578765156308?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3314523578765156308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3314523578765156308' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3314523578765156308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3314523578765156308'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/02/nady-usb-1c-doesnt-get-recognized.html' title='Nady USB-1C doesn&apos;t get recognized'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7420551320745726845</id><published>2010-01-26T18:07:00.001-08:00</published><updated>2010-01-26T18:18:59.723-08:00</updated><title type='text'>App Engine: AttributeError: 'module' object has no attribute 'Message'</title><content type='html'>Today I wasted over an hour trying to receive mail in App Engine.  Every time I'd try to use it, I'd get errors like:&lt;br /&gt;&lt;br /&gt;'module' object has no attribute 'Message'&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 509, in __call__&lt;br /&gt;handler.post(*groups)&lt;br /&gt;File "/base/python_lib/versions/1/google/appengine/ext/webapp/mail_handlers.py", line 58, in post&lt;br /&gt;self.receive(mail.InboundEmailMessage(self.request.body))&lt;br /&gt;File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 546, in __init__&lt;br /&gt;mime_message = _parse_mime_message(mime_message)&lt;br /&gt;File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 227, in _parse_mime_message&lt;br /&gt;if isinstance(mime_message, email.Message.Message):&lt;br /&gt;AttributeError: 'module' object has no attribute 'Message'&lt;br /&gt;&lt;br /&gt;Turns out I'd named my file "email.py", which is a builtin module for python.  Rename it and it works fine.&lt;br /&gt;&lt;br /&gt;Don't forget to delete the email.pyc, or your dev_appserver will complain about "ImportError: No module named email.message".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7420551320745726845?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7420551320745726845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7420551320745726845' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7420551320745726845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7420551320745726845'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/01/app-engine-attributeerror-module-object.html' title='App Engine: AttributeError: &apos;module&apos; object has no attribute &apos;Message&apos;'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-8520604933504577568</id><published>2010-01-25T18:59:00.000-08:00</published><updated>2010-01-25T19:01:33.124-08:00</updated><title type='text'>Firefox crashes when using facebook chat</title><content type='html'>Using firefox 3 for Linux, I was surprised to see it keep crashing when I chatted with a friend on facebook.  It only happens when receiving messages with smileys :) and when the Chat... Options... "Play Sound for New Messages" option is enabled.  So turn that off if you experience this bug.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-8520604933504577568?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/8520604933504577568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=8520604933504577568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8520604933504577568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/8520604933504577568'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/01/firefox-crashes-when-using-facebook.html' title='Firefox crashes when using facebook chat'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-1660696636255808464</id><published>2010-01-19T18:57:00.001-08:00</published><updated>2010-01-19T19:06:26.307-08:00</updated><title type='text'>Use vlc to find the title number for mplayer, or, Disney Sucks</title><content type='html'>Some studios (Disney is one of the worst) put stupid copy protection measures on their DVDs that make them difficult to play on anything but a DVD player.  That's a great way to tick off your completely legitimate paying customers.&lt;br /&gt;&lt;br /&gt;One of the common ones is to make something other than the first title the start of the movie, or worse, to put one or more corrupt copies of the start of the movie, then have the actual movie start on title 74 or something.  This makes it hard to play the DVDs on Linux with mplayer.&lt;br /&gt;&lt;br /&gt;To work around this on a Linux machine, use vlc to find the true start of the movie.  File... Open Disc... DVD (menus) and start playing the movie.  (Feel free to simply watch the movie at this point).  Wait until you get to the first scene.  Then in the Playback... Navigation dropdown you can find the title number.  Let's say it's 37.  Then you should be able to play the movie with mplayer dvd://37&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-1660696636255808464?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/1660696636255808464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=1660696636255808464' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1660696636255808464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/1660696636255808464'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/01/use-vlc-to-find-title-number-for.html' title='Use vlc to find the title number for mplayer, or, Disney Sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-7722385190837291845</id><published>2010-01-11T19:33:00.000-08:00</published><updated>2010-01-11T19:36:59.399-08:00</updated><title type='text'>Netflix sucks</title><content type='html'>Netflix is mostly doing the right things: today they sent me a very specific, very short survey about a movie I just watched.  Good, don't waste my time!  But they didn't even give me the option to type free text comments about the quality.  It's actually something I was interested in and willing to give them some details on.&lt;br /&gt;&lt;br /&gt;So I went to the account info page, and got the typical wild goose chase where companies don't want to admit that they won't let you email them.  So now you've wasted my time when I was trying to help you out.  That turned me from a happy, engaged customer into an annoyed one without an outlet.  So it goes on the blog instead, and costs you other customers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-7722385190837291845?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/7722385190837291845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=7722385190837291845' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7722385190837291845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/7722385190837291845'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2010/01/netflix-sucks.html' title='Netflix sucks'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-429945542224347515</id><published>2009-12-11T15:00:00.000-08:00</published><updated>2009-12-11T15:01:19.974-08:00</updated><title type='text'>unable to enumerate usb device</title><content type='html'>Today on an Ubuntu Karmic Koala machine, we plugged in a Canon camera and got a bunch of "unable to enumerate usb device" messages when we looked at dmesg.  Turns out it was a bad cable.  So check that first if you get that message.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-429945542224347515?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/429945542224347515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=429945542224347515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/429945542224347515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/429945542224347515'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/12/unable-to-enumerate-usb-device.html' title='unable to enumerate usb device'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6550041124881574481</id><published>2009-12-09T17:34:00.000-08:00</published><updated>2010-03-18T16:31:56.388-07:00</updated><title type='text'>Disable mouse or touchpad in xorg</title><content type='html'>Update: Apparently figuring out how to disable x input devices like mice, keyboards and touch pads is hard to find on the search engines, so I'm updating the post to make it more findable. (This post was originally called "Ubuntu karmic: 3dconnexion Space Navigator and xorg", but I just helped a friend of mine disable his EEE PC's elantech touch pad, and realized that the solution is general purpose.)&lt;br /&gt;&lt;br /&gt;My friend always uses an external mouse with his laptop, and accidentally brushes the touch pad when he's typing.  So he wanted to find a way to shut off the touch pad.  &lt;br /&gt;&lt;br /&gt;In Ubuntu Karmic Koala (9.10), xorg now autodetects my 3dConnexion Space Navigator and uses its events for mouse X and Y, which is not what I want.&lt;br /&gt;&lt;br /&gt;I just discovered xinput, though, which is extremely cool.  Thanks Philip Langdale and Frederic Lepied for writing it!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@lg1:~# xinput list&lt;br /&gt;...&lt;br /&gt;"3Dconnexion SpaceNavigator"    id=9    [XExtensionPointer]&lt;br /&gt;        Type is MOUSE&lt;br /&gt;        Num_buttons is 5&lt;br /&gt;        Num_axes is 6&lt;br /&gt;        Mode is Relative&lt;br /&gt;        Motion_buffer is 256&lt;br /&gt;        Axis 0 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;        Axis 1 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;        Axis 2 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;        Axis 3 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;        Axis 4 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;        Axis 5 :&lt;br /&gt;                Min_value is -1&lt;br /&gt;                Max_value is -1&lt;br /&gt;                Resolution is 1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;root@lg1:~# xinput list-props "3Dconnexion SpaceNavigator"&lt;br /&gt;Device '3Dconnexion SpaceNavigator':&lt;br /&gt;        Device Enabled (93):    1&lt;br /&gt;        Evdev Reopen Attempts (227):    10&lt;br /&gt;        Evdev Axis Inversion (228):     0, 0&lt;br /&gt;        Evdev Axis Calibration (229):&lt;br /&gt;        Evdev Axes Swap (230):  0&lt;br /&gt;        Evdev Middle Button Emulation (231):    2&lt;br /&gt;        Evdev Middle Button Timeout (232):      50&lt;br /&gt;        Evdev Wheel Emulation (233):    0&lt;br /&gt;        Evdev Wheel Emulation Axes (234):       0, 0, 4, 5&lt;br /&gt;        Evdev Wheel Emulation Inertia (235):    10&lt;br /&gt;        Evdev Wheel Emulation Timeout (236):    200&lt;br /&gt;        Evdev Wheel Emulation Button (237):     4&lt;br /&gt;        Evdev Drag Lock Buttons (238):  0&lt;br /&gt;&lt;br /&gt;root@lg1:~# xinput get-feedbacks "3Dconnexion SpaceNavigator"&lt;br /&gt;1 feedback class&lt;br /&gt;PtrFeedbackClass id=0&lt;br /&gt;        accelNum is 2&lt;br /&gt;        accelDenom is 1&lt;br /&gt;        threshold is 4&lt;br /&gt;&lt;br /&gt;root@lg1:~# xinput set-ptr-feedback "3Dconnexion SpaceNavigator" 4 8 1  # very sensitive X pointer&lt;br /&gt;root@lg1:~# xinput set-ptr-feedback "3Dconnexion SpaceNavigator" 4 1 8  # much less sensitive.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The threshold parameter doesn't seem to do anything.&lt;br /&gt;&lt;br /&gt;Ah, here's the magic to make it stop influencing the pointer:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@lg1:~# xinput set-int-prop "3Dconnexion SpaceNavigator" 93 8 0  # property 93 from list-props&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Also works as:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root@lg1:~# xinput set-int-prop "3Dconnexion SpaceNavigator" "Device Enabled" 8 0&lt;br /&gt;root@lg1:~# xinput set-int-prop "3Dconnexion SpaceNavigator" "Device Enabled" 8 1  # reenable&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Unfortunately, I don't see any way to re-zero if it drifts (often happens when they're cold or hot or brand new), or turn on the LED.  Here's C code to do it, though:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;#include &amp;lt;error.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;linux/input.h&amp;gt;&lt;br /&gt;&lt;br /&gt;main(int argc, char **argv) {&lt;br /&gt;  &lt;br /&gt;  int fd;&lt;br /&gt;  int retval;&lt;br /&gt;  struct input_event ev; /* the event */&lt;br /&gt;&lt;br /&gt;  if (argc != 3) {&lt;br /&gt;    printf("Usage: %s device 1|0\n", argv[0]);&lt;br /&gt;    exit(2);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if ((fd = open(argv[1], O_WRONLY)) &lt; 0) {&lt;br /&gt;      perror("opening the file you specified");&lt;br /&gt;      exit(1);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  ev.type = EV_LED;&lt;br /&gt;  ev.code = LED_MISC;&lt;br /&gt;  ev.value = (argv[2][0] == '1') ? 1:0;&lt;br /&gt;  write(fd, &amp;ev, sizeof(struct input_event));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6550041124881574481?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6550041124881574481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6550041124881574481' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6550041124881574481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6550041124881574481'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/12/ubuntu-karmic-3dconnexion-space.html' title='Disable mouse or touchpad in xorg'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-656205209356402319</id><published>2009-11-24T23:22:00.001-08:00</published><updated>2009-11-24T23:24:31.983-08:00</updated><title type='text'>Dell mini 10 with ubuntu jaunty xorg crash: stolenbase</title><content type='html'>Good grief.  Did a dist-upgrade on the Dell mini 10, and now xorg is broken again.  Something about a stolenbase in Xorg.0.log. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://meandubuntu.wordpress.com/2009/07/31/dell-mini-and-kernel-2-6-28-14/"&gt;Thanks to this blog for the fix:&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;sudo apt-get remove --purge psb-kernel-source&lt;br /&gt;sudo apt-get install psb-kernel-source&lt;br /&gt;&lt;br /&gt;Since when did I become a full time distro installer?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-656205209356402319?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/656205209356402319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=656205209356402319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/656205209356402319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/656205209356402319'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/dell-mini-10-with-ubuntu-jaunty-xorg.html' title='Dell mini 10 with ubuntu jaunty xorg crash: stolenbase'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4897417082287277143</id><published>2009-11-23T13:37:00.000-08:00</published><updated>2009-11-23T13:41:23.143-08:00</updated><title type='text'>Ubuntu Karmic: install -pae kernel breaks nvidia driver</title><content type='html'>Since I have &gt; 3GB of RAM, I installed linux-image-generic-pae so that I could access up to 16GB on my Karmic Koala install.  Note that installing a new kernel doesn't choose it as the default in grub (which is actually now grub2).  So in /etc/default/grub I set GRUB_DEFAULT=saved so that it'd remember my choice, and then rebooted and hit SHIFT during the (very brief) grub blip to pull up the menu and choose the new kernel, which it then remembers.&lt;br /&gt;&lt;br /&gt;Unfortunately, that broke my nvidia driver: when I rebooted into the kernel, the text login screen just flickered as xorg restarted constantly.  This is due to 2 bugs:&lt;br /&gt;&lt;br /&gt;https://bugs.launchpad.net/ubuntu/karmic/+source/jockey/+bug/451305&lt;br /&gt;&lt;br /&gt;https://bugs.launchpad.net/ubuntu/+bug/454220&lt;br /&gt;&lt;br /&gt;Summary: I had to &lt;br /&gt;&lt;br /&gt;apt-get remove --purge linux-headers-2.6.31-15&lt;br /&gt;&lt;br /&gt;And then, when I did an&lt;br /&gt;&lt;br /&gt;apt-get install linux-headers-2.6.31-15-pae&lt;br /&gt;&lt;br /&gt;it automatically rebuilt (successfully) the nvidia.ko.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4897417082287277143?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4897417082287277143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4897417082287277143' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4897417082287277143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4897417082287277143'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/ubuntu-karmic-install-pae-kernel-breaks.html' title='Ubuntu Karmic: install -pae kernel breaks nvidia driver'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-343438435338904715</id><published>2009-11-21T23:14:00.000-08:00</published><updated>2009-11-21T23:29:57.074-08:00</updated><title type='text'>Asus EEE pc 900 frequency scaling</title><content type='html'>&lt;a href="http://credentiality2.blogspot.com/2009/11/asus-eee-pc-900-linux-howto.html"&gt;I just got Ubuntu Jaunty&lt;/a&gt; running on this cursed EEE 900, and noticed it was running hot.  But I just turned on CPU frequency scaling, so now the machine can automatically slow itself down from 900mhz to as low as 112mhz.&lt;br /&gt;&lt;br /&gt;Right click on the menu bar and click "Add to panel", then select "CPU Frequency Scaling Monitor".  When I first did this, it complained "CPU Frequency scaling unsupported".  Turns out the celeron needs a particular kernel module installed for that to work. Here's my source for this fix, &lt;a href="http://translate.google.com/translate?hl=en&amp;sl=it&amp;u=http://www.tuxmind.org/2009/05/01/ubuntu-netbook-remix-904-su-eeepc-900/&amp;ei=0tgIS6u-I43YtgOUzKDBCQ&amp;sa=X&amp;oi=translate&amp;ct=result&amp;resnum=2&amp;ved=0CA8Q7gEwAQ&amp;prev=/search%3Fq%3Deee%2B900%2Bceleron%2Bpowernowd%26hl%3Den%26client%3Dfirefox-a%26rls%3Dcom.ubuntu:en-US:unofficial%26hs%3DDL6"&gt;translated from Italian&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;sudo apt-get install cpufrequtils sysfsutils&lt;br /&gt;sudo modprobe p4_clockmod&lt;br /&gt;&lt;br /&gt;Then add p4_clockmod to your /etc/modules with your favorite text editor or by:&lt;br /&gt;&lt;br /&gt;sudo bash&lt;br /&gt;echo p4_clockmod &gt;&gt;/etc/modules&lt;br /&gt;exit&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-343438435338904715?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/343438435338904715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=343438435338904715' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/343438435338904715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/343438435338904715'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/asus-eee-pc-900-frequency-scaling.html' title='Asus EEE pc 900 frequency scaling'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-218253610880181748</id><published>2009-11-21T22:28:00.000-08:00</published><updated>2009-11-21T23:31:18.953-08:00</updated><title type='text'>Asus EEE pc 900 linux howto</title><content type='html'>(Update: linked to my post on frequency scaling down at the bottom).&lt;br /&gt;&lt;br /&gt;Wow, I can't believe how many hours I've spent trying to make Linux work on this EEE 900. Our 900A seems to be okay, but ubunty karmic is completely broken with the 900, and hardy is seriously deficient.  I tried eeebuntu, moblin, and I don't even remember what other distros.  All failed miserably.  Here's how I got Jaunty to work reliably with the VESA video driver.&lt;br /&gt;&lt;br /&gt;The main problem is the xserver-xorg-video-intel driver, which locks up quickly after (or during) boot.  For some reason, the i915 just seems to cause everybody huge headaches.  And unfortunately, switching to the (slower) vesa xorg driver in many distros (such as Karmic Koala) causes it to lose video sync and be even more unfixable, since then the VTs (alt-F1, etc.) won't work.&lt;br /&gt;&lt;br /&gt;Ubuntu Jaunty is the only thing that even comes close to working for me.  It installs okay, and uses the vesa video driver, but has the standard trouble with the mind-rendingly awful netbook-launcher, which has plagued every netbook install I've ever tried.  netbook-launcher sucks in a big way.  It tries to be fancy by using OpenGL for visual effects, but in doing so either breaks video drivers or just eats up 100% CPU all the time.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://answers.launchpad.net/netbook-remix/+question/66076"&gt;Worse, Jaunty has a bug when turning it off that leaves you without a working window manager.&lt;/a&gt; System... Preferences... Switch Desktop Mode turns it off, and everything looks great, but as soon as you restart, you'll get a blank desktop with no menu bar, task bar, or gnome menus.  Here's how to fix it, summarizing from the above link.  (The above link also has ideas about what to do if you've already switched and are in that broken state).&lt;br /&gt;&lt;br /&gt;To shut off netbook-launcher and get back to the normal gnome menus in Jaunty UNR, first switch to "Classic" mode from System... Preferences... Switch Desktop Mode.  Everything should look great, but it'll break if you logout or restart now.  To make sure the gnome menus load the next time, open System... Preferences... Startup Applications.  Make sure UNR Launcher and Maximus are unchecked.  Now click "Add" and create a "GNOME Panel" entry, running the command "gnome-panel" (no path needed).  Add another called "GNOME Window Manager", running command "gnome-wm".&lt;br /&gt;&lt;br /&gt;That should do it!  You'll be limited to 800x600, instead of the native 1024x600, and of course the VESA video won't be as fast as a working accelerated driver would be.  If that bothers you, feel free to spend a few days downloading and installing distros that'll break the machine entirely.  Then reinstall Jaunty and reapply this fix, and you'll appreciate the suboptimal yet stable performance.  Youtube and hulu work with flashplugin-nonfree, although not so much in HD or fullscreen modes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://credentiality2.blogspot.com/2009/11/asus-eee-pc-900-frequency-scaling.html"&gt;Next up, enabling CPU frequency scaling to extend battery life.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-218253610880181748?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/218253610880181748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=218253610880181748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/218253610880181748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/218253610880181748'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/asus-eee-pc-900-linux-howto.html' title='Asus EEE pc 900 linux howto'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6979523326324329303</id><published>2009-11-11T15:19:00.000-08:00</published><updated>2009-11-11T15:20:22.720-08:00</updated><title type='text'>Carmichael orrery</title><content type='html'>It occurs to me that it ought to be possible to demonstrate pseudoprimality with a purely mechanical device.&lt;br /&gt;&lt;br /&gt;For instance, we could demonstrate 2^560%561 with 560 2:1 (or equivalently, 35 65536:1) gear amplifications followed by a 1:561 reduction, and rotate the input shaft once to see the output gear rest at 1. Of course, 2^560 ~ 3.8E168, so you'd have to turn the crank fairly hard.&lt;br /&gt;&lt;br /&gt;You could also do a single 65536:1:561 train cranked n times for individual 65536n (mod 561) reductions, and repeat 35 iterations for 65536^35%561.&lt;br /&gt;&lt;br /&gt;That would provide a (false) Fermat witness of 2.  Simile for the other integers &lt; 561.  Not very interesting so far, but perhaps there's something more elegant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6979523326324329303?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6979523326324329303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6979523326324329303' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6979523326324329303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6979523326324329303'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/carmichael-orrery.html' title='Carmichael orrery'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4386996714111750077</id><published>2009-11-05T23:54:00.000-08:00</published><updated>2009-11-05T23:57:07.024-08:00</updated><title type='text'>Math and music</title><content type='html'>If you represent the notes in the musical scale as the numbers 0 to 11 (0=A, 1=A#, 2=B, etc.), then the wheel of fifths is merely the multiples of 7 modulo 12.  Likewise, the wheel of fourths is 5 mod 12.  For some reason, the internets appear to be silent on this relationship.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4386996714111750077?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4386996714111750077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4386996714111750077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4386996714111750077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4386996714111750077'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/math-and-music.html' title='Math and music'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4386201584240462938</id><published>2009-11-02T16:57:00.000-08:00</published><updated>2009-11-02T17:00:02.384-08:00</updated><title type='text'>Capturing sound in Linux using a USB headset (Plantronics DA40)</title><content type='html'>I picked up a Plantronics DA40 USB headset today and figured out how to capture .wav files to disk and play them back through the headset.&lt;br /&gt;&lt;br /&gt;There are lots of other options, but I like this one because it's USB and I could use it with any Linux system, whereas if I used the native souncard, I'd probably have to do more per-machine troubleshooting.  dmesg showed that it was detected okay:&lt;br /&gt;&lt;br /&gt;[14563.672694] input: Plantronics DA40 Adapter as /devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.3/input/input6&lt;br /&gt;[14563.728138] input,hidraw3: USB HID v1.00 Device [Plantronics DA40 Adapter] on usb-0000:00:1d.3-2&lt;br /&gt;[14563.909787] usbcore: registered new interface driver snd-usb-audio&lt;br /&gt;&lt;br /&gt;Usually the mic comes muted by default, so I pulled up alsamixer to check.  It came up with my native sound card first.  So I ran "alsamixer -c 1" to try it with the second card, and that was indeed the DA40.  Hitting TAB let met toggle between record and playback settings. &lt;br /&gt;&lt;br /&gt;In the playback tab, there's a Mic option.  You want to mute that ("m"), since that just loops the mic back through the speakers.  On the Capture tab, there's a "Mic" field, and that's the one that actually sets the mic gain.&lt;br /&gt;&lt;br /&gt;To record, I ran:&lt;br /&gt;&lt;br /&gt;arecord -r 44100 -f S16_LE -D hw:1,0 foo.wav&lt;br /&gt;&lt;br /&gt;(Hit control-c to end capture.)  hw:1,0 let me record from card 1, the second sound card.  It refused to record at its default setting of 8000Hz, so the 44100 and S16_LE were necessary.  Then I was able to play back foo.wav with:&lt;br /&gt;&lt;br /&gt;mplayer -ao alsa:device=hw=1.0 foo.wav&lt;br /&gt;&lt;br /&gt;So far so good.  Next, I wanted to know how much deviation I was getting (was the gain turned up enough?) so I downloaded a nifty, very old program called Wavesurfer, available as a statically linked binary:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.speech.kth.se/wavesurfer/"&gt;http://www.speech.kth.se/wavesurfer/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I selected a "waveform" panel and loaded up foo.wav, and could see that I was only getting around +-500 units max (out of +-32767).  In File... Preferences... Sound I/O, I set the Input and Output device to /dev/dsp1 (which I believe is the OSS version of the second sound card).  Now I can record and playback from wavesurfer.  I used alsamixer to tweak the Mic setting (remember to use the Record tab!) until I got +-10000 or so on my recordings.  Anything over +-1000 would probably have been fine.&lt;br /&gt;&lt;br /&gt;(BTW, wavesurfer will also show you nifty spectrograms, from which I learned a lot about the human voice.)&lt;br /&gt;&lt;br /&gt;Here's a trivial script to start arecord recording in the background, and another script to kill it when you've had enough.&lt;br /&gt;&lt;br /&gt;$more start-recording.sh&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;arecord -r 44100 -f S16_LE -D hw:1,0 /tmp/recording-in-progress.wav &amp;&lt;br /&gt;ARECORD_PID="$!"&lt;br /&gt;echo Recording.  Wrote arecord pid of $ARECORD_PID to /tmp/arecord.pid&lt;br /&gt;echo $ARECORD_PID &gt; /tmp/arecord.pid&lt;br /&gt;&lt;br /&gt;$more stop-recording.sh&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;kill "`cat /tmp/arecord.pid`"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4386201584240462938?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4386201584240462938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4386201584240462938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4386201584240462938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4386201584240462938'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/11/capturing-sound-in-linux-using-usb.html' title='Capturing sound in Linux using a USB headset (Plantronics DA40)'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-4281977887314883848</id><published>2009-10-27T16:26:00.000-07:00</published><updated>2009-10-27T16:36:07.652-07:00</updated><title type='text'>Machine Monastery</title><content type='html'>I've been reading &lt;a href="http://www.365tomorrows.com/"&gt;365 Tomorrows&lt;/a&gt;, and I like the idea of flash fiction.  Here's a story that popped into my head while deep cleaning my carpets:&lt;br /&gt;&lt;br /&gt;Cynthia was reluctant when it came time to leave the Machine Monastery.  Nobody had predicted that machines would be Buddhists.  Crazed killers, perhaps.  Indifferent to humanity, perhaps.  Cold calculators, almost certainly.&lt;br /&gt;&lt;br /&gt;She had learned the tactile pleasures of sanding the walnut sides of an imperfect jewelry box she had made herself with hand tools.  The visual pleasure of brushing a finish with a wet edge.&lt;br /&gt;&lt;br /&gt;The empty contentedness of sweeping a floor.  The ragged exhaustion of breaking out old concrete sidewalks with a sledgehammer and hauling them to a skip.  The gleam of a toilet scrubbed clean.&lt;br /&gt;&lt;br /&gt;The machines had done all these things, mostly better than humans could, and had found the same peace from their lessons.  Cynthia would go back to her life in the city, where her finance skills would pay the bills, and where machine and human craftsmen continue to do their jobs with the labor-saving tools that made mass production cheap.  But perhaps in the summer she would take another vacation to the mountains east of town, away from the noise, and rejuvenate with the joys of manual labor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-4281977887314883848?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/4281977887314883848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=4281977887314883848' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4281977887314883848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/4281977887314883848'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/10/machine-monastery.html' title='Machine Monastery'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6453635019763105679</id><published>2009-10-13T11:31:00.000-07:00</published><updated>2009-10-13T11:33:27.295-07:00</updated><title type='text'>Ubuntu 8.04 (Hardy LTS) on HP EliteBook 8530w</title><content type='html'>Trying to boot the laptop with my 8.04 live CD, it hangs with a message "BUG: soft lockup - CPU#0 stuck for 11s".  Hit F6 at the ubuntu boot screen and edit the boot params: remove "splash" and "quiet", and add "acpi=off".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6453635019763105679?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6453635019763105679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6453635019763105679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6453635019763105679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6453635019763105679'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/10/ubuntu-804-hardy-lts-on-hp-elitebook.html' title='Ubuntu 8.04 (Hardy LTS) on HP EliteBook 8530w'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-3055602971599929380</id><published>2009-09-25T22:16:00.000-07:00</published><updated>2009-09-25T22:28:23.052-07:00</updated><title type='text'>Shopbot joinery</title><content type='html'>I tried my first joinery on the shopbot today. It's a concept for a sideboard to foot joint for a bed. I recessed the post 1/8" deeper than the plywood to give it a sense of depth when assembled, but I'm still deciding whether I like the effect.  Maybe with a very gentle roundover on the post edges.&lt;br /&gt;&lt;br /&gt;Here are my &lt;a href="http://sites.google.com/site/credentiality/Home/joinery.zip"&gt;Sketchup, PartWorks and Shopbot partfiles&lt;/a&gt;.  The partfiles are written for a 1/4" bit.&lt;br /&gt;&lt;br /&gt;The raised sections of the post need a little rounding off at the tip to accommodate the 1/4" radius in the mating part; I should probably fix that in the sketchup model before I do any more of those.  Also, in partworks, I relieved the plywood path by 0.030" so it had enough clearance to fit.  I like how the fit came out with that amount of clearance.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh3.ggpht.com/_oXIW_jM0QDA/Sr2hNa9c-SI/AAAAAAAAKEE/GMn9mjmmMI4/s1024/2009-09-25%2022.02.55.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 512px; height: 384px;" src="http://lh3.ggpht.com/_oXIW_jM0QDA/Sr2hNa9c-SI/AAAAAAAAKEE/GMn9mjmmMI4/s1024/2009-09-25%2022.02.55.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh5.ggpht.com/_oXIW_jM0QDA/Sr2hS5HIv-I/AAAAAAAAKEM/oK1IGpp6_nU/s1024/2009-09-25%2022.02.41.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 512px; height: 384px;" src="http://lh5.ggpht.com/_oXIW_jM0QDA/Sr2hS5HIv-I/AAAAAAAAKEM/oK1IGpp6_nU/s1024/2009-09-25%2022.02.41.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-3055602971599929380?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/3055602971599929380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=3055602971599929380' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3055602971599929380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/3055602971599929380'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/09/shopbot-joinery.html' title='Shopbot joinery'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_oXIW_jM0QDA/Sr2hNa9c-SI/AAAAAAAAKEE/GMn9mjmmMI4/s72-c/2009-09-25%2022.02.55.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6486847724120122589.post-6367420850879593564</id><published>2009-09-04T19:34:00.000-07:00</published><updated>2009-09-04T19:46:38.147-07:00</updated><title type='text'>squid reverse proxy (aka website accelerator) on ubuntu hardy</title><content type='html'>We had a bunch of machines all hitting the same URLs on www.example.com, so we put up a squid reverse proxy on ourcache.example.com so that http://www.example.com/foo/bar would get served and cached by http://ourcache.example.com/foo/bar&lt;br /&gt;&lt;br /&gt;sudo apt-get install squid squid-cgi # squid-cgi enables the cache manager web interface&lt;br /&gt;&lt;br /&gt;Edit /etc/squid/squid.conf.  It's very well documented, and we only had to modify a few lines from the default ubuntu hardy config:&lt;br /&gt;&lt;br /&gt;Allow other local machines to use our cache:&lt;br /&gt;&lt;br /&gt;acl our_networks src 10.42.42.0/24&lt;br /&gt;http_access allow our_networks&lt;br /&gt;&lt;br /&gt;instead of the default of:&lt;br /&gt;&lt;br /&gt;http_access allow localhost&lt;br /&gt;&lt;br /&gt;Have the cache listen on port 80 and forward all requests to www.example.com:&lt;br /&gt;&lt;br /&gt;http_port 80 defaultsite=www.example.com&lt;br /&gt;cache_peer www.example.com parent 80 0 no-query originserver &lt;br /&gt;&lt;br /&gt;In our case, we wanted to cache pages that included "GET parameters" in the URL, such as http://www.example.com/search?query=foo (which is something you should only do in special cases):&lt;br /&gt;&lt;br /&gt;# enable logging of the full URL, so you can see what's going on (though it's a potential privacy risk to your users)&lt;br /&gt;strip_query_terms off&lt;br /&gt;&lt;br /&gt;Comment out the lines that exclude cgi-bin and GET parameter URLs from being cached:&lt;br /&gt;&lt;br /&gt;#acl QUERY urlpath_regex cgi-bin \?&lt;br /&gt;#cache deny QUERY&lt;br /&gt;&lt;br /&gt;Then we went to: http://localhost/cgi-bin/cachemgr.cgi to see how well our cache was working (blank login and password by default).&lt;br /&gt;&lt;br /&gt;After doing an "/etc/init.d/squid restart", we found that we could hit http://ourcache.example.com/foo/bar.html and get http://www.example.com/foo/bar.html, as expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6486847724120122589-6367420850879593564?l=credentiality2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://credentiality2.blogspot.com/feeds/6367420850879593564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6486847724120122589&amp;postID=6367420850879593564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6367420850879593564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6486847724120122589/posts/default/6367420850879593564'/><link rel='alternate' type='text/html' href='http://credentiality2.blogspot.com/2009/09/squid-reverse-proxy-aka-website.html' title='squid reverse proxy (aka website accelerator) on ubuntu hardy'/><author><name>Lunkwill</name><uri>http://www.blogger.com/profile/08543336341601290962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
