<?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:blogger='http://schemas.google.com/blogger/2008' 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-21956912</id><updated>2024-09-06T08:08:36.275+10:00</updated><category term="python"/><category term="zope"/><category term="wallpaper"/><category term="windows"/><category term="Arduino"/><category term="Crash"/><category term="PIL"/><category term="code"/><category term="multiple monitors"/><category term="trac"/><category term="1984"/><category term="3d scanning"/><category term="Aldous Huxley"/><category term="Bethesda"/><category term="Bug"/><category term="Dick Cheney"/><category term="DisplayLink"/><category term="Dumb"/><category term="Elite"/><category term="ExternalFile"/><category term="Fallout 3"/><category term="False Advertising"/><category term="Fixed"/><category term="GP2X"/><category term="George Orwell"/><category term="Google"/><category term="Iraq"/><category term="Javascript"/><category term="LCD"/><category term="Microsoft"/><category term="R"/><category term="Stupid"/><category term="UTC"/><category term="Windows 7"/><category term="Wiz"/><category term="ZPT"/><category term="algebrra"/><category term="australia"/><category term="beautiful soup"/><category term="big data"/><category term="bus pirate"/><category term="change"/><category term="cuecat"/><category term="darpa"/><category term="dystopia"/><category term="extjs form submit enter"/><category term="layout"/><category term="lego"/><category term="maths"/><category term="mechanise"/><category term="mechanize"/><category term="milk"/><category term="mod"/><category term="national geographic"/><category term="numpy"/><category term="photo of the day"/><category term="porting"/><category term="proofs"/><category term="putty"/><category term="python collatz iterative"/><category term="scipy"/><category term="sendfile"/><category term="serial"/><category term="source code"/><category term="steampunk"/><category term="subversion"/><category term="terminal"/><category term="terrorists"/><category term="timezones"/><category term="ugly"/><category term="webcam"/><title type='text'>TJ&#39;s Place</title><subtitle type='html'>A collection of unordered thoughts somehow expressed in English.&#xa;&lt;br&gt;&lt;br&gt;&#xa;gabbpuy</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-21956912.post-1075155746632162887</id><published>2013-02-06T19:04:00.002+11:00</published><updated>2013-02-06T19:06:55.190+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="big data"/><category scheme="http://www.blogger.com/atom/ns#" term="darpa"/><category scheme="http://www.blogger.com/atom/ns#" term="numpy"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="R"/><category scheme="http://www.blogger.com/atom/ns#" term="scipy"/><title type='text'>Darpa funds python development for big data</title><content type='html'>&lt;a href=&quot;http://www.itworld.com/big-data/340570/python-gets-big-data-boost-darpa&quot; target=&quot;_blank&quot;&gt;DARPA funds python development for big data&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/1075155746632162887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/1075155746632162887?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1075155746632162887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1075155746632162887'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2013/02/darpa-funds-python-development-for-big.html' title='Darpa funds python development for big data'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6410724846474409933</id><published>2013-01-11T21:46:00.001+11:00</published><updated>2013-01-11T21:51:09.597+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="beautiful soup"/><category scheme="http://www.blogger.com/atom/ns#" term="mechanise"/><category scheme="http://www.blogger.com/atom/ns#" term="mechanize"/><category scheme="http://www.blogger.com/atom/ns#" term="national geographic"/><category scheme="http://www.blogger.com/atom/ns#" term="photo of the day"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>National Geographic Photo of the Day using Python</title><content type='html'>&lt;div&gt;
A small snippet of code to get the National Geographic Photo of the Day.&lt;/div&gt;
&lt;div&gt;
It uses &lt;a href=&quot;http://wwwsearch.sourceforge.net/mechanize/&quot;&gt;mechanize&lt;/a&gt; and &lt;a href=&quot;http://www.crummy.com/software/BeautifulSoup/&quot;&gt;beautiful soup 4&lt;/a&gt;&amp;nbsp;to help with the scraping.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
It also has a function to allow walking backwards to pickup previous photos.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; os
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; mechanize
&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; bs4 &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; BeautifulSoup

MASTER_URL = &lt;span class=&quot;string&quot;&gt;&quot;http://photography.nationalgeographic.com/photography/photo-of-the-day/?source=NavPhoPOD&quot;&lt;/span&gt;

&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;POD_Browser&lt;/span&gt;(mechanize.Browser):
    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
    A browser for pod, with our configuration settings.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, *args, **kwargs&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        mechanize.Browser.__init__(self, *args, **kwargs)
        self.set_handle_robots(False)
        self.set_debug_redirects(False)
        self.set_debug_http(False)
        self.set_handle_equiv(True)
        self.set_handle_gzip(True)
        self.set_handle_redirect(True)
        self.open(MASTER_URL)

