<?xml version="1.0"?><rss version="2.0"><channel><title>partiallydisassembled.net</title><link>http://www.partiallydisassembled.net/blog</link><description>partiallydisassembled.net</description><item><title>What slows down development...</title><pubDate>Sat, 16 Aug 2008 17:00:22 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=170</link><description>&lt;pre&gt;... Vista bluescreening every time I terminate a hung Python process that has a 
lock (&amp;quot;Process has locked pages&amp;quot;).  Yep, I can trigger it consistently 
and reliably.

Makes.. me.. angry!&lt;/pre&gt;</description></item><item><title>Multithreaded goodness for pyglet</title><pubDate>Tue, 12 Aug 2008 00:01:13 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=169</link><description>&lt;pre&gt;I&apos;ve finally gotten some good results after spending the last few months (on and 
off) refactoring the pyglet.media module in pyglet to use multiple threads.  
There were two main reasons for attempting this: to make better use of multi-core 
machines (pyglet is currently single threaded), and to avoid having to schedule 
audio pump in the main event loop (in pyglet 1.0 this was explicit, in 1.1 it&apos;s 
done on the clock).  

The problem with having the audio pump in the main loop is that it requires 
application developers to manually tune their programs to keep the audio buffer 
full -- and this is obviously very dependent on the hardware and drivers 
available.  One motivating example was my last PyWeek entry, which had background 
music that stalled during long loading times (I managed to get this down to just 
the initial loading time, and smooth for the rest of the game, but this was a lot 
of effort, and removing the initial pause proved too difficult).

The redesigned media module is still residing in the experimental/mt_media 
directory of SVN trunk.  Only the OpenAL driver is anywhere near complete.  The 
DirectSound driver has yet to be ported to the multithreaded API, and the ALSA 
driver has been deprecated in favour of a new PulseAudio driver.  PulseAudio is 
proving far more reliable and capable than the ALSA user-space daemon, and has 
been the default audio server in both Ubuntu and Fedora Core for some time.  The 
PulseAudio driver is mostly complete, but has no 3D capability (Linux users can 
still choose to use OpenAL as an alternative).

The audio driver modules are required to pump themselves now.  The PulseAudio 
driver does this using the built-in PA thread runloop, whereas the OpenAL driver 
creates a Python thread that periodically wakes.

Much of the shared code between drivers regarding video frame synchronisation 
has been moved into the base classes.  This should greatly reduce the amount of 
effort required to develop a new audio driver.  Audio drivers dispatch events to 
the Player object when a new video frame should be displayed.  New methods on 
pyglet.app make it easy to post events from one thread into the main event loop 
safely (these also automatically wake up the main event loop if it&apos;s sleeping, 
allowing more opportunities for people to integrate multithreaded code into their 
pyglet applications).

The AVbin source driver also now spawns a worker thread for decoding video 
frames.  Since most of the work in decoding the frame is done outside of Python 
(in FFmpeg), this is a great chance for pyglet to do some real multiprocessing.  
Quite a lot of work went into ensuring the queue of video frames to be decoded is 
kept up-to-date with what&apos;s needed on-screen; without an excessive preroll period 
or memory usage.

I&apos;ve done most development on my 900MHz iBook, which is incapable enough that it 
can&apos;t even play YouTube videos in real time (though pyglet can play them just 
fine once downloaded, thanks to FFmpeg).  This has forced me to make the 
implementation efficient enough to work on old computers; the overhead of the 
extra thread processing is significant and required several manual context 
switches to get everything playing (almost) as well as the old, single-threaded 
code.

On newer computers the performance is fantastic.  I did a quick benchmark test 
on my 1.8GHz Core 2 Duo Mac Mini.  It happily plays 7 SD videos simultaneously 
(DivX or Xvid encoding) without sweating, whereas the old code could only play 3 
videos.  Watching the activity monitor shows that both cores are now being 
utilised fully when needed (and run each at around 5% when playing a single 
video).

