Archive for August, 2008

Blog Updates

After heavily updating some things on my blog, someone on my shared host server caused the server to die repeatedly. My blog was pretty much gone all of yesterday and part of the day before. Hopefully it’s all been resolved. Anyway, I’ve recently added a Contact page, updated the About page, added OpenID login option to commenting, added option to have comment followups emailed, added syntax highlighting for code chunks, and made some theme updates to accommodate all these changes. And I added avatars to the comments. So I’ve made a lot of updates, but I haven’t really tested everything. Let me know if there are any problems.

WordPress Upgrade Script

Even though the WordPress upgrade is easy, it’s troublesome. So I wrote a script to do it for me. Yep. There’s lots of these out there. And a lot of hosts (including mine) have a one-click install/update thing. But for some reason, I decided to write my own script. In python. Got to use a bunch of modules I’ve never used before, so it was a good experience.

How to Use

Run this script from the directory that contains your wordpress directory, on your server. I think it requires Python version 2.3. I ran it with 2.3.5. Use python -V to check the version. There’s two methods to run it.

With Prompts

1: Be prompted to push the Enter key to continue at each major step. Nice for the first time.

python wp-upgrade.py

Example output:

python ../src/wp-upgrade/wp-upgrade.py 
Current WordPress Version: '2.5'
Newest WordPress Version:  2.6.1
Downloading wordpress-2.6.1.tar.gz ...
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
Create working wordpress directory... 
			[[Press Enter to Continue]]
 
Update Wordpress root contents...  
			[[Press Enter to Continue]]
 
'/tmp/tmprpJTKu/wordpress' -> 'wordpress.working'
wp-trackback.php,  wp-config-sample.php,  wp-settings.php,  wp-rss2.php,  readme.html,  index.php,  wp-links-opml.php,  wp-pass.php,  wp-feed.php,  wp-register.php,  wp-rdf.php,  wp-rss.php,  wp-commentsrss2.php,  license.txt,  wp-comments-post.php,  wp-blog-header.php,  wp-load.php,  wp-mail.php,  wp-atom.php,  wp-cron.php,  wp-app.php,  xmlrpc.php,  wp-login.php,  
Replace wp-admin and wp-includes... 
			[[Press Enter to Continue]]
 
 
Update default themes and plugins...  
			[[Press Enter to Continue]]
 
'/tmp/tmprpJTKu/wordpress/wp-content' -> 'wordpress.working/wp-content'
index.php,  
'/tmp/tmprpJTKu/wordpress/wp-content/plugins' -> 'wordpress.working/wp-content/plugins'
akismet,  hello.php,  
'/tmp/tmprpJTKu/wordpress/wp-content/themes' -> 'wordpress.working/wp-content/themes'
default,  classic,  
 
Backup original, Rename working....
			[[Press Enter to Continue]]
 
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
### VISIT 'http://stevenbrown.ca/blog/wordpress/wp-admin/upgrade.php' in your browser. ###
After that, you're All Done!
Go re-enable all your plugins and make sure everything works.
If you need to, you can always roll back by renaming the backup to 'wordpress'.
 
 
			[[Press Enter to Continue]]

Without Prompts

2. Do everything without a prompt. Do this by passing the -q option. The -q is for quiet and prints the same messages, but doesn’t wait for the user to press Enter. Blasts through the whole upgrade in one step.

python wp-upgrade.py -q

Example output would be the same as the above, minus the “[[Push Enter to Continue]]” bits.

What’s it do?

If you look at the above output, which is from my own site, you can see what it does. It will compare your installed wordpress version and to the latest available from http://www.wordpress.org. If your version is older, it will download the new one, extract it, perform the appropriate steps to update the old one. Note that the default themes and plugins will be overwritten, which is fine as long as you didn’t customize them. After it’s done, your wordpress directory should be up-to-date (you just have to visit the upgrade page), and you should have a wordpress 2.5 backup containing the directory as it was before running the script (and 2.5 would be the appropriate version). Also, there’s two variables you will (probably) want to customize: wpsite and wpdir. That’s it, basically.

Download

Browse the source and download the script here.

python treeview toggle

Had this post sitting around. Seems finished. May be helpful to someone. /me waves Wand of Publish +1