&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;Session&lt;/span&gt;(object):
    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
    A Session.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.browser = POD_Browser()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;downloadPhotoOfTheDay&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
        Search the page looking for a Wallpaper link. Not all pages have
        Wallpaper link, and we (politely) don&#39;t download the image in that
        case.
        &quot;&quot;&quot;&lt;/span&gt;
        page = self.browser.response().read()
        soup = BeautifulSoup(page)

        tags = soup.find_all(&lt;span class=&quot;string&quot;&gt;&#39;a&#39;&lt;/span&gt;, text = re.compile (&lt;span class=&quot;string&quot;&gt;&#39;Download Wallpaper&#39;&lt;/span&gt;))
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; t &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; tags:
            filename = t[&lt;span class=&quot;string&quot;&gt;&#39;href&#39;&lt;/span&gt;].split(&lt;span class=&quot;string&quot;&gt;&#39;/&#39;&lt;/span&gt;)[-&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;]
            &lt;span class=&quot;comment&quot;&gt;# If we&#39;ve already downloaded the file, don&#39;t download it again.&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; os.path.exists(filename):
                filename, _headers = self.browser.retrieve(t[&lt;span class=&quot;string&quot;&gt;&#39;href&#39;&lt;/span&gt;], filename )
                &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; filename
                sys.stdout.flush()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;goPrevious&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
        Find the previous link and go back a day
        &quot;&quot;&quot;&lt;/span&gt;
        link = self.browser.find_link(text_regex = re.compile(&lt;span class=&quot;string&quot;&gt;&#39;Previous&#39;&lt;/span&gt;))
        self.browser.follow_link(link)
        
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;downloadPriorPhotos&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, start = &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;, num = &lt;span class=&quot;int&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
        Download some prior photos.
        You can start 7 days back and get 14 days of photos with
        start = 7, num = 14

        :param start: How many days to go back before starting
        :param num: How many days to look at.
        
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(start):
            self.goPrevious()

        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(num):
            self.downloadPhotoOfTheDay()
            self.goPrevious()

&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; __name__ == &lt;span class=&quot;string&quot;&gt;&#39;__main__&#39;&lt;/span&gt;:
    s = Session()
    s.downloadPhotoOfTheDay()
    &lt;span class=&quot;comment&quot;&gt;# If you want to get the last week&#39;s worth uncomment this instead.&lt;/span&gt;
    &lt;span class=&quot;comment&quot;&gt;#s.downloadPriorPhotos(num = 7)&lt;/span&gt;

&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6410724846474409933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6410724846474409933?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6410724846474409933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6410724846474409933'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2013/01/national-geographic-photo-of-day-using.html' title='National Geographic Photo of the Day using Python'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-2660814737319588223</id><published>2012-04-11T16:32:00.000+10:00</published><updated>2012-04-11T16:32:32.421+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="multiple monitors"/><category scheme="http://www.blogger.com/atom/ns#" term="PIL"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="wallpaper"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>pyWallpaper Updated</title><content type='html'>I have committed a much more comprehensive version of pyWallpaper to the subversion repository.&lt;br /&gt;
&lt;br /&gt;
It is multi-threaded to speed up the wallpaper construction &amp;nbsp;(most of the threads end up being I/O bound, so this is a win in terms of elapsed time).&lt;br /&gt;
&lt;br /&gt;
Also supports walking subfolders by prefixing paths with a +&lt;br /&gt;
&lt;br /&gt;
The code is still available at &lt;a href=&quot;http://code.google.com/p/pywallpaper/&quot;&gt;http://code.google.com/p/pywallpaper/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/2660814737319588223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/2660814737319588223?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/2660814737319588223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/2660814737319588223'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2012/04/pywallpaper-updated.html' title='pyWallpaper Updated'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-3846646071830130729</id><published>2011-03-12T17:52:00.003+11:00</published><updated>2011-03-12T18:06:33.344+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="algebrra"/><category scheme="http://www.blogger.com/atom/ns#" term="maths"/><category scheme="http://www.blogger.com/atom/ns#" term="proofs"/><title type='text'>When .999 is actually 1</title><content type='html'>You remember at school (or maybe you&#39;re just learning now) when doing fractions, that dividing something by 9 would give you an &quot;infinite&quot; decimal that repeated? For example 4/9 = .444444 on to infinity.&lt;br /&gt;
&lt;br /&gt;
This means that if you ever see a number that is that way you know it&#39;s something divided by 9, so .77777...&amp;nbsp; is 7/9.&lt;br /&gt;
&lt;br /&gt;
But wait, what about .999999... ? That would be 9/9 which is 1, that can&#39;t be right!&lt;br /&gt;
&lt;br /&gt;
In fact it is, and without any tricks, here&#39;s the algebra to show it.&lt;br /&gt;
&lt;br /&gt;
I will use .999999r to indicate .9 repeater, normally it would be a .9 with a . above the 9, but, finding a font that everyone has that has that proved too tedious :-) I have also made all the steps explicit instead of doing multiple operations at once, just so algebra beginners can see there is no subterfuge going on.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Let a = .999999r&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Multiply both sides by 10 gives&lt;br /&gt;
&lt;i&gt;10a = 9.999999r&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Subtract 9 from both sides gives&lt;br /&gt;
&lt;i&gt;10a - 9 = .999999r&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Replace .999999r with a from above&lt;br /&gt;
&lt;i&gt;10a - 9 = a&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Subtract a from both sides&lt;br /&gt;
&lt;i&gt;10a - 9 - a = 0&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Add 9 to both sides&lt;br /&gt;
&lt;i&gt;10a - a = 9&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Simplify&lt;br /&gt;
&lt;i&gt;9a = 9&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Divide both sides by 9&lt;br /&gt;
&lt;i&gt;a = 1&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Therefore .999999r = 1&lt;/i&gt;&lt;br /&gt;
&lt;i&gt; &lt;/i&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/3846646071830130729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/3846646071830130729?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3846646071830130729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3846646071830130729'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2011/03/when-999-is-actually-1.html' title='When .999 is actually 1'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-8800554562699746044</id><published>2010-11-18T01:02:00.001+11:00</published><updated>2010-11-18T01:02:53.816+11:00</updated><title type='text'>Process Explorer gets Tree CPU Usage feature</title><content type='html'>The feature I&#39;ve missed most from Process Explorer has been implemented in version 14.&lt;br /&gt;
The ability to see the combined CPU usage for a parent and all its children, this is especially useful for things like Chrome, but, now I can roll up a lot of trees of stuff and still see what&#39;s making my CPU fans spin up all of a sudden.&lt;br /&gt;
&lt;br /&gt;
Thanks guys d8)&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://blogs.technet.com/b/sysinternals/archive/2010/11/16/update-process-explorer-v14.aspx&quot;&gt;http://blogs.technet.com/b/sysinternals/archive/2010/11/16/update-process-explorer-v14.aspx&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/8800554562699746044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/8800554562699746044?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8800554562699746044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8800554562699746044'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/11/process-explorer-gets-tree-cpu-usage.html' title='Process Explorer gets Tree CPU Usage feature'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-3693971958785541057</id><published>2010-10-08T05:56:00.000+11:00</published><updated>2010-10-08T05:56:33.289+11:00</updated><title type='text'>5 Fridays, 5 Saturdays, 5 Sundays, 823 years, wrong..</title><content type='html'>The calendar repeats every 11 years, so the maximum this can be is 11 years...&lt;br /&gt;
so October in 2021 will be the same as October in 2010 (handy if you want to reuse those calendars), go ahead look on your computer or phone right now.&lt;br /&gt;
&lt;br /&gt;
However, we have a few months that have 31 days, and we only need one of them to begin on a Friday.&lt;br /&gt;
In 2013, March starts on a Friday (and 2024, etc)...&lt;br /&gt;
&lt;br /&gt;
In 2014, August starts on a Friday (and 2025, etc)... &lt;br /&gt;
&lt;br /&gt;
There are other months in other years that have 3 days that occur 5 times too, so, it&#39;s not special.&lt;br /&gt;
&lt;br /&gt;
Next time someone tells you something about some weird calendar event, think about the 11 year cycle, and go back/forward 11 years and see if it&#39;s true.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/3693971958785541057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/3693971958785541057?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3693971958785541057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3693971958785541057'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/10/5-fridays-5-saturdays-5-sundays-823.html' title='5 Fridays, 5 Saturdays, 5 Sundays, 823 years, wrong..'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-8604224506198095071</id><published>2010-10-05T23:34:00.002+11:00</published><updated>2010-10-05T23:34:14.794+11:00</updated><title type='text'>When...</title><content type='html'>When you &quot;talk&quot; like a LOL Cats caption, I wonder if your parents were too closely related to each other...</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/8604224506198095071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/8604224506198095071?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8604224506198095071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8604224506198095071'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/10/when.html' title='When...'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6785656702159667961</id><published>2010-09-09T23:40:00.000+10:00</published><updated>2010-09-09T23:40:11.215+10:00</updated><title type='text'>Random code repo</title><content type='html'>I&#39;ve created a google project (akm-code) into which I can dump random code projects.&lt;br /&gt;
Most of the code in there is finished, but, might be suffering from bit-rot (patches welcome d8)&lt;br /&gt;
&lt;br /&gt;
You can browse the code here; &lt;a href=&quot;http://code.google.com/p/akm-code/source/browse/&quot;&gt;http://code.google.com/p/akm-code/source/browse/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6785656702159667961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6785656702159667961?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6785656702159667961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6785656702159667961'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/09/random-code-repo.html' title='Random code repo'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-5094954159029905256</id><published>2010-08-18T18:24:00.000+10:00</published><updated>2010-08-18T18:24:35.644+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="bus pirate"/><category scheme="http://www.blogger.com/atom/ns#" term="putty"/><category scheme="http://www.blogger.com/atom/ns#" term="serial"/><category scheme="http://www.blogger.com/atom/ns#" term="terminal"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Serial terminals</title><content type='html'>Most people forget, that putty and its relations are usable as serial terminals under windows. Putty has built in terminal emulation and you can choose speed and COM port, AND save the profile.&lt;br /&gt;
&lt;br /&gt;
This is useful for things like Bus Pirate or Arduino use since you can just pull up your profile from the putty interface.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/5094954159029905256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/5094954159029905256?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/5094954159029905256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/5094954159029905256'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/08/serial-terminals.html' title='Serial terminals'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6229815673775767595</id><published>2010-07-26T08:04:00.001+10:00</published><updated>2010-07-26T08:04:40.731+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="source code"/><category scheme="http://www.blogger.com/atom/ns#" term="subversion"/><category scheme="http://www.blogger.com/atom/ns#" term="wallpaper"/><title type='text'>Google Code Repo for windows wallpaper code</title><content type='html'>I&#39;ve setup a google code repository for the pywallpaper code.&lt;br /&gt;
You can download it from there , and get any updates as I make them, or contribute patches.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://code.google.com/p/pywallpaper/&quot;&gt;pywallpaper project&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6229815673775767595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6229815673775767595?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6229815673775767595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6229815673775767595'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/07/google-code-repo-for-windows-wallpaper.html' title='Google Code Repo for windows wallpaper code'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6246858920684169939</id><published>2010-07-20T21:30:00.001+10:00</published><updated>2010-07-20T22:31:03.314+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="change"/><category scheme="http://www.blogger.com/atom/ns#" term="layout"/><category scheme="http://www.blogger.com/atom/ns#" term="multiple monitors"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="wallpaper"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Set windows wallpaper from python for multiple monitors</title><content type='html'>This code will allow you to set a different image per monitor for any combination of monitors. Monitors don&#39;t have to be the same size, or setup to be square on for it to work. You can have your third monitor straddling the other two, and the wallpaper will be built to accommodate it.&lt;br /&gt;
&lt;br /&gt;
You can now specify per-monitor directory lists if you want.&lt;br /&gt;
&lt;br /&gt;
There are blending and resizing options available too, see the comments.&lt;br /&gt;
&lt;br /&gt;
I&#39;ve added a setup.py to make a .exe so that the dos window doesn&#39;t pop-up. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#!C:/python25/python.exe&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Code to rotate or set wallpaper under windows&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# Copyright (C) Andrew K. Milton 2007 - 2010&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# Released under a 2-clause BSD License&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# See: http://www.opensource.org/licenses/bsd-license.php&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# Multi monitor detection based on http://code.activestate.com/recipes/460509/&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# This will handle any configuration of an arbitrary number of monitors,&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# including offset boundaries.&lt;/span&gt;


&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; os
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; time
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; random

&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; optparse &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; OptionParser
&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; ConfigParser &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; SafeConfigParser
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; ctypes

&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; ctypes &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; windll

&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; win32con &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; *
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; win32gui
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; win32api
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; win32con

&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; PIL &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Image, ImageDraw, ImageChops, ImageOps, ImageFilter


&lt;span class=&quot;comment&quot;&gt;# I recommend you create a pywallpaper.conf file that looks something&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# like this to store the directories in rather than specifying -d&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# multiple times on the command line.&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# NB you can specify paths per monitor. Any monitor number without its&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# own paths will get the global paths. Monitors start at 0 which is always&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# the primary monitor.&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# Some options don&#39;t play nicely together.&lt;/span&gt;

&lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
[global]
Blending = True
BlendRatio = 0.40
Crop = False
Fill = True
Gradient = False
PreRotate = True

[directories]
paths = C:\Documents and Settings\akm\My Documents\My Pictures\gb
        C:\Documents and Settings\akm\My Documents\My Pictures\Ralph

[monitor_0]
paths = C:\Documents and Settings\akm\My Documents\My Pictures\Wide Screen
[monitor_1]
paths = C:\Documents and Settings\akm\My Documents\My Pictures\Landscapes
&quot;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;comment&quot;&gt;# If you don&#39;t like the little dos window that pops you can use the&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# following as setup.py to create a .exe that won&#39;t display the window,&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# makes it a little easier to use as a startup item too.&lt;/span&gt;

&lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;
from distutils.core import setup
import py2exe

options = {
    &quot;bundle_files&quot;: 2,
    &quot;ascii&quot;: 1, # to make a smaller executable, don&#39;t include the encodings
    &quot;compressed&quot;: 1, # compress the library archive
    &quot;excludes&quot;: [&#39;w9xpopen.exe&#39;,]
    }

setup( windows = [&#39;pyWallpaper.py&#39;],
       options = {&#39;py2exe&#39;: options},
       )
&quot;&quot;&quot;&lt;/span&gt;


&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;RECT&lt;/span&gt;(ctypes.Structure):
    _fields_ = [
        (&lt;span class=&quot;string&quot;&gt;&#39;left&#39;&lt;/span&gt;, ctypes.c_long),
        (&lt;span class=&quot;string&quot;&gt;&#39;top&#39;&lt;/span&gt;, ctypes.c_long),
        (&lt;span class=&quot;string&quot;&gt;&#39;right&#39;&lt;/span&gt;, ctypes.c_long),
        (&lt;span class=&quot;string&quot;&gt;&#39;bottom&#39;&lt;/span&gt;, ctypes.c_long)
        ]
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;dump&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        f = (self.left, self.top, self.right, self.bottom)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; [int(i) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; f]

&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;MONITORINFO&lt;/span&gt;(ctypes.Structure):
    _fields_ = [
        (&lt;span class=&quot;string&quot;&gt;&#39;cbSize&#39;&lt;/span&gt;, ctypes.c_ulong),
        (&lt;span class=&quot;string&quot;&gt;&#39;rcMonitor&#39;&lt;/span&gt;, RECT),
        (&lt;span class=&quot;string&quot;&gt;&#39;rcWork&#39;&lt;/span&gt;, RECT),
        (&lt;span class=&quot;string&quot;&gt;&#39;dwFlags&#39;&lt;/span&gt;, ctypes.c_ulong)
        ]

&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;Monitor&lt;/span&gt;(object):
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, monitor, physical, working, flags&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.monitor = monitor
        self.physical = physical
        self.working = working
        self.size = self.getSize(*self.physical)
        self.width, self.height = self.size
        self.left, self.top, self.right, self.bottom = self.physical
        self._left, self._top, self._right, self._bottom = self.physical
        
        self.isPrimary = (flags != &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;)

        self.cTop = self.top
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.cTop &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;:
            self.cTop = &lt;span class=&quot;int&quot;&gt;20000&lt;/span&gt;  + self.cTop
        self.cLeft = self.left
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.cLeft &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;:
            self.cLeft  = &lt;span class=&quot;int&quot;&gt;20000&lt;/span&gt;  + self.cLeft

        self.wLeft = int(self.left)
        self.wTop = int(self.top)

        self.needsSplit = ( (self.left &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; self.right &amp;gt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;or&lt;/span&gt;
                            (self.top &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; self.bottom &amp;gt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;) )
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.needsSplit:
            self.needVSplit = self.top &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; self.bottom &amp;gt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;
            self.needHSplit = self.left &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; self.right &amp;gt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;addWallpaper&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, bgImage, wallpaper&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; self.needsSplit:
            bgImage.paste(wallpaper, (self.wLeft, self.wTop))
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.needVSplit:
            height = -self.top
            bottom = wallpaper.crop((&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, self.width, height))
            bottom.load()
            top = wallpaper.crop((&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, height, self.width, self.height))
            top.load()
            bgImage.paste(top, (self.wLeft, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;))
            bgImage.paste(bottom, (self.wLeft, bgImage.size[&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;] - height))
        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
            width = -self.left
            right = wallpaper.crop((&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, width, self.height))
            right.load()
            left = wallpaper.crop((width, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, self.width, self.height))
            left.load()
            bgImage.paste(left, (&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, self.wTop))
            bgImage.paste(right, (bgImage.size[&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;] - width, self.wTop))

            
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getSize&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, left, top, right, bottom&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; [abs(right - left), abs(bottom - top)]

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__repr__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;extent: &#39;&lt;/span&gt; + str(self.physical) + &lt;span class=&quot;string&quot;&gt;&#39; :: size: &#39;&lt;/span&gt; + str(self.size) + &lt;span class=&quot;string&quot;&gt;&#39; :: primary: &#39;&lt;/span&gt; + str(self.isPrimary) + &lt;span class=&quot;string&quot;&gt;&#39; :: needsSplit &#39;&lt;/span&gt; + str(self.needsSplit) + &lt;span class=&quot;string&quot;&gt;&#39;:: &#39;&lt;/span&gt; + hex(self.monitor)
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__cmp__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, other&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; cmp(self.cTop, other.cTop):
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; cmp(self.cLeft, other.cLeft)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; cmp(self.top, other.top)

&lt;span class=&quot;keyword&quot;&gt;class &lt;/span&gt;&lt;span class=&quot;hilight&quot;&gt;Desktop&lt;/span&gt;(object):
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.setMonitorExtents()

        &lt;span class=&quot;comment&quot;&gt;# Merge with the desktop background colour&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# Handy to tint your background to your theme.&lt;/span&gt;
        self.Blending = &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# Amount of picture to bg colour ratio&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# This works well for black...&lt;/span&gt;
        self.BlendRatio = &lt;span class=&quot;float&quot;&gt;0.40&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# Render a gradient under the image..&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# I&#39;m not overly happy with the results.&lt;/span&gt;
        self.Gradient = &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# Crop black/white borders before zooming&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# This doesn&#39;t work well with Fill..&lt;/span&gt;
        self.Crop = &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# Don&#39;t just maxpect the image... blow it up so there&#39;s no bg colour&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# showing so this will crop parts.&lt;/span&gt;
        self.Fill = &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# If the aspect ratio is &quot;wrong&quot; for the monitor, rotate it for a&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# better fit first. So portraits rotate for landscape monitors.&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# With per-monitor dirs you can sort your pictures based on aspect&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# ratio if you want.&lt;/span&gt;
        self.PreRotate = &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;
        
        self.createEmptyWallpaper()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;createEmptyWallpaper&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        c = (&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;)

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Blending:
            &lt;span class=&quot;comment&quot;&gt;# Alpha blend the image with the current desktop colour&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# Or black if something goes wrong with getting the desktop colour&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:
                dc = windll.user32.GetSysColor(&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;)
                c = ((dc &amp;amp; 0xFF  ),
                     (dc &amp;amp; 0xFF00) &amp;gt;&amp;gt; &lt;span class=&quot;int&quot;&gt;8&lt;/span&gt;,
                     (dc &amp;amp; 0xFF0000) &amp;gt;&amp;gt; &lt;span class=&quot;int&quot;&gt;16&lt;/span&gt;)
            &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt;:
                &lt;span class=&quot;keyword&quot;&gt;pass&lt;/span&gt;

        self.bgColour = c

        bgImage = Image.new(&lt;span class=&quot;string&quot;&gt;&#39;RGB&#39;&lt;/span&gt;, self.wSize, c)
            
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Gradient:
            r, g, b = c
            width, height = bgImage.size
            fh = float(height)

            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (r + g + b) / &lt;span class=&quot;int&quot;&gt;3&lt;/span&gt; &amp;lt; &lt;span class=&quot;int&quot;&gt;64&lt;/span&gt;:
                r1, g1, b1 = (&lt;span class=&quot;int&quot;&gt;128&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;128&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;128&lt;/span&gt;)
            &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
                r1, g1, b1 = c
                r, g, b = (&lt;span class=&quot;int&quot;&gt;64&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;64&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;64&lt;/span&gt;)

            rd = r1 - r
            gd = g1 - g
            bd = b1 - b

            rs = float(rd) / fh
            gs = float(gd) / fh
            bs = float(bd) / fh

            draw = ImageDraw.Draw(bgImage)
            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; h &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, height):
                draw.line((&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, h, width, h),
                          fill = (int(r1), int(g1), int(b1)))
                r1 -= rs
                b1 -= bs
                g1 -= gs
                
        self.bgImage = bgImage

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;findMonitors&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        retval = []
        CBFUNC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(RECT), ctypes.c_double)
        &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;hMonitor, hdcMonitor, lprcMonitor, dwData&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
            r = lprcMonitor.contents
            data = [hMonitor]
            data.append(r.dump())
            retval.append(data)
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;
        cbfunc = CBFUNC(cb)
        temp = windll.user32.EnumDisplayMonitors(&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, cbfunc, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; retval

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;calcWallSize&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Also sets the relative offsets for building the wallpaper...&lt;/span&gt;
        
        ms = self.monitors

        primaryMonitor = [m &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m.isPrimary][&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;]

        leftMonitors = [m &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m.left &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;]
        rightMonitors = [m &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m.left &amp;gt;= primaryMonitor.right]
        topMonitors = [m &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m.top &amp;lt; &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;]
        bottomMonitors = [m &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m.top &amp;gt;= primaryMonitor.bottom]

        leftMonitors.sort()
        rightMonitors.sort()
        topMonitors.sort()
        bottomMonitors.sort()

        hMonitors = [primaryMonitor,] + rightMonitors + leftMonitors
        vMonitors = [primaryMonitor,] + bottomMonitors + topMonitors

        width = max([m.right &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms])
        height = max([m.bottom &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms])

        extraWidth = -min([m.left &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms])
        extraHeight = -min([m.top &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; ms])

        width += extraWidth
        height += extraHeight

        hOff = width
        redo = []
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; leftMonitors:
            m.wLeft = width + m.left
            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; bottomMonitors:
                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;
            m.right = width

        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; topMonitors:
            m.wTop = height + m.top
            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; m &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; rightMonitors:
                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;

            m.bottom = height

        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (width, height)    

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getMonitors&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        retval = []
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; hMonitor, extents &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; self.findMonitors():
            &lt;span class=&quot;comment&quot;&gt;# data = [hMonitor]&lt;/span&gt;
            mi = MONITORINFO()
            mi.cbSize = ctypes.sizeof(MONITORINFO)
            mi.rcMonitor = RECT()
            mi.rcWork = RECT()            
            res = windll.user32.GetMonitorInfoA(hMonitor, ctypes.byref(mi))
            data = Monitor(hMonitor, mi.rcMonitor.dump(), mi.rcWork.dump(), mi.dwFlags)
            retval.append(data)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; retval
        
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setMonitorExtents&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.monitors = self.getMonitors()
        self.wSize = self.calcWallSize()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getDefaultDirs&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; [&lt;span class=&quot;string&quot;&gt;r&#39;C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures&#39;&lt;/span&gt;,]

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallPaperFromBmp&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, pathToBmp&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;&quot;&quot;&quot; Given a path to a bmp, set it as the wallpaper &quot;&quot;&quot;&lt;/span&gt;

        &lt;span class=&quot;comment&quot;&gt;# Set it and make sure windows remembers the wallpaper we set.&lt;/span&gt;
        result = windll.user32.SystemParametersInfoA(
            SPI_SETDESKWALLPAPER, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;,
            pathToBmp,
            SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE)
        
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; result:
            &lt;span class=&quot;keyword&quot;&gt;raise&lt;/span&gt; Exception(&lt;span class=&quot;string&quot;&gt;&quot;Unable to set wallpaper.&quot;&lt;/span&gt;)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;autoCrop&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, im, bgcolor = (&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;):
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; im.mode != &lt;span class=&quot;string&quot;&gt;&quot;RGB&quot;&lt;/span&gt;:
            im = im.convert(&lt;span class=&quot;string&quot;&gt;&quot;RGB&quot;&lt;/span&gt;)

        im2 = ImageOps.autocontrast(im, &lt;span class=&quot;int&quot;&gt;5&lt;/span&gt;)
        bg = Image.new(&lt;span class=&quot;string&quot;&gt;&quot;RGB&quot;&lt;/span&gt;, im.size, bgcolor)
        diff = ImageChops.difference(im2, bg)
        bbox = diff.getbbox()
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; bbox:
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; im.crop(bbox)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; im &lt;span class=&quot;comment&quot;&gt;# no contents&lt;/span&gt;

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;maxAspectWallPaper_fill&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, image, width, height&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Blow up the image making sure that the smallest image aspect&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# fills the monitor.&lt;/span&gt;
        
        rsFilter = Image.BICUBIC
        scale = &lt;span class=&quot;float&quot;&gt;2.0&lt;/span&gt;

        imWidth, imHeight = image.size


        hScale = float(height) / float(imHeight)
        wScale = float(width) / float(imWidth)

        scale = max(hScale, wScale)
            
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; scale &amp;lt; &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;:
            rsFilter = Image.ANTIALIAS

        newSize = (int(imWidth * scale), int(imHeight * scale))
        
        newImage = image.resize(newSize, rsFilter)

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; scale &amp;gt; &lt;span class=&quot;int&quot;&gt;2&lt;/span&gt;:
            newImage = newImage.filter(ImageFilter.BLUR)

        imWidth, imHeight = newSize

        x = int((imWidth - width) / 2.0)
        y = int((imHeight - height) / 2.0)
        bbox = (x, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, width + x, height + y)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; newImage.crop(bbox)
    
    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;maxAspectWallPaper&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, image, width, height&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Blow the image up as much as possible without exceeding the monitor&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# bounds.&lt;/span&gt;
        rsFilter = Image.BICUBIC
        scale = &lt;span class=&quot;float&quot;&gt;2.0&lt;/span&gt;

        imWidth, imHeight = image.size

        hScale = float(height) / float(imHeight)
        wScale = float(width) / float(imWidth)

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Fill:
            scale = max(hScale, wScale)
        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
            scale = min(hScale, wScale)
            
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; scale &amp;lt; &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;:
            rsFilter = Image.ANTIALIAS

        newSize = (int(imWidth * scale), int(imHeight * scale))
        newImage = image.resize(newSize, rsFilter)
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Fill:
            imWidth, imHeight = newSize
            x = int((imWidth - width) / 2.0)
            y = int((imHeight - height) / 2.0)
            bbox = (x, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, width + x, height + y)
            newImage = newImage.crop(bbox)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; newImage

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;preRotateImage&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self,image&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Rotate 90 degrees.&lt;/span&gt;
        im = image.rotate(-&lt;span class=&quot;int&quot;&gt;90&lt;/span&gt;, resample = True, expand = True)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; im

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;createWallPaperFromFile&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, pathToImage, monitor&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Given a path to an image, convert it to bmp format and set it as&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# the wallpaper&lt;/span&gt;

        bmpImage = Image.open(pathToImage)

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.PreRotate:
            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; bmpImage.size[&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;] &amp;lt; bmpImage.size[&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;]:
                bmpImage = self.preRotateImage(bmpImage)
        
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Crop:
            bmpImage = self.autoCrop(bmpImage, (&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;))
            bmpImage = self.autoCrop(bmpImage, (&lt;span class=&quot;int&quot;&gt;255&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;255&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;255&lt;/span&gt;))
            
        bmpImage = self.maxAspectWallPaper(bmpImage, *monitor.size)

        bmpSize = bmpImage.size
        xOffset = int((monitor.size[&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;] - bmpImage.size[&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;]) / &lt;span class=&quot;int&quot;&gt;2&lt;/span&gt;)
        yOffset = int((monitor.size[&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;] - bmpImage.size[&lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;]) / &lt;span class=&quot;int&quot;&gt;2&lt;/span&gt;)

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; bmpImage.size != monitor.size:
            img1 = Image.new(&lt;span class=&quot;string&quot;&gt;&quot;RGB&quot;&lt;/span&gt;, monitor.size, (&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;))
        img1.paste(bmpImage, (xOffset, yOffset))

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.Blending:
            img2 = Image.new(&lt;span class=&quot;string&quot;&gt;&quot;RGB&quot;&lt;/span&gt;, monitor.size, self.bgColour)
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Image.blend(img2, img1, self.BlendRatio)
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; img1

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallpaperStyleSingle&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# 0x80000001 == HKEY_CURRENT_USER&lt;/span&gt;
        k = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER,&lt;span class=&quot;string&quot;&gt;&quot;Control Panel\\Desktop&quot;&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;,win32con.KEY_SET_VALUE)
        win32api.RegSetValueEx(k, &lt;span class=&quot;string&quot;&gt;&quot;WallpaperStyle&quot;&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, win32con.REG_SZ, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;)
        win32api.RegSetValueEx(k, &lt;span class=&quot;string&quot;&gt;&quot;TileWallpaper&quot;&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, win32con.REG_SZ, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallpaperStyleMulti&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# To set a multi-monitor wallpaper, we need to tile it...&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# 0x80000001 == HKEY_CURRENT_USER&lt;/span&gt;
        k = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER,&lt;span class=&quot;string&quot;&gt;&quot;Control Panel\\Desktop&quot;&lt;/span&gt;,&lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;,win32con.KEY_SET_VALUE)
        win32api.RegSetValueEx(k, &lt;span class=&quot;string&quot;&gt;&quot;WallpaperStyle&quot;&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, win32con.REG_SZ, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;)
        win32api.RegSetValueEx(k, &lt;span class=&quot;string&quot;&gt;&quot;TileWallpaper&quot;&lt;/span&gt;, &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, win32con.REG_SZ, &lt;span class=&quot;string&quot;&gt;&quot;1&quot;&lt;/span&gt;)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallpaperStyle&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; len(self.monitors) &amp;gt; &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;:
            self.setWallpaperStyleMulti()
        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
            self.setWallpaperStyleSingle()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallpaper&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.setWallpaperStyle()

        &lt;span class=&quot;comment&quot;&gt;# Save the new wallpaper in our current directory.&lt;/span&gt;
        newPath = os.getcwd()
        newPath = os.path.join(newPath, &lt;span class=&quot;string&quot;&gt;&#39;pywallpaper.bmp&#39;&lt;/span&gt;)
        self.bgImage.save(newPath, &lt;span class=&quot;string&quot;&gt;&quot;BMP&quot;&lt;/span&gt;)
        self.setWallPaperFromBmp(newPath)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallpaperFromFile&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, pathToImage&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; monitor &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; self.monitors:
            img = self.createWallPaperFromFile(filename, monitor)
            monitor.addWallpaper(self.bgImage, img)

        self.setWallpaper()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallPaperFromFileList&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, pathToDir, monitor&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;&quot;&quot;&quot; Given a directory choose an image from it and set it as a wallpaper &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# Image directories often contain Thumbs.db or other non-image&lt;/span&gt;
        &lt;span class=&quot;comment&quot;&gt;# files or directories, try a few times to set a wallpaper, and then just give up.&lt;/span&gt;

        tries = &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;
        done = &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;
        filenames = []
        files = os.listdir(pathToDir)

        &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:
            &lt;span class=&quot;comment&quot;&gt;# Priorwalls.txt is used so that we don&#39;t repeat an image&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# until every other image in that directory has been seen&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# The file is rewritten when necessary.&lt;/span&gt;
            prevList = open(&lt;span class=&quot;string&quot;&gt;&#39;priorWalls.txt&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;rb&#39;&lt;/span&gt;)
            filenames = [l.strip() &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; l &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; prevList.readlines()]
            prevList.close()
        &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt;:
            &lt;span class=&quot;keyword&quot;&gt;pass&lt;/span&gt;

        files = [os.path.join(pathToDir, f) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; files &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; f.endswith(&lt;span class=&quot;string&quot;&gt;&#39;.db&#39;&lt;/span&gt;)]
        availChoices = [f &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; files &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; filenames &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; f.endswith(&lt;span class=&quot;string&quot;&gt;&#39;.db&#39;&lt;/span&gt;)]

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; availChoices:
            &lt;span class=&quot;comment&quot;&gt;# This entire directory has been &quot;done&quot; remove them&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# from the previously seen wallpapers and rewrite&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# the cache file without any of these entries.&lt;/span&gt;
            filenames = [f &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; filenames &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; files]
            availChoices = files
            p = open(&lt;span class=&quot;string&quot;&gt;&#39;priorWalls.txt&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;wb&#39;&lt;/span&gt;)
            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; f &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; filenames:
                p.write(&lt;span class=&quot;string&quot;&gt;&quot;&lt;span class=&quot;specialChar&quot;&gt;%s&lt;/span&gt;\n&quot;&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;%&lt;/span&gt;(f))
            p.close()

        files = availChoices

        &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (not done) &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; tries &amp;lt; &lt;span class=&quot;int&quot;&gt;3&lt;/span&gt;:
            &lt;span class=&quot;comment&quot;&gt;# Thumbs.db and other stuff can live in the same Folder&lt;/span&gt;
            &lt;span class=&quot;comment&quot;&gt;# So try three times to set a wallpaper before giving up.&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:
                image = random.choice(files)
                filename = image
                img = self.createWallPaperFromFile(filename, monitor)
                monitor.addWallpaper(self.bgImage, img)
                prevList = open(&lt;span class=&quot;string&quot;&gt;&#39;priorWalls.txt&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;ab&#39;&lt;/span&gt;)
                prevList.write(&lt;span class=&quot;string&quot;&gt;&quot;&lt;span class=&quot;specialChar&quot;&gt;%s&lt;/span&gt;\n&quot;&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;%&lt;/span&gt;(filename))
                done = &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt;:
                &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; traceback; traceback.print_exc()
                &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &amp;gt;&amp;gt; sys.stderr, filename, &lt;span class=&quot;string&quot;&gt;&quot;failed&quot;&lt;/span&gt;
                tries += &lt;span class=&quot;int&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; done

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getMonitorDirs&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, monIndex&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        section = &lt;span class=&quot;string&quot;&gt;&#39;monitor_&lt;span class=&quot;specialChar&quot;&gt;%d&lt;/span&gt;&#39;&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;%&lt;/span&gt;(monIndex)
        &lt;span class=&quot;comment&quot;&gt;# Check for [monitor_0]&lt;/span&gt;
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.config.has_section(section):
            &lt;span class=&quot;comment&quot;&gt;# check for its own paths section&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.config.has_option(section, &lt;span class=&quot;string&quot;&gt;&#39;paths&#39;&lt;/span&gt;):
                dirs = self.config.get(section, &lt;span class=&quot;string&quot;&gt;&#39;paths&#39;&lt;/span&gt;).split(&lt;span class=&quot;string&quot;&gt;&#39;\n&#39;&lt;/span&gt;)
        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
            dirs = self.dirs

        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dirs

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallPaperFromDirList&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;&quot;&quot;&quot; Given a list of directories choose a directory &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; monNum, monitor &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; enumerate(self.monitors):
            imageDir = random.choice(self.getMonitorDirs(monNum))
            status = self.setWallPaperFromFileList(imageDir, monitor)

        self.setWallpaper()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getImageDirectories&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        &lt;span class=&quot;comment&quot;&gt;# Set global image directories.&lt;/span&gt;
        dirs = []
        &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:
            dirs = self.config.get(&lt;span class=&quot;string&quot;&gt;&#39;directories&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;paths&#39;&lt;/span&gt;).split(&lt;span class=&quot;string&quot;&gt;&#39;\n&#39;&lt;/span&gt;)
        &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt;:
            &lt;span class=&quot;keyword&quot;&gt;pass&lt;/span&gt;

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; dirs:
            dirs = self.getDefaultDirs()
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dirs

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;setWallPaperFromConfigDirs&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        self.setWallPaperFromDirList()

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getConfigFileOptions&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, options&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        configFile = &lt;span class=&quot;string&quot;&gt;&#39;pywallpaper.conf&#39;&lt;/span&gt;

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; options.configFile:
            configFile = options.configFile

        dirs = options.directories

        self.config = SafeConfigParser()
        self.config.readfp(open(configFile))

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.config.has_section(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;):
            self.Blending = self.config.getboolean(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Blending&#39;&lt;/span&gt;)
            self.BlendRatio = self.config.getfloat(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;BlendRatio&#39;&lt;/span&gt;)
            self.Crop = self.config.getboolean(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Crop&#39;&lt;/span&gt;)
            self.Fill = self.config.getboolean(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Fill&#39;&lt;/span&gt;)
            self.Gradient = self.config.getboolean(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Gradient&#39;&lt;/span&gt;)
            self.PreRotate = self.config.getboolean(&lt;span class=&quot;string&quot;&gt;&#39;global&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;PreRotate&#39;&lt;/span&gt;)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;getCommandLineOptions&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        parser = OptionParser()
        parser.add_option(&lt;span class=&quot;string&quot;&gt;&quot;-t&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;--time&quot;&lt;/span&gt;, dest=&lt;span class=&quot;string&quot;&gt;&quot;change_time&quot;&lt;/span&gt;,
                          help = &lt;span class=&quot;string&quot;&gt;&quot;Change wallpaper time in minutes (0 = change once and exit [default])&quot;&lt;/span&gt;,
                          default = &lt;span class=&quot;int&quot;&gt;0&lt;/span&gt;, type = &lt;span class=&quot;string&quot;&gt;&quot;int&quot;&lt;/span&gt;)
        parser.add_option(&lt;span class=&quot;string&quot;&gt;&quot;-i&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;--image&quot;&lt;/span&gt;, dest=&lt;span class=&quot;string&quot;&gt;&quot;singleImage&quot;&lt;/span&gt;, default = None,
                          help = &lt;span class=&quot;string&quot;&gt;&quot;Set wallpaper to this image and exit (overrides -d)&quot;&lt;/span&gt;)

        parser.add_option(&lt;span class=&quot;string&quot;&gt;&quot;-d&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;--directory&quot;&lt;/span&gt;, dest=&lt;span class=&quot;string&quot;&gt;&quot;directories&quot;&lt;/span&gt;, default = [], 
                          action=&lt;span class=&quot;string&quot;&gt;&quot;append&quot;&lt;/span&gt;, type=&lt;span class=&quot;string&quot;&gt;&quot;string&quot;&lt;/span&gt;,
                          help = &lt;span class=&quot;string&quot;&gt;&quot;Add an image directory&quot;&lt;/span&gt;)

        parser.add_option(&lt;span class=&quot;string&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;--config&quot;&lt;/span&gt;, dest=&lt;span class=&quot;string&quot;&gt;&quot;configFile&quot;&lt;/span&gt;, default = None,
                          help = &lt;span class=&quot;string&quot;&gt;&quot;path to alternate config file (default &amp;lt;working dir&amp;gt;/pywallpaper.conf)&quot;&lt;/span&gt;)

        parser.add_option(&lt;span class=&quot;string&quot;&gt;&quot;-w&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;--workingdir&quot;&lt;/span&gt;, dest=&lt;span class=&quot;string&quot;&gt;&quot;cwd&quot;&lt;/span&gt;, default=&lt;span class=&quot;string&quot;&gt;&quot;.&quot;&lt;/span&gt;,
                          help = &lt;span class=&quot;string&quot;&gt;&quot;Working Directory (default .)&quot;&lt;/span&gt;)

        (options, args) = parser.parse_args()
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (options, args)

    &lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;go&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:
        options, args = self.getCommandLineOptions()
        self.getConfigFileOptions(options)

        self.dirs = self.getImageDirectories()
        
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; options.cwd &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; options.cwd != &lt;span class=&quot;string&quot;&gt;&#39;.&#39;&lt;/span&gt;:
            os.cwd(cwd)
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; options.singleImage:
            self.setWallPaper(options.singleImage)
            
        &lt;span class=&quot;keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; options.change_time:
            self.setWallPaperFromConfigDirs()
        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:
            sleepTime = options.change_time * &lt;span class=&quot;float&quot;&gt;60.0&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; True:
                self.setWallPaperFromDirList()
                time.sleep(sleepTime)

&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; __name__ == &lt;span class=&quot;string&quot;&gt;&#39;__main__&#39;&lt;/span&gt;:
    d = Desktop()
    d.go()
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6246858920684169939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6246858920684169939?isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6246858920684169939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6246858920684169939'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/07/set-windows-wallpaper-from-python-for.html' title='Set windows wallpaper from python for multiple monitors'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-4530939008269910700</id><published>2010-07-18T04:32:00.001+10:00</published><updated>2010-07-18T04:43:03.194+10:00</updated><title type='text'>Belkin support</title><content type='html'>Every problem&amp;nbsp; I submit to Belkin about their wireless routers or WAPs results in the following response. Every single problem is fixed by &quot;reboot the machine.&quot;&lt;br /&gt;
&lt;br /&gt;
None of the problem reports submitted had anything to do with ADSL connections.&lt;br /&gt;
&lt;br /&gt;
I don&#39;t think I&#39;ll ever be buying another Belkin wireless product.&lt;br /&gt;
&lt;hr /&gt;&lt;pre style=&quot;font-size:x-small; font-family:Vera Bitstream Mono,Consolas,Courier New,Courier&quot; &gt;Let us assist you with this issue.                                                                                                  
                                                                                                                                    
In this case, we would suggest you to reset the router to factory settings and re-configure it once and check.                      
                                                                                                                                    
Please follow the steps given below:                                                                                                
- Connect the computer to the &quot;LAN&quot; port on the router and connect the modem to the Internet/&quot;WAN&quot; port, using Ethernet cables.     
- Take a paper clip, insert the paper clip in the reset hole of the router and hold it for 15 seconds.                              
- The power light will flash and then come back &quot;ON&quot; solid, indicating that the router is being restored to factory defaults.       
- The corresponding lights on the front of the router should be lit up.                                                             
- Log on to the router web interface by typing in http://192.168.2.1, in the address bar of your browser.                           
- By default, the password is blank.                                                                                                
- Click on &quot;Connection Type&quot; in the left hand column under &quot;Internet WAN&quot; heading.                                                  
                                                                                                                                    
If the connection type is Dynamic (cable):                                                                                          
                                                                                                                                    
- Choose &quot;Dynamic&quot; and then click on &quot;Next&quot;.                                                                                        
- Type in your  Host Name , if your Internet Service Provider has provided it. Else, leave it blank.                                
- Click on &quot;Change WAN MAC Address&quot;.                                                                                                
- Click on the button &quot;Clone&quot;.                                                                                                      
- Click on &quot;Apply Changes&quot;.                                                                                                         
                                                                                                                                    
If the connection type is PPPOE (DSL):                                                                                              
                                                                                                                                    
- Choose &quot;PPPOE&quot; and click on &quot;Next&quot;.                                                                                               
- Enter the user name and password given by your Internet Service Provider.                                                         
- Save the settings.                                                                                                                
- Click on the &quot;Home&quot; link at the top of the screen.                                                                                
                                                                                                                                    
If the connection is Static:                                                                                                        
                                                                                                                                    
- Choose &quot;Static&quot; and click on &quot;Next&quot;.                                                                                              
- Enter the &quot;IP Address&quot;, &quot;Subnet Mask&quot; and &quot;ISP Gateway Address&quot;. Click on &quot;Apply Changes&quot;.                                        
- It would ask for the &quot;Primary DNS&quot; and &quot;Secondary DNS&quot; information. Enter the required details and click on &quot;Apply Changes&quot;.      
                                                                                                                                    
Note: All the required information would be provided by your ISP.                                                                   
                                                                                                                                    
Internet Status should show &quot;Connected&quot; on the top right hand corner of the web page. 
                                              
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/4530939008269910700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/4530939008269910700?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/4530939008269910700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/4530939008269910700'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/07/belkin-support.html' title='Belkin support'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-5039866315558315602</id><published>2010-04-14T23:48:00.000+10:00</published><updated>2010-04-14T23:48:22.845+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="Elite"/><category scheme="http://www.blogger.com/atom/ns#" term="GP2X"/><category scheme="http://www.blogger.com/atom/ns#" term="porting"/><category scheme="http://www.blogger.com/atom/ns#" term="Wiz"/><title type='text'>GPH Wiz and Elite</title><content type='html'>I recently dusted off my misappropriated copy of the newkind source I snarfed while it was available (10 years ago, thank you Mr. Pinder), and ported it to use SDL and then to run on the Wiz (the button mappings are currently a little awkward, but, usable).&lt;br /&gt;
&lt;br /&gt;
I fixed up some long standing bugs in the code (suns are rendered, it doesn&#39;t crash randomly due to -ve array indexes), so it gives me something to do when I&#39;m forced to wait (for anything, a compile to finish, for someone to finish shopping d8)&lt;br /&gt;
&lt;br /&gt;
It&#39;s running very nicely, it&#39;s very playable, I&#39;ve replaced the scanner with the one from the Archimedes version (I also added the bumper sticker, I need to acquire some decent dice images to add the fluffy dice though). The code let you load one via file, but, that&#39;s not quite flexible enough to deal with really changing the scanners. The Archimedes one is about 30px shorter than the original one (a lot when you have 320x240 screen size!), but looks sweet.&lt;br /&gt;
&lt;br /&gt;
I&#39;ve coverted from PCX-fonts to true-type fonts and made some of the decals transparent. I&#39;ve removed all the (not-really working) code that tried to deal with different screen resolutions, and have streamlined it to deal with 320x240 (for now). I&#39;m not sold on the &quot;big&quot; font I&#39;m using right now.&lt;br /&gt;
&lt;br /&gt;
I&#39;m now in the process of restructuring the code to make it a little easier to work on, the original code was controlled with globals and it&#39;s kind of ugly to try to map js buttons or mouse buttons to mode-specific key presses.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqVapXiNrD3-z6sd0KzUq2U9J3A6mEH-aaxVE32idUhK3ydPXJ84EnpnSgj6vYtbBoiHot1xIxLQPRQb18s8_CKHTcmok_4KSPkbbVdCAhE1oTgmzairlEcghDHX6nX2aniEV7Eg/s1600/EliteSS.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqVapXiNrD3-z6sd0KzUq2U9J3A6mEH-aaxVE32idUhK3ydPXJ84EnpnSgj6vYtbBoiHot1xIxLQPRQb18s8_CKHTcmok_4KSPkbbVdCAhE1oTgmzairlEcghDHX6nX2aniEV7Eg/s320/EliteSS.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
My ToDo List is (in no particular order):&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Find some .ogg or .mp3 music to replace the 2 MIDIs, the wiz doesn&#39;t seem to have timidity or anything that SDL can use to play the midis. &lt;/li&gt;
&lt;li&gt;Restructure Code to allow nicer event handling.&lt;/li&gt;
&lt;li&gt;Add an Icon Bar to allow &quot;Screen Changing&quot; with the stylus instead of buttons.&lt;/li&gt;
&lt;li&gt;Add the extra Archimedes ships.&lt;/li&gt;
&lt;li&gt;Add convoy, formation, and independent battle logic.&lt;/li&gt;
&lt;li&gt;Add &quot;trimble&quot; mission.&lt;/li&gt;
&lt;li&gt;Add fluffy dice (as an option perhaps only at a certain ranking). &lt;/li&gt;
&lt;li&gt;Add IFS equipment.&lt;/li&gt;
&lt;li&gt;Convert to OpenGL instead of original 3D.&lt;/li&gt;
&lt;li&gt;Re-add the screen resolution code (in a better fashion) so I can transfer my saved games back/forth and play at a nice resolution when I want to.&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/5039866315558315602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/5039866315558315602?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/5039866315558315602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/5039866315558315602'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/04/gph-wiz-and-elite.html' title='GPH Wiz and Elite'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqVapXiNrD3-z6sd0KzUq2U9J3A6mEH-aaxVE32idUhK3ydPXJ84EnpnSgj6vYtbBoiHot1xIxLQPRQb18s8_CKHTcmok_4KSPkbbVdCAhE1oTgmzairlEcghDHX6nX2aniEV7Eg/s72-c/EliteSS.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-883051144334511210</id><published>2010-04-04T20:39:00.001+10:00</published><updated>2010-04-04T20:40:32.515+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bug"/><category scheme="http://www.blogger.com/atom/ns#" term="Crash"/><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft"/><category scheme="http://www.blogger.com/atom/ns#" term="Stupid"/><category scheme="http://www.blogger.com/atom/ns#" term="UTC"/><category scheme="http://www.blogger.com/atom/ns#" term="Windows 7"/><title type='text'>Windows 7 and UTC: Caveat Emptor</title><content type='html'>IF you are running your BIOS Clock at UTC, &lt;br /&gt;
AND you are running Windows 7 in your local timezone&lt;br /&gt;
AND your local timezone is WEST of UTC, &lt;br /&gt;
AND ( Daylight Savings (Ends OR Finishes) &lt;br /&gt;
OR the year changes )&lt;br /&gt;
THEN your machine will lock up&lt;br /&gt;
AND will not boot&lt;br /&gt;
AND system restore will not work&lt;br /&gt;
AND recovery console will not work&lt;br /&gt;
UNTIL midnight UTC is reached (because internally some value goes negative (which is very largely positive for unsigned values)).&lt;br /&gt;
&lt;br /&gt;
It locks so hard, even trying to boot to safe mode, that the caps lock light won&#39;t even come on.&lt;br /&gt;
&lt;br /&gt;
If you can boot up in a timezone EAST of UTC it comes up OK.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/883051144334511210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/883051144334511210?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/883051144334511210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/883051144334511210'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/04/windows-7-and-utc-caveat-emptor.html' title='Windows 7 and UTC: Caveat Emptor'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-1622204061202008900</id><published>2010-03-06T16:15:00.001+11:00</published><updated>2010-03-06T16:15:37.621+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bethesda"/><category scheme="http://www.blogger.com/atom/ns#" term="Crash"/><category scheme="http://www.blogger.com/atom/ns#" term="DisplayLink"/><category scheme="http://www.blogger.com/atom/ns#" term="Fallout 3"/><category scheme="http://www.blogger.com/atom/ns#" term="Fixed"/><title type='text'>Fallout 3 -- Crash Fixed</title><content type='html'>I&#39;ve been swearing at Bethesda Softworks for some time since my Fallout 3 stopped working for no apparent reason, when I upgraded from Vista x64 to Windows 7 x64.&lt;br /&gt;
&lt;br /&gt;
It failed once before and it turned out to be an nVidia video driver update, and a new update fixed it. However it&#39;s been over 6 months now and multiple nVidia updates have failed to fix it.&lt;br /&gt;
&lt;br /&gt;
I spent some time this weekend debugging it, and discovered it&#39;s some kind of issue with Fallout 3 and DisplayLink drivers. I had tried unplugging my Mimo 7&quot; USB auxillary monitor before, and Fallout 3 had still crashed. It turns out, that it was still crashing inside Fallout 3 when it returned from the DisplayLink drivers. I assume there&#39;s some monitor iteration or some other call going on, and it&#39;s not happy when something comes back with bounds smaller than the main screen.&lt;br /&gt;
&lt;br /&gt;
Anyhow, if you have issues with Fallout 3 and you have &quot;other&quot; video/monitor drivers, try uninstalling them.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/1622204061202008900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/1622204061202008900?isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1622204061202008900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1622204061202008900'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/03/fallout-3-crash-fixed.html' title='Fallout 3 -- Crash Fixed'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-1761325303142220907</id><published>2010-03-06T02:59:00.000+11:00</published><updated>2010-03-06T02:59:07.665+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python collatz iterative"/><title type='text'>Iterative Collatz in Python (with resume)</title><content type='html'>I&#39;m assumming there will be a lot of people looking to play with Collatz soon.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s a non-recursing version that will resume when you restart it.&lt;br /&gt;
Given all numbers to 2^58 have already been checked you might be there a while...&lt;br /&gt;
&lt;br /&gt;
It&#39;s trivial to get it to dump a CSV with the steps for graphing, but, this one doesn&#39;t do that (but gives you the steps so that you can).&lt;br /&gt;
&lt;br /&gt;
If you don&#39;t know what this is for, it doesn&#39;t matter.. (but you can google it...)&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;font-family: andale mono, courier new; font-size: 10px&quot;&gt;import os
def collatz(n):
 steps = []
 stAppend = steps.append
 while n &gt; 1:
  stAppend(n)
  
  while not (n &amp; 0x1):
   n &gt;&gt;= 1
   stAppend(n)

  if n == 1:
   break
  n = n * 3 + 1
 return steps

if __name__ == &#39;__main__&#39;:
 n = 2
 if os.access(&#39;collatz.prg&#39;, os.F_OK|os.R_OK|os.W_OK):
  n = int(open(&#39;collatz.prg&#39;, &#39;rb&#39;).read())

 while True:
  steps = collatz(n)
  open(&#39;collatz.prg&#39;, &#39;wb&#39;).write(str(n))
  print n, len(steps)
  n += 1

&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/1761325303142220907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/1761325303142220907?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1761325303142220907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1761325303142220907'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/03/iterative-collatz-in-python-with-resume.html' title='Iterative Collatz in Python (with resume)'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-1101952001610380785</id><published>2010-02-26T23:26:00.001+11:00</published><updated>2010-02-26T23:28:02.460+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="extjs form submit enter"/><title type='text'>Adding a &quot;submit on enter&quot; in ExtJS formpanels.</title><content type='html'>I had to retrospectively setup &quot;submit on enter&quot; to some existing ExtJS forms.&lt;br /&gt;
Googling only turned up some fairly unappetizing solutions.&lt;br /&gt;
Here&#39;s a way using defaults. Just change the getCmp or parametize it if you want, I&#39;ve left it as a constant for illustration purposes.&lt;br /&gt;
Add this to your FormPanel constructor and all your fields will get &quot;submit-on-enter&quot;.&lt;br /&gt;
If you only want 1 field to have it then just add everything inside the defaults to that 1 field.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;font-size:10px; font-family:Andale Mono,Courier New;&quot;&gt;defaults:{
  enableKeyEvents:true,
  listeners:{
    specialKey: function(field, el)
    {
      if(el.getKey() == Ext.EventObject.ENTER)
      {
        Ext.getCmp(&#39;address-search-button&#39;).fireEvent(&#39;click&#39;);
      }
    }
  }
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/1101952001610380785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/1101952001610380785?isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1101952001610380785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1101952001610380785'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/02/adding-submit-on-enter-in-extjs.html' title='Adding a &quot;submit on enter&quot; in ExtJS formpanels.'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6838123200978191842</id><published>2010-02-20T05:26:00.004+11:00</published><updated>2010-02-26T23:20:01.437+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cuecat"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="ugly"/><title type='text'>Decode Encrypted CueCat Output With Ugly Python</title><content type='html'>&lt;pre style=&quot;font-family:Andale Mono,Courier New;font-size:10px;&quot;&gt;import sys; from string import maketrans as m; from binascii import a2b_uu as d
q = lambda x,y: &#39;&#39;.join([chr(c) for c in range(ord(x), ord(y) + 1)])
t = m(q(&#39;a&#39;,&#39;z&#39;) + q(&#39;A&#39;,&#39;Z&#39;) + q(&#39;0&#39;,&#39;9&#39;) + &#39;+-&#39;, q(&#39; &#39;,&#39;_&#39;))
def u(st): return &#39;&#39;.join([chr(ord(c) ^ 67) for c in d(chr(32 + 3 * len(st) / 4) + st)])
print &quot;ID: %s, Type: %s, Barcode: %s&quot;%(tuple([u(b.translate(t)) for b in sys.stdin.read().split(&#39;.&#39;)[1:-1]]))
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6838123200978191842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6838123200978191842?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6838123200978191842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6838123200978191842'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/02/decode-encrypted-cuecat-output-with.html' title='Decode Encrypted CueCat Output With Ugly Python'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-3172280639956025715</id><published>2010-02-13T23:59:00.006+11:00</published><updated>2010-02-14T02:30:09.114+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><title type='text'>12 Bar Blues on an Arduino</title><content type='html'>&lt;p&gt;Using a small 8ohm analogue speaker hooked up to pin 11, by strobing the pin, I generate a square wave (a kind of annoying timbre to be honest).    &lt;br /&gt;
I generate 2 octaves of semitones starting with A-220 and index into it.     &lt;br /&gt;
The timing is currently inaccurate as the note length for lower notes runs slightly longer (half a pulse width) than higher notes due to how the strobing currently works. It&#39;s surprisingly noticeable. I need to work on that to make it more consistent. Probably by using timer interrupts instead of delays.     &lt;br /&gt;
&lt;/p&gt;&lt;h4&gt;To do:&lt;/h4&gt;&lt;p&gt;Alter the volume by using analogWrite() to set the duty cycle of the pin... 255 = loud 0 = off.    &lt;br /&gt;
I think I can use that mechanism to generate other waveforms, I&#39;ll probably try sawtooth next.     &lt;br /&gt;
Proper ADSR waveforms.     &lt;br /&gt;
Multichannel output (haw haw).&lt;/p&gt;&lt;br /&gt;
&lt;pre style=&quot;font-family: Andale Mono, Courier New; font-size:10px&quot;&gt;const int baseFreq = 220; // A
const int numHalfTones = 24; // 2 Octaves
long frequencies[numHalfTones];
long halfFreqs[numHalfTones];

/* 12 semi-tones per octave
  | Bf| | | C#| Ef| | |F# |G# |
 -+---+ | +---+---+ | +---+---+-
| A | B | C | D | E | F | G | A |
+---+---+---+---+---+---+---+---+
 
 2 octaves: 
 0  1  2  3  4  5  6  7  8  9 10 11
 A Bf  B  C C#  D Ef  E  F F#  G G# 
 12 13 14 15 16 17 18 19 20 21 22 23
 */

int seq[] = {
  3,  7, 10, 12, 13, 12, 10 , 7,
  3,  7, 10, 12, 13, 12, 10 , 7,
  8, 12, 15, 17, 18, 17, 15, 12,
  3,  7, 10, 12, 13, 12, 10 , 7,
  10, 14, 17, -1,  8, 12, 15, -1
};

int notes = 40;

long getTimeHigh(int i)
{
  return halfFreqs[i]; 
};

void ToneGen(void)
{
  float baseMult;
  int i;
  int lastTone = baseFreq;  
  baseMult = pow(2.0 , 0.083333);
  for(i = 0; i &lt; numHalfTones; ++i)
  {
    long frequency = baseFreq;
    if(i)
    {
      frequency = (0.5 + (frequencies[i - 1] * baseMult));
    }
    frequencies[i] = frequency;
    halfFreqs[i] = (0.5 + (1000000.0 / frequency / 2.0));
  } 
};

void setup(void) {
  pinMode(11, OUTPUT);
  ToneGen();
  Serial.begin(57600);
}

int rest_count = 100;
long duration = (60 * 1000000) / 288;

void playNote(int idx)
{
  long tone = 0;
  if (idx &gt;= 0)
  {
    tone = getTimeHigh(idx);
  }

  long endTime = micros() + duration ;
  if (tone &gt; 0) 
  { 
    int val = HIGH;  
    while (micros() &lt; endTime) 
    {
      digitalWrite(11,val);
      delayMicroseconds(tone);
      val = !val;
    } 

  }
  else 
  {
    delay(duration / 1000);
  }   
  digitalWrite(11, LOW); 
}

void loop(void) {
  analogWrite(11, 0);
  for(int i = 0; i &lt; notes; ++i)
  {  
    playNote(seq[i]); 
    delay(10);
  }
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/3172280639956025715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/3172280639956025715?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3172280639956025715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3172280639956025715'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2010/02/12-bar-blues-on-arduino.html' title='12 Bar Blues on an Arduino'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-3589294709506938789</id><published>2007-06-08T03:56:00.000+10:00</published><updated>2007-06-08T04:01:31.910+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="LCD"/><category scheme="http://www.blogger.com/atom/ns#" term="mod"/><category scheme="http://www.blogger.com/atom/ns#" term="steampunk"/><title type='text'>Steampunk LCD Monitor</title><content type='html'>To go with the steampunk keyboard and mouse, the guys over at steampunk workshop have made an absolutely amazing steampunk shell for and LCD-Flat panel.&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://steampunkworkshop.com.nyud.net:8080/images/M19.jpg&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;&quot; src=&quot;http://steampunkworkshop.com.nyud.net:8080/images/M19.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can see it being made here &lt;a href=&quot;http://steampunkworkshop.com/lcd.shtml&quot;&gt;here&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/3589294709506938789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/3589294709506938789?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3589294709506938789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/3589294709506938789'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/06/steampunk-lcd-monitor.html' title='Steampunk LCD Monitor'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-1657667310450566216</id><published>2007-06-07T09:35:00.000+10:00</published><updated>2007-06-07T09:41:25.483+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3d scanning"/><category scheme="http://www.blogger.com/atom/ns#" term="lego"/><category scheme="http://www.blogger.com/atom/ns#" term="milk"/><category scheme="http://www.blogger.com/atom/ns#" term="webcam"/><title type='text'>How to scan in 3d using milk, lego, and a webcam.</title><content type='html'>&lt;a href=&quot;http://www.instructables.com/id/E16Y5T8F22U9YWA/&quot;&gt;This instructable&lt;/a&gt; shows how to create 3d models using milk, lego and a webcam. I love low-tech solutions, and this ranks right up there.&lt;br /&gt;&lt;br /&gt;This video shows how it works;&lt;br /&gt;&lt;br /&gt;&lt;object width=&quot;400&quot; height=&quot;325&quot;&gt;&lt;br /&gt;&lt;param value=&quot;http://www.youtube.com/v/XSrW-wAWZe4&quot; name=&quot;movie&quot;/&gt;&lt;br /&gt;&lt;param value=&quot;transparent&quot; name=&quot;wmode&quot;/&gt;&lt;br /&gt;&lt;embed width=&quot;400&quot; height=&quot;325&quot; wmode=&quot;transparent&quot; type=&quot;application/x-shockwave-flash&quot; src=&quot;http://www.youtube.com/v/XSrW-wAWZe4&quot;&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/object&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/1657667310450566216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/1657667310450566216?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1657667310450566216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/1657667310450566216'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/06/how-to-scan-in-3d-using-milk-lego-and.html' title='How to scan in 3d using milk, lego, and a webcam.'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-8230844310083940342</id><published>2007-03-19T20:27:00.000+11:00</published><updated>2007-03-19T21:13:39.454+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ExternalFile"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="sendfile"/><category scheme="http://www.blogger.com/atom/ns#" term="zope"/><title type='text'>Sendfile Patch for Zope2</title><content type='html'>I&#39;ve put together a patch for Zope that allows code to use the sendfile system call to transfer data out of Zope.&lt;br /&gt;&lt;br /&gt;As this requires a file object, it&#39;s only available for use from trusted code, so that means inside a Product or an External method.&lt;br /&gt;&lt;br /&gt;The good news is, that it&#39;s fairly easy to write an External method that does something useful like serve contents from a directory.&lt;br /&gt;&lt;br /&gt;Here&#39;s an example external method that serves files from &#39;/shared/images&#39;&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;import os&lt;br /&gt;directory = &lt;span class=&quot;string&quot;&gt;&#39;/shared/images&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hilight&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;(&lt;/span&gt;self, filename&lt;span class=&quot;specialChar&quot;&gt;)&lt;/span&gt;:&lt;br /&gt;    newPath = os.path.join(directory, filename)&lt;br /&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; os.access(newPath, os.F_OK|os.R_OK):&lt;br /&gt;        self.REQUEST.RESPONSE.setStatus(&lt;span class=&quot;int&quot;&gt;404&lt;/span&gt;)&lt;br /&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;br /&gt;    f = open(newPath, &lt;span class=&quot;string&quot;&gt;&#39;rb&#39;&lt;/span&gt;)&lt;br /&gt;    self.REQUEST.RESPONSE.sendfile(f, content_type=&lt;span class=&quot;string&quot;&gt;&#39;image/jpeg&#39;&lt;/span&gt;, other_headers = {&lt;span class=&quot;string&quot;&gt;&#39;Content-Disposition&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;inline;filename=&lt;span class=&quot;specialChar&quot;&gt;%s&lt;/span&gt;&#39;&lt;/span&gt;&lt;span class=&quot;specialChar&quot;&gt;%&lt;/span&gt;(filename))&lt;br /&gt;    f.close()&lt;br /&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;It uses the sendfile wrapper module from &lt;a href=&quot;http://tautology.org/software/python-modules/sendfile&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It gives you a speed up of 2-3 times serving content out of Zope from the filesystem.&lt;br /&gt;I also have a patch for ExternalFile to let this use the sendfile patch.&lt;br /&gt;&lt;br /&gt;You can get the code and the patch from &lt;a href=&quot;http://www.zope.org/Members/TheJester/Sendfile%20Patch&quot;&gt;zope.org&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/8230844310083940342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/8230844310083940342?isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8230844310083940342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/8230844310083940342'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/03/sendfile-patch-for-zope2.html' title='Sendfile Patch for Zope2'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-9070788425491395289</id><published>2007-02-24T08:30:00.000+11:00</published><updated>2007-06-08T04:33:36.672+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="1984"/><category scheme="http://www.blogger.com/atom/ns#" term="Aldous Huxley"/><category scheme="http://www.blogger.com/atom/ns#" term="Dick Cheney"/><category scheme="http://www.blogger.com/atom/ns#" term="dystopia"/><category scheme="http://www.blogger.com/atom/ns#" term="George Orwell"/><category scheme="http://www.blogger.com/atom/ns#" term="Iraq"/><category scheme="http://www.blogger.com/atom/ns#" term="terrorists"/><title type='text'>Dick Cheney vs George Orwell</title><content type='html'>In an article in the Sydney Morning Herald titled &lt;a href=&quot;http://www.smh.com.au/news/national/terrorists-aiming-for-empire/2007/02/23/1171734021090.html&quot;&gt;Terrorists have ambitions of empire, says Cheney&lt;/a&gt; Dick Cheney is reported to have said;&lt;br /&gt;&lt;blockquote&gt;[Terrorists&#39; ultimate aim is to establish] &quot;a caliphate covering a region from Spain, across North Africa, through the Middle East and South Asia, all the way to Indonesia -and it wouldn&#39;t stop there.&quot;&lt;/blockquote&gt;&lt;br /&gt;So this would mean we would see a map almost like this one (courtesty of wikipedia) where the yellow zone would indicate this caliphate;&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/1984_Orwell_arrows_2.png/800px-1984_Orwell_arrows_2.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/1984_Orwell_arrows_2.png/800px-1984_Orwell_arrows_2.png&quot; alt=&quot;&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;The problem is, the yellow zones represent the site of the &quot;Perpetual War&quot; in George Orwell&#39;s&lt;span style=&quot;font-style: italic;&quot;&gt; 1984&lt;/span&gt;.  In &lt;span style=&quot;font-style: italic;&quot;&gt;1984&lt;/span&gt; the perpetual war is unwinnable (and maybe fabricated), and is one of the mechanisms to to keep the population under control.&lt;br /&gt;&lt;br /&gt;Amusing isn&#39;t it, that an Orwelling dystopia may be upon us?</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/9070788425491395289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/9070788425491395289?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/9070788425491395289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/9070788425491395289'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/02/dick-cheney-vs-george-orwell.html' title='Dick Cheney vs George Orwell'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-182184296628165300</id><published>2007-02-17T01:18:00.000+11:00</published><updated>2007-02-18T01:31:26.044+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="trac"/><category scheme="http://www.blogger.com/atom/ns#" term="zope"/><title type='text'>ZopeTrac Updated</title><content type='html'>I have updated ZopeTrac to 0.10.3, which makes it work with Trac 0.10.3.&lt;br /&gt;&lt;br /&gt;You can get it from here; &lt;a href=&quot;http://www.zope.org/Members/TheJester/ZopeTrac/ZopeTrac/&quot;&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I will try to mimic the Trac release numbers so you can tell what version of Trac it last worked with.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/182184296628165300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/182184296628165300?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/182184296628165300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/182184296628165300'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/02/zopetrac-updated.html' title='ZopeTrac Updated'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21956912.post-6792318912267986567</id><published>2007-02-13T23:16:00.000+11:00</published><updated>2007-02-13T23:17:45.931+11:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dumb"/><category scheme="http://www.blogger.com/atom/ns#" term="False Advertising"/><category scheme="http://www.blogger.com/atom/ns#" term="Google"/><title type='text'>Some Advertisers are stupid...</title><content type='html'>&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEw-GvqP4VmylsetJoLySxVEBkgWXBzeJmfcVV2Xu5coRkZGR0fONExhyphenhyphenmG9EDxPgBClPQ2wf9On0G0RjJPdFS7TPPBCZ4gaEvYr0uBRyV0y-PHm1WK6yfM1Qo3ioOodRXdWOdAw/s1600-h/FalseAdvert.jpg&quot;&gt;&lt;img style=&quot;margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEw-GvqP4VmylsetJoLySxVEBkgWXBzeJmfcVV2Xu5coRkZGR0fONExhyphenhyphenmG9EDxPgBClPQ2wf9On0G0RjJPdFS7TPPBCZ4gaEvYr0uBRyV0y-PHm1WK6yfM1Qo3ioOodRXdWOdAw/s200/FalseAdvert.jpg&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5030991831649187922&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;Whilst doing a search on how to lodge a false advertising complaint, the following advertisement appeared. Perhaps these people need to be more selective in the terms they want to advertise with.&lt;br /&gt;&lt;br /&gt;Dumb.</content><link rel='replies' type='application/atom+xml' href='http://gabbpuy.blogspot.com/feeds/6792318912267986567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/21956912/6792318912267986567?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6792318912267986567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21956912/posts/default/6792318912267986567'/><link rel='alternate' type='text/html' href='http://gabbpuy.blogspot.com/2007/02/some-advertisers-are-stupid.html' title='Some Advertisers are stupid...'/><author><name>TJ</name><uri>http://www.blogger.com/profile/15256046011166077508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEw-GvqP4VmylsetJoLySxVEBkgWXBzeJmfcVV2Xu5coRkZGR0fONExhyphenhyphenmG9EDxPgBClPQ2wf9On0G0RjJPdFS7TPPBCZ4gaEvYr0uBRyV0y-PHm1WK6yfM1Qo3ioOodRXdWOdAw/s72-c/FalseAdvert.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>