Expect to see this new code in pyglet 1.2.  I&apos;ll introduce some more of the new 
features over the next few weeks.  I&apos;ll also be talking about pyglet 1.2 at OSDC 
2008 in Sydney in December.&lt;/pre&gt;</description></item><item><title>Good looking tick mark distribution</title><pubDate>Mon, 11 Aug 2008 18:40:25 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=168</link><description>&lt;pre&gt;Given a min/max range of any magnitude, how do you generate a &amp;quot;nice 
looking&amp;quot; distribution of values to cover the range?  My need for this was to 
generate tick marks on a graph.  The function I came up with works quite nicely, 
I think:

    import math

    def distribute_nicely(min_val, max_val, min_ticks=3, max_ticks=8):
        if max_val - min_val == 0:
            return [min_val]
        mag = 10 ** int(math.log10(max_val - min_val) - .5)
        if mag == 0:
            mag = 0.1
        for multiplier in (10, 5, 2, 1, .5, .2, .1):
            interval = multiplier * mag
            if min_ticks &amp;lt;= (max_val - min_val) / interval &amp;lt;= max_ticks:
                min_val = (min_val // interval) * interval
                break
        else:
            interval = (max_val - min_val) / max_ticks or max_val - min_val
        if interval &amp;gt; 1:
            return range(min_val, max_val + interval, interval)
        else:
            return [i * interval  \
                    for i in range(int(min_val / interval), 
                                   int(max_val / interval) + 1)]

Sample results:

    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(0, 10)
    [0, 2, 4, 6, 8, 10]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(0, 100)
    [0, 20, 40, 60, 80, 100]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(0, 5)
    [0, 1, 2, 3, 4, 5]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(3, 8)
    [3, 4, 5, 6, 7, 8]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(24, 786)
    [0, 200, 400, 600, 800]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(0.21, 0.86)
    [0.2, 0.4, 0.6, 0.8]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(-8, 8)
    [-10, -5, 0, 5, 10]
    &amp;gt;&amp;gt;&amp;gt; distribute_nicely(-105, 105)
    [-150, -100, -50, 0, 50, 100, 150]

I&apos;d be interested to hear if anyone has an alternative function or improvements 
to this one.  Or if there&apos;s one in the standard library -- I always tend to miss 
those :-)&lt;/pre&gt;</description></item><item><title>Clean termination of daemon Python threads</title><pubDate>Sat, 09 Aug 2008 11:23:03 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=167</link><description>&lt;pre&gt;Daemonic threads in Python are threads that will not prevent the interpreter 
from exiting (put another way, the interpreter shuts down when all non-daemon 
threads exit).  When the interpreter shuts down, all variables are set to None, 
then each daemon thread is woken up to crash (unexpectedly finding all its 
variables, globals and builtins missing).

Here&apos;s a nifty pattern that suppresses the ugly exception trace resulting from 
these crashes being printed to the terminal:

    def worker_thread():
        try:
            .... do work ...
        except:
            if True:
                raise

This ensures ordinary exceptions are re-raised, but interpreter shutdown related 
exceptions are suppressed, as True is evaluated as None.  In the off-chance that 
some future or alternative Python interpreter doesn&apos;t have the same strange 
daemon thread shutdown behaviour, the thread will still behave correctly.&lt;/pre&gt;</description></item><item><title>Annotate observed types in a Python program</title><pubDate>Wed, 18 Jun 2008 12:22:02 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=166</link><description>&lt;pre&gt;Neat script I wrote for a friend to &lt;a href=&apos;http://yallara.cs.rmit.edu.au/~aholkner/annotype.py.txt&apos;&gt;annotate a Python script&lt;/a&gt; with the types 
observed during a run of the program.  Usage:

    python -m annotype test.py

With this script:

    def foo(bar, baz):
        pass

    foo(1, &apos;a&apos;)
    foo(2, 3)

Outputs &apos;out_annotype/test.py&apos; with:
    
    def foo(bar, baz):
        # [annotype] bar: int
        # [annotype] baz: str, int
        pass

    foo(1, &apos;a&apos;)
    foo(2, 3)

Hopefully useful for discovering usage of undocumented APIs.&lt;/pre&gt;</description></item><item><title>Python, meet Vista/64</title><pubDate>Fri, 09 May 2008 00:06:24 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=165</link><description>&lt;pre&gt;Finally bought a copy of Vista/64 today.  First Python experience:

    C:\Python25&amp;gt;python
    Python 2.5.2 (r252:60911, Feb 21 2008, 13:17:27) [MSC v.1400 64 bit (AMD64)] 