I was confused when I was playing around with this basic concept: adding a toggle widget to the treeview in pygtk. The reason for this is an inconsistency in the api model – or at least how I perceived it. With a regular toggle button, you create the widget and can manipulate it once it is drawn. The checkmark is toggled and the “toggled” signal is emitted. I only connect a signal handler to the toggled signal after. However, following this same logic, I created a list with a column of toggle widgets and tried clicking them… but nothing happened. The problem here was the toggled value was linked to the list’s data, and the data wasn’t actually changing. Even though the toggle signal was being emitted, the checkmark wasn’t being toggled because the data wasn’t changing, so I thought there was a problem with my code and the signal wasn’t being emitted. But actually, it would make more sense if it was a “clicked” signal that was being emitted, not the “toggled” signal.

Example source code:

#!/usr/bin/env python
 
# example basictreeviewtoggle.py
 
import pygtk
pygtk.require('2.0')
import gtk
import gobject
 
class BasicTreeViewToggleExample:
 
    # close the window and quit
    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False
 
    def column_toggled(self, cell, path, model):
        # get toggled iter, and value at column 0
        iter = model.get_iter((int(path),))
        val = model.get_value(iter, 0)
 
        # toggle the value
        val = not val
 
        # set new value
        model.set(iter, 0, val)
 
 
    def __init__(self):
        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("Basic TreeView Toggle Example")
        self.window.set_size_request(200, 200)
        self.window.connect("delete_event", self.delete_event)
 
        # create a ListStore with two columns to use as the model
        self.model = gtk.ListStore(gobject.TYPE_BOOLEAN, str)
 
        # create some list items
        for item in range(5):
            self.model.append([False, 'item %i' % item])
 
        # create the TreeView using the model
        self.view = gtk.TreeView(self.model)
 
        # create a CellRendererText to render the data
        self.cellrenderer_text = gtk.CellRendererText()
        self.cellrenderer_toggle = gtk.CellRendererToggle()
        self.cellrenderer_toggle.connect('toggled', self.column_toggled, self.model)
 
        # create the TreeViewColumns to display the data
        self.tvcolumntext = gtk.TreeViewColumn('TreeViewColumn 1')
        self.tvcolumntoggle = gtk.TreeViewColumn('tog', self.cellrenderer_toggle, active=0)
 
        # add the TreeViewColumns to the TreeView
        self.view.append_column(self.tvcolumntoggle)
        self.view.append_column(self.tvcolumntext)
 
 
 
 
        # add the cell to the tvcolumn and allow it to expand
        self.tvcolumntoggle.pack_start(self.cellrenderer_toggle, False)
        self.tvcolumntext.pack_start(self.cellrenderer_text, True)
 
 
        # set the cell "text" attribute to column 0 - retrieve text
        # from that column in treestore
        self.tvcolumntext.add_attribute(self.cellrenderer_text, 'text', 1)
 
 
 
        # make it searchable
        self.view.set_search_column(1)
 
        # Allow sorting on the column
        self.tvcolumntext.set_sort_column_id(1)
 
        # Allow drag and drop reordering of rows
        self.view.set_reorderable(True)
 
        self.sw = gtk.ScrolledWindow()
        self.sw.add(self.view)
        self.window.add(self.sw)
 
        self.window.show_all()
 
def main():
    gtk.main()
 
if __name__ == "__main__":
    tvexample = BasicTreeViewToggleExample()
    main()

Creating a DVD Slideshow in Linux

For my brother’s wedding, about a week ago, my sister wanted to do a slideshow for them. She’s done this before and she’s known for spending lots of time making very nice, emotional slideshows with carefully chosen pictures and music. Previously, she would count in her head while manually switch the slides with a traditional projector. (We have a lot of great family photos that are only on slides.) Anyway, she figured she’d use computers this time around and my assistance was “enlisted.” I kept thinking, “If only I had a Mac, I’m sure this would be easy….” But it turns out there’s a reasonable command-line program available on Linux that is just a little cumbersome (mostly because it’s command-line tool for something that really needs to be visual) – but works quite well: dvd-slideshow. I’m going to go over what I did, mention some quirks and how to work around them.

First, install dvd-slideshow (a set of command-line tools).

sudo aptitude install dvd-slideshow

You may want to get the latest version from the webpage and manually install that.

Update: While writing this, I have since discovered “slcreator” which looks like it would fill in the glaringly absent graphical component of dvd-slideshow. Though it hasn’t been updated for quite a long time…. it’s definitely worth investigating before going through the manual process yourself.

Step 1: Organize your digitized photos within a directory

Since my sister was the creative force behind this, she needed to see the photos as she was deciding on the order. Nautilus thumbnails were good enough, so I simply showed her how to rename files and made suggestions for organizing them by name (like naming a photo “12a.jpg” if you want the photo to be in between “12.jpg” and “13.jpg”). This worked in Nautilus, but in the next step, the ordering would be changed to 12a.jpg, 12.jpg, 13.jpg – which is probably a bug in dir2slideshow. (You could work around this by always using a single letter after the number.)

