The Coding Weasel

Tuesday, March 06, 2007

a theatrical open-source story, part one.

In what I laughingly refer to as "my spare time" I do lighting and sound for an amateur theatre company. The current play (plug: come see it - it's really, really good) has some fairly major tech behind it - particularly for a small amateur theatre (i.e. a miniscule budget).

The requirements include:
  • dual projectors behind stage, showing around 150 slides during the course of the show
  • a camera on stage at various points, going to the projectors. These then get news overlays on screen to make it look like a live news conference. The projectors are behind the screens, so the video needs to be flipped left-to-right.
  • a couple of dozen pieces of music to be played at various points - this needs to fade in and out cleanly.


I'm also operating the lighting desk while I do this, so whatever I do has to be incredibly easy to operate. Requiring me to use the mouse is just right out.

Oh, and of course I shouldn't forget that I really only had one or two evenings to put something together. The choice of hardware was pretty easy - clearly I'm going to need a couple of PCs - one backstage with the camera and the projectors, connected by wireless to a laptop in the lighting box running the whole show (and outputting audio to the sound system when needed). I grabbed a cheapo wireless card and a Radeon 9550 (with a DVI-to-VGA convertor, I get the two VGA outs that I need) for a spare desktop I had lying around and dropped a fresh install of Ubuntu Edgy on it.

Software - well, clearly this calls for some one-off custom software. Again, my choices were pretty easy. Python (duh), pygtk for the UI, gstreamer for the audio and video, and twisted to tie things together. Things like callLater and deferreds just make stuff too damn easy.

So how did I do? Well, here's a quick sampler (click the image for a larger version). I'll talk about it in more detail in a subsequent post. This was the result of a single Sunday evening's intense hacking, followed by a few hours over a couple of nights tweaking things after using it. All up, it's under 600 lines of code, plus a few tiny shell scripts.

Image

Labels: , , ,

Tuesday, January 23, 2007

Journalamentism at it's finest.

Well, by "journalism" I mean "reprinting a press release". Normally this sort of thing would be over at my other place, but since it's open source related, I figure it can go here.

I'm referring to this piece on the site itwire.com.au, which is a straight rewrite of a press release.

The piece in question is an attack on the OLPC project by a rival not-for-profit which instead works on refurbishing computers.

On the plus side, the writer of the piece did point out that FAIR mis-spoke, (or perhaps flat-out lied) in calling OLPC a "normal commercial organisation". On the minus side, there was no attempt to investigate whether the claims made were true - I'm sorry, but when it's an extreme hatchet job, "An email has been sent to the press office of OLPC inviting the organization to respond to FAIR's comments" is hardly sufficient. Note the wording - not "they didn't reply", but "we sent an email and published anyway without getting a response first". Very very poor.

Particularly when, as in this case, a number of the claims made are easily refuted using the FAQ available from the front page of the OLPC website. (It's the big link on the left hand side labelled "FAQ")

FAIR's claim that refurbished PCs are a better option is dealt with - OLPC points out that one hour of work per PC, times 100 million refurbished machines is 45,000 work years.

FAIR's claim that a single lab full of P4 computers would cost a tenth of the amount of the cost of the OLPC basis and provide the same outcomes is clearly laughable. Lets do a little math here. Assume the 500 laptops for a school - FAIR claims a tenth of US$100,000 is needed. OK. That's $10,000. Assume a lab of 16 P4 machines for $600 each, including software. That works out to around 1 hour of computer time per week per student. That's really what they think is equivalent to a machine that can be taken home?

More from FAIR: "For example, OLPC does not even offer a simple spreadsheet. Theoretically it might be possible for OLPC to be made satisfactorily compatible with PC (WIN/LIN/MAC), but it would take many years of software development to achieve this."

I have no idea if the current builds of OLPC software include a spreadsheet - but there's plenty of small Linux ones available, and I'm sure it could be added easily enough. Their focussing on this makes me suspect their own solution is to foist Windows + Office onto the 3rd world. Teaching kids office automation for an hour a week is hardly a useful set of skills - especially when compared to using a machine that they can carry around with them, and has software on it that's been designed for teaching. And if the OLPC project was starting from scratch, and trying to replicate Windows, sure, it would take years. Of course, they're doing nothing of the sort.

"With its limited 512 Mb memory it is equally likely that OLPC could never be able to become a satisfactory work station" - bollocks. Utter bollocks. Sure, you probably can't even load the Windows Vista installer in that space, but claiming that you need gigabytes of space to be useful is utterly insane and ludicrous.

Gah - I give up responding to the FAIR piece in depth. Suffice to say, it's full of easily refuted nonsense, and even a tiny amount of research would have shown that.




Last week at LCA there were a number of folks from OLPC in the country, including Jim Gettys and Chris Blizzard. Collabra folks got voice conferencing working on the OLPC. Mention was made of the 1.3km wireless range some Australians working with the OLPC managed to get. Some of the OLPC prototypes were brought along and demonstrated at the Open Day. All very neat stuff.

Meanwhile, itwire rewrites a misleading and incorrect press release from another non-profit working as a rival to the OLPC project. And itwire's
"Open Source" writer Sam Varghese was focused like a laser on the stories that really matter:


  • the ground-breaking story that Novell was a minor sponsor of LCA, and Bruce Perens doesn't like this. Gosh. Well, Bruce Perens opinion clearly outweighs GNOME, Mono and all the other work Novell does for Linux. How very silly of LCA organisers to not run all their arrangements through Perens first! I can't imagine why, with a title like "30 Pieces of Silver", this piece might be considered a trite and insulting beatup.

  • Builder AU had an interview with Linus Torvalds, and the video put on the Builder AU website required a version of the flash plugin that's only been available for a short time for Linux. Note - he wasn't writing about the conference videos on the LCA site itself, which are in an open source, unencumbered format - but that the magazine Builder AU interviewed someone at LCA and put up a flash video player thingy. And he quotes someone who posted a comment on slashdot - how much more credible can you get? I think you'll agree that this is a major, major scandal, and obviously LCA should be held entirely responsible. No - wait. The other term I used: a trite and insulting beatup.





I could go on further - the itwire open source articles are just full of this sort of crap. But, frankly, I don't see any point.

Kids - don't just rewrite press releases. It's not big, it's not clever, and it's not funny. And don't bother with itwire - at least, not for news about open source.

ObDisclaimer: I find the OLPC project to be extremely neat, and plan on helping them where-ever I can. I also really, really don't like bad journalism. And quite clearly, I'm speaking for myself, and not for any projects or organisations I'm involved with.

More tech stuff soon. Sorry for the interruption/rant.

Labels: ,

Thursday, January 11, 2007

the venice project

Courtesy of Daniel, I got a betatest account for The Venice Project, the latest project from the folks who gave us Kazaa and then Skype. This is their attempt to do to TV what Skype does to phone calls.

So what is it? It's a peer-to-peer system for distributing full quality on demand streaming television over the internet.

The UI is a little awkward at first (it's an overlay over the video) but once you get used to it, it's nice and clean.

The content is organised into channels. At the moment, they're obviously still putting together content deals, so it's not an awesome range. I can see problems in the future with the "one big list of channels" approach once they get enough content into the system. There's a 'Search' option that still needs a fair bit of help.

The video quality is remarkable. I've noticed a few times where the audio/video starts stalling and glitching, but given I'm watching fullscreen TV quality, that's still not too bad at all. Whacking pause/play seems to make it better.

There's a few things I've noticed that are Not Quite Right - the most annoying is that it seems to disable the external video port on my laptop while it's running. I'd much, much rather watch the video on the external LCD than the laptop's own display. I've logged a bug against this, hopefully it's something they'll fix.

One huge caveat is the bandwidth requirements. The website quotes 220-320 megabytes per hour downstream, and 100 or so upstream. That pretty much means you need at least a 1Mbit connection (I have a 1.5Mbit connection). People on a 256k DSL link are probably going to have a non-useful experience. If you're on a bandwidth capped link, I could see this chewing through your cap in very short order. For people in Australia who are unfortunate enough to get excess billing charges, this could be very very scary. The application minimises itself to the system tray when you close it rather than quitting, so unless you want to cause yourself enormous pain, make sure you close it properly, or uncheck the "use standby mode" checkbox in the preferences screen.

As far as content - there's a pile of music-related things, documentaries, and various other bits and pieces. I'd fully expect this to grow rapidly.
(Aside: one of the channels is Fifth Gear. I'd heard of this as a knock-off of the BBC's Top Gear, but never watched it before. Wow. It's like Top Gear with the humour and sense of fun sliced out.)

Important Note: I do not have any spare beta invites to give away. Please don't bother asking me for them in comments.
(I only mention this because every other blog post I've seen on TVP gets countless numbers of people saying "pls send me invite kthxbye")

Labels:

Tuesday, January 02, 2007

Bruce 1.2

Bruce 1.2 is out. This is the version resulting from the work Richard and I both did while preparing our talks for OSDC a month ago, and means you can run the presentations I linked to earlier, without needing to grab the SVN version of the code.

It works on MacOS X, Unix, and Windows - but note that some bits, such as SpawnPage and ShellInterpreterPage won't work currently on Windows. If someone wants to contribute patches to make these work (it shouldn't be hard - I just don't have a need or motivation to do it right now) they'll be gratefully accepted.

I've begun the work on what will become Bruce 2.0 - this will be a merge of the IronKant code, allowing Bruce to run on IronPython with SdlDotNet, and should hopefully also include a pyglet backend. Pyglet should allow for a whole host of shiny new possibilities.

Next up is a talk at LCA 2007's Speaker's Dinner in 2 weeks.

Labels: , ,

Wednesday, December 13, 2006

gstreamer and messages, pt 1

If you take a simple GStreamer pipeline (for instance, something based on the first piece of code in this post) and run it, one of the first things you'll notice is that it doesn't exit when the file finishes playing. To do this, you'll want to use messages. Here's a simple example showing this. This example sets up a filesrc, connects it to a 'mad' element (which decodes MP3s) and then dumps out to ALSA via an alsasink.


import pygst
pygst.require("0.10")
import gst
import gobject

class Playback:
def __init__(self, filename):
self.pipeline = gst.Pipeline('player')

# Get the message bus from the pipeline
self.bus = self.pipeline.get_bus()
# register a watch function - self.message
self.bus.add_watch(self.message)

# create a filesrc->mad->alsasink pipeline
filesrc = gst.element_factory_make("filesrc", "input")
filesrc.set_property('location', filename)
converter = gst.element_factory_make("mad", "converter")
output = gst.element_factory_make("alsasink", "output")
output.set_property('device', 'plughw:0')
# Add them all to the pipeline with one call.
self.pipeline.add(filesrc, converter, output)
# Link them all together in one call.
gst.element_link_many(filesrc, converter, output)
self.pipeline.set_state(gst.STATE_PLAYING)

def message(self, bus, message):
# Check for an 'End Of Stream' message
if message.type == gst.MESSAGE_EOS:
print "Got EOS, quitting mainloop"
self.quit()
# We want to continue receiving messages, so return True
# If you return False, this function is removed from the list
# of functions that receive bus messages.
return True

def run(self):
self.mainloop = gobject.MainLoop()
self.mainloop.run()
def quit(self, *args):
self.mainloop.quit()

if __name__ == "__main__":
import sys
player=Playback(sys.argv[1])
player.run()

Let's look at this in more detail. After we create the pipeline, we get the message bus associated with it.

    # Get the message bus from the pipeline
self.bus = self.pipeline.get_bus()

We then add a 'watch' function to the pipeline. This function will receive all messages on the bus. You can't add more than one watch function to a pipeline (yet).

    # register a watch function - self.message
self.bus.add_watch(self.message)

The watch function itself is pretty simple - it takes the bus and the message as arguments, and returns True or False. The return value indicates whether we want to keep receiving messages. If you return False, this watch function is removed from the bus.

def message(self, bus, message):
# Check for an 'End Of Stream' message
if message.type == gst.MESSAGE_EOS:
print "Got EOS, quitting mainloop"
self.mainloop.quit()
# We want to continue receiving messages, so return True
# If you return False, this function is removed from the list
# of functions that receive bus messages.
return True

We compare the message.type with the singleton gst.MESSAGE_EOS. If it's true, we stop the mainloop and exit.

There's many other messages you can receive, not just end-of-stream. If we put a "print message.type" statement before the message.type check in the message() method, you'll see something like this:


flags GST_MESSAGE_CLOCK_PROVIDE of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_TAG of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_NEW_CLOCK of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_STATE_CHANGED of type GstMessageType
flags GST_MESSAGE_EOS of type GstMessageType

If you look a bit closer, you'll see there's a couple of sets of messages. First off, there's 4 STATE_CHANGED messages - one from each element, and from the pipeline itself. These are going from a state of VOID to PAUSED, as the pipeline starts up. There's another set of 4 going from PAUSED to PLAYING, and a final set of 4 going from PLAYING to VOID when the pipeline finishes. There's also a couple about the pipeline clock (which I'll touch on in a future piece) and a MESSAGE_TAG message. That's from the 'mad' converter, and if we print it, we'll see:
<gst.Message taglist, layer=(guint)3, mode=(string)joint,
emphasis=(string)none, audio-codec=(string)"MPEG-1\ layer\ 3",
bitrate=(guint)128000 from converter at 0x81cae98>

Note that these messages are from the pipeline as a whole, not from individual elements. If you want to know about when a particular element runs out of data, you use pad.add_event_probe() and look for EVENT_EOS. More on that in a future post.

That's enough for one starting post.



Please note - I'm still learning about gstreamer as I go. If you see something wrong, or unclear, please let me know in the comments. Also let me know if blogger has messed up the formatting - I think I've got it OK now.

Labels: ,

you're part of the problem, not part of the solution

Phillip Eby wrote a response to Richard's post about the OSDC problem with a softcore porn image being displayed in a lightning talk. He managed to completely miss the point as well as throw in any number of irrelevant sidepoints.


I was going to let it slide (as far as I can see, he is just being needlessly contrary and provocative), but ... to hell with it. He doesn't seem to have comments on his blog, so consider this my response.


The problem is not that "porn" is driving women away from the computer industry.


The problem is the mindset which says "it's fine to show porn in a talk at a conference". This is appalling.


If you don't think that putting up a softcore porn image of a woman is going to offend more women than men, you're out of your mind. I missed the slide in question (I was sitting outside finishing my own talk) but I heard enough from people about it afterwards. Plenty of people, both men and women, were offended. Almost every single female in the audience was offended, in some cases, extremely offended. (That PJE's own wife wouldn't have been offended is no excuse. That's nice for her but it doesn't excuse the slide in question). No-one would even contemplate putting up something offensively racist in a talk, or almost any other form of offensive imagery, but this sort of thing isn't that big an issue for some folks.


PJE also asks in his piece:



P.S. Does anybody know why it's supposed to be so gosh-darn important to have more women in IT?

He then compares it to the under-representation of men in the nursing industry.


Gah. Gah. Gah. I'm almost speechless.


Last time I looked, the nursing industry didn't provide a hostile work environment that actively discouraged men from joining. Plenty of people in the IT industry do this to women. PJE's minimisation of this issue is a great example.


As far as "why is it important to have more women in IT"... well, if he's being genuine here (rather than just contrary for the sake of it) I'm stunned. There's a basic issue of equity here. IT provides an ever increasing number of highly paid skilled jobs. Saying "if there's a hostile work environment that discourages women, too bad for them" is a mind-blowing attitude to me. (I'd have also thought that someone who's all about efficiency and that sort of thing would recognise that a more heterogenous team produces better outcomes all around.)


PJE finishes with this little pearler:



Now, some people will think I'm joking about what I just said, but that will serve only as a helpful illustration of their own bias. You see, when a person thinks that trying to protect men in porn is silly, it's because deep down, they think women need more "protection" than men -- thereby demonstrating their own patriarchal sexist patronizing bullshit attitude!

This is, to not put too fine a point on it, unmitigated bullshit of the highest order. If I saw that the industry I'm in was discriminating against any group, I'd be annoyed. The fact is, though, that it's primarily biased against women. I'm not trying to "protect" women because I think they need to be protected by big strong ol' me (hell, half or more of my female friends could easily beat 10 kinds of crap out of me in a serious fight). I'm annoyed because I see an industry full of people for whom putting up a softcore porn image in a talk in front of an audience isn't that big a deal.


And that is the issue.

Tuesday, December 12, 2006

some more on IronPython

Michael Foord has some notes on getting IronKant working with IronPython on Windows here

During my talk, I showed a slide that IronPython on .Net runs pybench at 41% of CPython 2.5's speed (71%, if you exclude the TryRaiseExcept case, where it totally loses), while Mono 1.1.17 gets around 14% of of CPython 2.5's speed. I finally got around to trying Mono 1.2.2 (I didn't have time before the talk). It's actually about 12% _slower_ than 1.1.17. This makes me sad. Very sad. I need to get pybench checked into IPCE and point the Mono and .Net folks at it.

It's pretty obvious that both .Net and Mono optimised for pystone - in both cases, IronPython is more than 20% faster than CPython. Unfortunately, pystones is a terrible benchmark. If they can optimise for pybench, most people's applications will see a real improvement.

Labels: , ,

Monday, December 11, 2006

talk #2: futurepython

The final talk from the three I did at OSDC is up now. This was the end of day talk on Thursday, "futurepython". I talked about IronPython and Python 3.0. Unlike the other two talks, this one wasn't done using Bruce. Instead, I did an extremely quick port of Bruce to run on top of IronPython and SdlDotNet. In keeping with the philosopher's naming scheme of Bruce, I called it "ironkant".

The talk is here, including the ironkant code. I should point out that ironkant almost certainly has bugs - I started it late Wednesday night after the conference dinner and finished it (and the talk) a good 5 minutes before I presented it the next afternoon. What can I say, I just thrive on the stress. Having the presentation running on top of IronPython was a pretty good demonstration of just how far along IronPython has come.

And sorry Jim for calling you a crazy man - I mean that with love and respect :-)

I was extremely impressed with how easy it is to grab a C# assembly, read the C# docs and get coding. I also only had to make one fix to a CPython standard library module to get the code to work - in this case, I had to fix codeop.py to not pass the DONT_IMPLY_DEDENT flag to the builtin compile() method. This flag is both undocumented and implemented in codeop.py in a most foul way - I've opened Python bug 1612012 about it. The fixed version of codeop.py is now in the SVN version of IPCE.

I started porting popen2 as well, that's not finished yet (but will be this week). For the moment, I'm just using os.spawnl() directly inside IronKant for spawning external programs.

The longer Windows.Forms example in the talk is from Michael Foord's excellent tutorial on the subject. If you're at all interested in producing native GUIs on both Windows and Unix, you should definitely check the tutorial out. And buy his book about IronPython when it's done!

Labels: , ,