on win32
    Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or 
&amp;quot;license&amp;quot; for more information.
    &amp;gt;&amp;gt;&amp;gt; import sys
    &amp;gt;&amp;gt;&amp;gt; sys.platform
    &apos;win32&apos;
    &amp;gt;&amp;gt;&amp;gt;

Sigh.  And then,

    &amp;gt;&amp;gt;&amp;gt; import ctypes
    Traceback (most recent call last):
      File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;
    ImportError: No module named ctypes
    &amp;gt;&amp;gt;&amp;gt;

Um, should Python even be distributed as version &amp;quot;2.5.2&amp;quot; on this 
platform if parts of the standard library are missing?

(Oh, and Vista is pretty, except when the &amp;quot;Press this button to keep doing 
what you&apos;re doing&amp;quot; dialog pops up, because it always seems to blank the 
screen first -- possibly disabling Aero temporarily?).&lt;/pre&gt;</description></item><item><title>Compiling for G3 on OS X 10.5</title><pubDate>Fri, 18 Apr 2008 00:03:46 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=164</link><description>&lt;pre&gt;It took me a long time to figure this out.  By default gcc on Leopard compiles 
for OS X 10.5 only.  When cross-compiling to PowerPC, the default target is 
actually certain G4 models.  The magic options for G3&apos;s and OS X 10.3.9 (it looks 
like you can&apos;t compile for earlier versions any more) and later:

    -arch ppc 
    -isysroot /Developer/SDKs/MacOSX10.4u.sdk 
    -mmacosx-version-min=10.3.9
    -force_cpusubtype_ALL

(both linker and compiler).  Use 

    otool -hv xyz.dylib

to check that a Mach-O file is for the target you expect (&amp;quot;ppc&amp;quot; not 
&amp;quot;ppc7740&amp;quot; etc), and

    lipo -info xyz.dylib

to check the contents of a universal binary.&lt;/pre&gt;</description></item><item><title>pyglet download statistics</title><pubDate>Sun, 23 Mar 2008 22:44:21 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=163</link><description>&lt;pre&gt;I felt charty this evening, and this is what happened:

&lt;img src=&apos;http://chart.apis.google.com/chart?chs=550x300&amp;amp;chd=t:49,241,69,101,234,542,263|67,448,244,330,316,69,176|28,6,10,2,10,440,49|45,7,10,4,126,440,245|76,926,382,630,727,2237,0|43,177,116,131,180,552,0&amp;amp;cht=bvs&amp;amp;chds=0,5100&amp;amp;chco=00aaaa,00cccc,aa4444,cc4444,44aa44,44cc44&amp;amp;chxt=x,y&amp;amp;chxl=0:|1.0alpha1|1.0alpha2|1.0beta1|1.0beta2|1.0beta3|1.0|1.1alpha1|1:|0|1000|2000|3000|4000|5000|&amp;amp;chbh=35,20&amp;amp;chdl=.zip source|.tar.gz source|2.4 egg|2.5 egg|Windows runtime|Mac OS X runtime&apos; /&gt;

That&apos;s a breakdown by release and distribution of pyglet, from 1.0 alpha 1 
through to 1.1 alpha 1 (alpha 2, released hours ago, doesn&apos;t yet rate on this 
chart).

Interesting to note: the eggs are popular for release, but not development.  The 
only reason they&apos;re featured in 1.0 alpha 1 is that they were actually linked 
from the download page then.  (Now people are only likely to grab an egg if 
they&apos;re using easy_install from the command line).

The Windows installer is quite the popular, which makes me glad I spent so much 
time on it.  (I&apos;m not making installers available for 1.1 alpha releases).

Here are the download stats for the packages including documentation/examples.