Step 2: Generate input file from images directory and customize

dir2slideshow -o output_directory -t seconds_per_picture -c crossfade_seconds images_directory

This will output a text file in the output_directory that contains all the images in the images_directory with specified transition and duration times. The order of the pictures should be how it is listed by name in your file browser, minus the bug I mentioned earlier. You can manually edit this file and then pass it to dvd-slideshow.

Multiple Directories:
My sister had arranged photos in multiple directories, each consisting of a theme (childhood, Halloween, travel, etc) and a specific song to go with it. So I just generated multiple input files with appropriate names, worked on individual sections, and eventually copied them all into a master input file keeping the desired order.

Adding Music and Silence:
Another bug I encountered was getting music to fade out at the correct time. In the input file, the format for adding music is this: audiofile:track:effect1:effect1_params:effect2:effect2_params . So I had my_sad_song.mp3:1:fadein:0:fadeout:5 saying I wanted it to spend 5 seconds fading out. Additionally, I wanted about 10 seconds of silence at the very end. Your are supposedly able to specify silence:duration_in_seconds but at the end of the slideshow, it wasn’t forcing the song to fade out in time to include that amount of silence – it seemed to be ignoring it at the end if there was no more photos. I got around this by creating a small file of silence, silence.wav, and using that instead of the built-in silence option.

Nice looking fonts
Another quirk I encountered was terrible looking fonts with the built-in title:duration:thought_provoking_title. I didn’t want to spend too long looking at the cause of this, so I just created some title images in the Gimp.

Step 3: Generate the Slideshow

dvd-slideshow -mp2 -nomenu -o tmp/working -f tmp/ALL.txt

The mp2 option is required to avoid an error message and has worked on all DVD players I’ve heard of, so far. The nomenu option is for creating a DVD with no menu – I just wanted it to start playing the slideshow when the disc is inserted into the player. The o option specifies the output directory and the f option specifies the input file created earlier. Once this finishes (it might take a while) you should have a DVD .vob (MPEG2) file and an xml file in the output directory.

Debugging:
I like to see how the final product will look, so I chose not to use the L (low quality) option for debugging. Instead, I created a smaller input file with specifically what I wanted to test. When I was happy with the test, I copied the changes into my master input file.

Step 4: Create the DVD Filesystem

dvd-menu -f tmp/working/ALL.xml -nomenu -mp2 -o tmp/working-dvd

This will output a folder dvd_fs in the output folder (tmp/working-dvd) containing VIDEO_TS and AUDIO_TS directories with the required files for a proper DVD.

Adding Content:
This is where you optionally add more files to the DVD. For me, I added two folders, Music containing the music used in the slideshow and Photos containing the photos used in the slideshow. A good idea would also be to add the source file and commands used to create the DVD and then you are distributing the source. 😉

Step 5: Make an ISO to burn

mkisofs -dvd-video -udf -o ~/Desktop/slideshow.iso tmp/working-dvd/dvd_fs

This creates an ISO called slideshow.iso on the desktop.

Step 6: Burn the ISO

There’s many ways to burn an ISO, but just use Nautilus: right click on the icon on your desktop and select Write to Disc…. That’s it! Test it out in your DVD player.

References

Lots more info about specific commands and useful examples can be found at the dvd-slideshow’s documentation page.

Congratulations!

Update: Added a couple photos. 🙂

My Big Brother, Aryk, is now officially married to his wife, Heather! The wedding was Sunday, August 3rd and it went extremely well. I had the honour of being best man which meant a lot to me. I even got to wear a kilt! (Along with my brother, their baby, the officiant, and the piper.) I don’t have any pictures at the moment, but I’m sure I’ll get some eventually.

me in my man skirt, testing the volume and holding my speech in left hand

I helped my sister out with creating a DVD slideshow with music to present at the wedding (via rented projector) and give to them as a gift. My sister was behind all the creative and organizational efforts, I was just needed to put it together. It turned out really great, and it was definitely worth going with the more expensive projector. But the thing I was most nervous about was the “often most anticipated” (according to various sources on the Internet) speech of the evening – the Best Man’s Speech. I was brainstorming bits here and there for quite a while, but I worked on it pretty intensely the last couple days trying to make it flow and deciding what to keep. I was even making changes 1 minute prior to getting up and doing it! ^.^ Anyway, the speech went really well – better than I could have imagined. It’s amazing; the feeling you get when you have an auditorium full of people under your control, laughing when you want them to laugh. People throughout the night kept telling me how good it was. I think I’m still floating on that high.