&lt;img src=&apos;http://chart.apis.google.com/chart?chs=520x300&amp;amp;chd=t:95,931,370,456,515,1221,272|49,241,69,101,234,542,263|67,448,244,330,316,69,176&amp;amp;cht=bvs&amp;amp;chds=0,5100&amp;amp;chco=4444aa,00aaaa,00cccc&amp;amp;chxt=x,y&amp;amp;chxl=0:|1.0alpha1|1.0alpha2|1.0beta1|1.0beta2|1.0beta3|1.0|1.1alpha1|1:|0|1000|2000|3000|4000|5000|&amp;amp;chbh=35,20&amp;amp;chdl=Documentation|.zip%20source|.tar.gz%20source&apos; /&gt;

Looks to me like the number of developers isn&apos;t really increasing, but perhaps 
those developers are testing on more machines, and perhaps there are some runtime 
installations being made on non-developer machines.  Or maybe there are more 
developers but they&apos;re happy to use old or online documentation.

There are currently 271 pyglet-users members (or 269, depending on which counter 
on the same page you read).&lt;/pre&gt;</description></item><item><title>Play with your peas</title><pubDate>Tue, 12 Feb 2008 23:40:29 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=162</link><description>&lt;pre&gt;Danc of &lt;a href=&apos;http://lostgarden.com&apos;&gt;Lost Garden&lt;/a&gt; has posted a new &lt;a href=&apos;http://lostgarden.com/2008/02/play-with-your-peas-game-prototyping.html&apos;&gt;game challenge&lt;/a&gt; that includes a design and 
sprites.

Under the cover of &amp;quot;testing the latest pyglet features&amp;quot; (but really 
for the hell of it) I made a quick stab at it last night and today.

&lt;img src=&apos;/peas/peas-ss.png&apos; /&gt;

You can play with &lt;a href=&apos;/peas/peas-1.zip&apos;&gt;peas-1.zip&lt;/a&gt;, you&apos;ll need pyglet trunk r1760.  It&apos;s nothing like 
complete: you can place and remove blocks, and the peas will A* themselves up to 
the higest point and &amp;quot;ninja&amp;quot; themselves off it; but the scoring, flag 
raising and deathliness is missing.

The physics seems quite stable (using Verlet integration with a fixed timestep), 
but the contact constraints on the corners are doubled, which is why the peas 
seem to gain energy when bouncing off walls.

I made a botch of the AI movement: every specific combination of blocks that can 
be moved between has to be listed (e.g., left side of standard block to top side 
of left ramp, ...).  I didn&apos;t get around to listing them all, so the peas will 
refuse to move around certain objects that seem trivial.  If you just place 
standard blocks they&apos;ll do fine.  I would rewrite this to something a bit 
cleverer if I was going to continue any further...

...which I don&apos;t think I will.  These peas are cute, but I don&apos;t think the game 
is going to turn out all that great, relative to the effort required to fix up 
the AI and physics.

I was able to pick up a few pyglet bugs writing this.  The sprite module seems 
(now) pretty solid and absolutely useful for this kind of game -- I didn&apos;t need 
to use pyglet.gl at all.&lt;/pre&gt;</description></item><item><title>7</title><pubDate>Sat, 19 Jan 2008 23:50:53 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=161</link><description>&lt;pre&gt;I think it&apos;s great that channel 7 chooses to simulcast the tennis on all five of 
their digital channels, rather than running the scheduled movie.  Just like 
watching someone else play that Wii game.&lt;/pre&gt;</description></item><item><title>delta-v update</title><pubDate>Tue, 15 Jan 2008 01:36:10 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=160</link><description>&lt;pre&gt;I ported &lt;a href=&apos;/deltav&apos;&gt;delta-v&lt;/a&gt; to pyglet 1.0 beta 3, and also took the opportunity to fix some 
gameplay issues:

  * Baddies now die when shot, rather than just being pushed away.
  * The field of view is reduced.
  * There is a more obvious visual indicator when the player is hurt.
  * Player&apos;s health is gradually restored continually.
  * Motion blur is greatly reduced.
  * Survival mode score resets to zero before each attempt.

This makes the game far less frustrating.&lt;/pre&gt;</description></item><item><title>Son of follower of lines</title><pubDate>Tue, 01 Jan 2008 23:44:41 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=159</link><description>&lt;pre&gt;Much improved, as predicted.

&lt;a href=&apos;http://img40.picoodle.com/img/img40/5/1/1/f_IMG0364m_b6421a2.jpg&apos;&gt;&lt;img border=&apos;1&apos; src=&apos;http://img40.picoodle.com/img/img40/5/1/1/t_IMG0364m_b6421a2.jpg&apos; /&gt;&lt;/a&gt;

I ripped up the front of the tribot and replaced the jaws with an articulated 
light sensor, which can sweep +/- around 60 degrees from center.  It took quite a 
while to figure out how to gear it and get everything solid enough; all these 
new-fangled lego pieces I&apos;ve not seen before.

This is what it does:

&lt;object width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;param name=&apos;movie&apos; value=&apos;http://www.youtube.com/v/x0V4J_aXveQ&amp;amp;rel=1&apos;&gt;&lt;/param&gt;&lt;embed src=&apos;http://www.youtube.com/v/x0V4J_aXveQ&amp;amp;rel=1&apos; type=&apos;application/x-shockwave-flash&apos; width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;/embed&gt;&lt;/object&gt;

It&apos;s much faster than the last one -- when it gets it right, it can work out the 
curvature of the line and steer exactly along it.  When it loses the line, it 
backtracks a little to find it.  At the end of the video you can see the sensor 
can&apos;t pick up the sharp turn in the line and the robot drives off into oblivion 
(more work required).

On the programming side of things, I&apos;m getting more used to the NXT environment. 
 I used two threads: one to control the sensor motor and one for the drive 
motors.  They communicate through two semaphores: the angle of the sensor motor, 
and a flag that gets raised when the sensor has lost the line.

It probably would be feasible to do it in a single run-loop, albeit with more 
state variables, and the NXT tool has fits with two many nested conditionals (it 
also has fits about most other things, to be fair).

I find I have to change the tolerances of the light/dark sensing very carefully 
to avoid incorrect readings.  I have to adjust these tolerances throughout the 
day, by trial and error, due to the change in ambient light.  I still haven&apos;t had 
any luck with the calibration.

Here&apos;s the source code; this time I&apos;ve added some annotations that might give a 
feel for what it&apos;s all about.  Note that this is the only view of the program 
you&apos;re given, and it can&apos;t be zoomed out (nor are there scrollbars...).

&lt;a href=&apos;http://img31.picoodle.com/img/img31/5/1/1/f_linefollow2m_9764e72.png&apos;&gt;&lt;img border=&apos;1&apos; src=&apos;http://img31.picoodle.com/img/img31/5/1/1/t_linefollow2m_9764e72.png&apos; /&gt;&lt;/a&gt;&lt;/pre&gt;</description></item><item><title></title><pubDate>Mon, 31 Dec 2007 19:35:50 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=158</link><description>&lt;pre&gt;&lt;a href=&apos;http://img27.picoodle.com/img/img27/5/12/31/f_followline1m_47d5f32.jpg&apos;&gt;&lt;img border=&apos;1&apos; src=&apos;http://img27.picoodle.com/img/img27/5/12/31/t_followline1m_47d5f32.jpg&apos; /&gt;&lt;/a&gt; 

First Mindstorms robot.  Here it is in action:

&lt;object width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;param name=&apos;movie&apos; value=&apos;http://www.youtube.com/v/52KrhSZaypE&apos;&gt;&lt;/param&gt;&lt;embed src=&apos;http://www.youtube.com/v/52KrhSZaypE&apos; type=&apos;application/x-shockwave-flash&apos; width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;/embed&gt;&lt;/object&gt;

I started out with the tribot, which has building instructions but no real 
programs.  I had to rip up the front of it to move the light sensor further from 
the floor -- in its initial position it couldn&apos;t tell the difference between 
white and black.

You can show the current readings of the sensors on the device, which would be 
handy when programming thresholds, but they don&apos;t seem to match up at all... so 
it needed quite a bit of tweaking.

Here&apos;s the source code:

&lt;a href=&apos;http://img26.picoodle.com/img/img26/5/12/31/f_followline1m_03555ef.png&apos;&gt;&lt;img border=&apos;1&apos; src=&apos;http://img26.picoodle.com/img/img26/5/12/31/t_followline1m_03555ef.png&apos; /&gt;&lt;/a&gt;