But what’s most important is that Aryk and Heather loved it – that makes me feel great – that I was able to contribute a little bit of success to their fantastic wedding.

Had a bit of a nasty hangover the following day… and I was incredibly tired. But it was all worth it! Again, Congratulations guys! 🙂

Playing Video from your Linux PC on your Wii

Maybe you’ve watched youtube videos on your Wii using the Internet Channel or the promo videos on the Nintendo Channel and you thought it would be cool to watch other videos from your (Linux) PC. I know I did. But I wasn’t sure if it would be possible in a reasonable quality. Since then, I’ve decided the quality was unacceptable for me… But I’ll try to quickly document what I did for others.

You basically have two options: Put a decompressed copy of your video on your SD card and watch it in the Photo Channel OR watch it streaming from your PC over your network via the Internet Channel (like youtube).

1. Playing it directly off your SD card

Instructions for how to convert the video to play in the Photo Channel can be found here:
http://icculus.org/~dolson/wii-video-conversion.html
HOWEVER, 3/4 of an hour of decent quality video will cost 1+ gigabytes, due to the format. The quality will be maintained, but unless you have a 2GB card and/or small videos, this may not be feasible. I couldn’t get my 45min (350MB originally, I think) file to fit on my 1GB SD card in the appropriate format, so I gave up on this method. I was more interested in browsing multiple files on my PC, anyways.

On to the other option….

2. Stream it from your computer

For this method, you need a few more things:

  • A home PC accessible from the network via your Wii
  • Videos you want to play need to be converted to Flash video (FLV). To do this, you will need ffmpeg.
  • sudo aptitude install ffmpeg
  • Web server running on your home PC. I’m using Apache on an Ubuntu PC.
  • sudo aptitude install apache2 apache2-utils

Most of what follows can be configured, but I’m going to try and follow what’s default in Ubuntu (if I can remember correctly).

To keep things clean, I enabled user directories. To do this, you must enable the userdir mod in apache:

sudo a2enmod userdir

What are user directories?

This is a directory (usually called “public_html”) that every user can use to publish things (like webpages) on the webserver from their home directory. For me, my home directory is /home/steve/ so my user directory is /home/steve/public_html/ . It is optional, so I have to create it if it doesn’t already exist.

mkdir ~/public_html/

When accessing these user directories via a web browser (Internet Channel), you must enter your Home PC’s IP address, followed by a tilde (~) and your username.

"http://your.pc's.ip.address/~username/"

So accessing my public_html directory is done as follows: http://192.168.0.99/~steve/ . (Note that 192.168.0.99 is a private IP address and unless your computer is set up on your local network with the same IP AND your username is “steve”, this won’t work for you. 😉 )

Test it, and make sure you’ve installed Apache and set up user directories correctly.

Flash Video Player

Now you need a compatible flash player to embed into your webpage. Wii’s Internet Channel is based on Opera, and includes Flash version…. 7?! Doh! Newer FLV players won’t work! Also, Full-screen mode isn’t possible so you want the video to be as large as possible, or to be easily zoomed in and centred – yup, it’s a pain. The best player I found for this was FLV Player, but feel free to look around for more. 😉 Now put your player of choice (I chose player_flv_maxi.swf) in public_html somewhere so that it can be included in your webpage.

Example Preparing Video

An example command for converting your video to FLV using ffmpeg:

ffmpeg -i input_video.avi -ar 22050 -b 1280 -s 320x240 output.flv

Example Webpage

An example of an html page containing a video:

< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 
	<title>Wii Video Test</title>
 
	<style type="text/css">
		body { background-color: #000; padding: 0 20px; color:#000; font: 13px/18px Arial, sans-serif; }
		a { color: #360; }
		h3 { padding-top: 20px; }
	</style>
 
</head>
<body>
 
    <object type="application/x-shockwave-flash" data="player_flv_maxi.swf" width="624" height="352">
        <param name="movie" value="player_flv.swf_maxi" />
        <param name="allowFullScreen" value="true" />
        <param name="FlashVars" value="flv=my_converted_video.flv&amp;autoload=1" />
    </object>
 
</body>
</html>

Note: both player_flv_maxi.swf and my_converted_video.flv must be in the same directory as this html page. For testing purposes, call this index.html and put it in your public_html directory.

That’s it, I think. Again, I wasn’t really satisfied with the compression of FLVs and the frame rate of bigger videos, so I ended up not using either of these two methods. I suppose a media PC, Apple TV, or PS3 or something would be better suited – none of which I have. 🙂

Related