Lots of room for improvement...&lt;/pre&gt;</description></item><item><title>Method caching in CPython</title><pubDate>Mon, 17 Dec 2007 11:32:50 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=156</link><description>&lt;pre&gt;&lt;a href=&apos;http://bugs.python.org/issue1685986&apos;&gt;This patch&lt;/a&gt; by Armin Rigo has been getting a lot of attention on the python-dev 
list recently.  From the description:

  This is a port of PyPy&apos;s method cache optimization.  It gives a very good 
  speed-up to PyPy, and it is simple enough to be attempted on CPython.

The patch introduces a global method cache, currently set to hold 1024 elements. 
 Each element in the cache looks like this:

  struct method_cache_entry {
      int version;
      PyObject *name;
      PyObject *value;
  };

The struct is 12 bytes wide on 32-bit systems and 20 bytes wide on 64-bit 
systems, making the table 12kb and 20kb large, respectively.

Each Python type is given a &amp;quot;version&amp;quot; number which is treated the same 
as version numbers in Microsoft&apos;s Dynamic Language Runtime.  Version numbers are 
obtained from a global counter (so no two types share the same version number).  
When a type is modified, that type&apos;s version number is refreshed (updated from 
the global counter), as are the version numbers of all that type&apos;s subtypes.

When an attribute is looked up on a type (i.e., because it has failed lookup on 
the object), the cache is first checked for the corresponding type&apos;s version 
number, and the name of the method.  The method cache is a hash table, with the 
hash formed by the tuple (version, name).

If that attribute is not found in the method cache, lookup proceeds through the 
MRO as usual; however that method will subsequently be cached before returning.  
The entry in the method cache that occupies the same hash location will be 
tossed.

The version number is a 32-bit int, and wraparound is handled correctly (when 
the global counter reaches 0 again, the method cache is cleared).  The last time 
I checked, Microsoft&apos;s DLR did not gracefully handle wraparound.  Because type 
modification is relatively rare, I believe the version number could be held in a 
16-bit integer without performance penalty, and with a small memory footprint 
benefit.  I haven&apos;t tried this though.

Armin and the patch reviewers have been reporting a consistent 20% or better 
performance improvement on total runtime of all applications, which is nothing to 
be sneezed at.  The patch is still under review but looks like it&apos;s heading for 
inclusion in Python 2.6.

The technique is similar to method caching used in Smalltalk-80.  All 
implementations of Smalltalk use a global descriptor table which maps the (class, 
method) tuple to the method object.  The earlier implementations, up until 1983, 
typically used global method caches like this one to decrease the cost of looking 
in the global table.  Since then, inline caches have been the typical approach, 
such as in Smalltalk (1984), Self (1994) and the Microsoft DLR / IronPython 
(2007).
&lt;/pre&gt;</description></item><item><title>TEN HD beg for my forgiveness</title><pubDate>Sun, 16 Dec 2007 09:54:45 +1000</pubDate><link>http://www.partiallydisassembled.net/blog/?item=155</link><description>&lt;pre&gt;No doubt in response to my &lt;a href=&apos;http://www.partiallydisassembled.net/blog/?item=149&apos;&gt;post last month&lt;/a&gt;, TEN has &lt;a href=&apos;http://www.smarthouse.com.au/HD/HD_TV/P3C9M2T4&apos;&gt;stopped using the term 
&amp;quot;full HD&amp;quot;&lt;/a&gt; to describe their new channel, which launches today.

Disappointingly the new channel offers little new content (one late night movie 
most days, and repeats of Veronica Mars and Battlestar Galactica), and even less 
timeshifted content (only the news, delayed by half an hour).

&lt;a href=&apos;http://www.ebroadcast.com.au/TV/static/MelbourneNight.html&apos;&gt;EBroadcast&lt;/a&gt;, with their larger-than-screen-sized banner ads, have the TEN HD 
schedule; &lt;a href=&apos;http://www.yourtv.com.au/guide/index.cfm?action=tonight&apos;&gt;YourTV&lt;/a&gt;, with their sensibly-sized ads, have not yet added TEN HD or 7 
HD.&lt;/pre&gt;</description></item></channel></rss>