Peter's Blog

Redefining the Impossible

Items filed under mp3


Much as I hate flash, it is a nice way to embed a sound or video player in a page. Here's how I did it in rails using the JW FLV Media Player. I added the following to my view:

   1  <script type="text/javascript" src="/javascripts/swfobject.js"></script>
   2  
   3  <% for oRssItem in @rssitems %>
   4    <hr/>
   5    <h3><%= oRssItem.title %></h3>
   6    <p><%= oRssItem.description %></p>
   7    <table width="470">
   8      <tr>
   9         <td wIdth="50%"><%= oRssItem.created.strftime( "%m %B %y") %></td>
  10         <td align="right"><%= link_to "Download", "/#{ oRssItem.filename}" %></td>
  11      </tr>
  12    </table>
  13  
  14    <div id="player<%=oRssItem.id%>">This text will be replaced</div>
  15  
  16    <script type="text/javascript">
  17      var so = new SWFObject('/mediaplayer.swf','mpl','470','20','8');
  18      so.addParam('allowscriptaccess','always');
  19      so.addParam('allowfullscreen','true');
  20      so.addVariable('width','470');
  21      so.addVariable('height','20');
  22      so.addVariable('file','/<%= oRssItem.filename%>');
  23      so.write('player<%=oRssItem.id%>');
  24    </script>
  25  <% end %>

This generates a page full of podcast entries, each with a little media player thing so you can listen to them easily. This does mp3 files but it can handle video too.

I am aware that the swfobject.js would be better loaded in the html header.

Here's a demo: I don't know if this will work in the rss feed (UPDATE: no!) so bear with me and please be gentle on my bandwidth, it's quite a catchy tune:

Oops, no flash? Javascript broken? Works for me.

The main reason I am blogging this is because it only needs a change to a view file and installation of two files in the /public directory (the player and a javascript file). Since view files are awkward to comment legibly I decided to document it all here so I can find it again.


Filed under: mp3 rails ruby

2 Comments

Bought myself a new PDA, an HP Ipaq rx1950 Pocketpc. It was a bit of an impulse buy, a bit of retail therapy I felt in need of a few weeks back. The model I bought was essentially the cheapest I could get locally that had integrated wifi.

I used to use a palm tungsten T2 but it's digitiser does not work properly, it takes about five goes to get past the initial calibration and it's downhill from there. I still had a hankering for a pda, a portable notetaking device to serve as a backup for my failing memory.

Following my experiences with the palm and bluetooth I decided that wifi was pretty much essential, bluetooth was slow and the bluetooth stacks in windows complex and buggy.

The rx1950 runs Windows Mobile 2005, the latest name for Windows CE/pocketpc. It is a stylus driven thing, not my first preference but keyboard models are more expensive and have smaller screens.

Bullet point review:

  • first impression when I took it out the box was how light it is, much lighter than my old palm. It's fairly thin as well, maybe half an inch thick. It would fit better in a trouser pocket if not for the carry case that comes with it which is almost as thick again.
  • nice solid build quality: HP after all.
  • stylus has a tendency to fall out: I put it in the carrying case the wrong way round to restrain it or I would certainly lose it.
  • no charging cradle: comes with a USB cable and a mains adapter that plugs into the USB cable: rather awkward and fiddly and annoying that it cannot charge from the USB port. There are aftermarket USB cables available that will charge it.
  • synchronises with the pc using activesync and I was amazed to discover that it won't sync over the wifi. Apparently microsoft decided it was a security hole and they couldn't think of a way to plug it so they just removed the feature. This leaves USB or infra-red so I'm using USB when I feel the need. Many pocketpc apps are available as cab files that can be downloaded directly to the device over the wifi and installed. Some producers are not enlightened to this and ship apps with windows installers that use activesync and hence can only be installed at home base.
  • the device has 32M of 'program memory' for running programs data and this isn't really enough. The symptoms of this seem to be the o/s terminating apps that are not in the foreground. If you have, say, windows media player playing something then you can only run maybe one more program before something gets randomly zapped. Microsoft have tried to create a paradigm where you don't have separate applications but flip between different modes without worrying about having to close apps down. Apps are closed automatically by the OS as memory runs low and should be designed to save their state such that when they are reopened they are in the same state as when they were shut down. Unfortunately it looks like developers use standard development techniques and applications being suddenly terminated by the OS leaves the user high and dry.
  • it has another 32M for storing programs but I bought a 1G SD card and I put everything in that.
  • the screen is just about big enough. It is ok for reading without scrolling too much. For most web browsing it is awful unless I use http://skweezercom or google mobile to strip out any fancy stuff.
  • the character recognisers that come with it are not much good: the handwriting recognition (transcriber) is slow and inaccurate. I am using something called Tengo which is a bit like predictive text on a phone so involves hitting only six big buttons. It has some clever design features and there is something about it that is kinda fun. I am writing this review with it so you may spot predictive-text style wrong word errors.
  • a frequently used feature is the reset button: windows mobile is a typical windows o/s and isn't sophisticated enough to offer robust task management. Applications can lock it hard and banging on an unresponsive plastic screen is particularly fruitless.
  • it has speaker and microphone. The speaker is just about loud enough to listen to podcasts. I haven't tried skype on it, the skype site doesn't list the rx1950 as supported and the cpu may not be fast enough.
  • has 3.5mm audio jack and the sound to my ears was pretty good. It is a good mp3 player.
  • battery life is very good, one charge gives a good day of use.

As a device for browsing rss feeds while watching tv, taking notes, listening to music, watching videos or whatever it is just fine. It is more convenient than a laptop and I can carry it in my pocket so is far more mobile. I can see that it is a quirky platform and will probably have been killed off by mobile phones and mp3 players within two years time.

I'll write about the applications I have installed in it some other time.


7 Comments

I decided to update my python podcast script ipydder.py. Based on the comments for the old version I ditched the horrible sax parser and used the lovely Beautiful Soup. This has simplified it a great deal, 49 lines of code if I delete all the comments.

   1  #!/usr/bin/python
   2  #
   3  # ipydder mark 2
   4  # Download podcasts
   5  #
   6  
   7  import BeautifulSoup
   8  import os
   9  
  10  def GetPodcast( strFeed, strTargetDir):
  11      #
  12      # Get the rss file.
  13      #
  14      strRSS = os.popen4( 'wget -q -O - "%s"' % strFeed)[1].read()
  15  
  16      #
  17      # Parsing it.
  18      #
  19      oSoup = BeautifulSoup.BeautifulStoneSoup()
  20      oSoup.feed( strRSS)
  21  
  22      #
  23      # Go through the items in the feed.
  24      #
  25      for oItem in oSoup( 'item'):
  26          #
  27          # Look for enclosures in the item.
  28          #
  29          strUrl = oItem.enclosure[ 'url']
  30          if not strUrl:
  31              #
  32              # If no enclosures, see if there is a link
  33              #
  34              strUrl = oItem.link.string
  35  
  36          if strUrl:
  37              #
  38              # Remove whitespace.
  39              #
  40              strUrl = strUrl.strip()
  41  
  42              #
  43              # Look for mp3 enclosures
  44              #
  45              if strUrl[-4:].lower() == '.mp3':
  46                  #
  47                  # Ok there is an mp3 file to be had
  48                  #
  49                  # Determine unique id for this item
  50                  #
  51                  strGuid = oItem.guid.string
  52                  if not strGuid:
  53                      #
  54                      # No guid, lets use the file url.
  55                      # Presumably each file name is unique.
  56                      #
  57                      strGuid = strUrl
  58  
  59                  #
  60                  # See if guid has already been downloaded by searching the database
  61                  #
  62                  strDBFile = strTargetDir + '/.ipydder.db'
  63  
  64                  try:
  65                      oDB = [ strLine.strip() for strLine in open( strDBFile).readlines()]
  66                  except(IOError):
  67                      oDB = []
  68  
  69                  if not strGuid in oDB:
  70                      #
  71                      # try to download the file
  72                      # Use wget as a more robust way to download big mp3 files
  73                      #
  74                      print 'Downloading %s' % strUrl
  75  
  76                      os.chdir( strTargetDir)
  77                      strResults = os.popen4( 'wget -nv "%s"' % strUrl)[1].read()
  78  
  79                      strFileName = strTargetDir + os.path.basename( strUrl)
  80                      print 'Downloaded file %s' % strFileName
  81                      print strResults
  82  
  83                      #
  84                      # Remember that the file has been processed, don't download it again.
  85                      #
  86                      oDB.append( strGuid)
  87                      open( strDBFile, 'wt').write( "\n".join( oDB))
  88  
  89  strHomeDir = os.environ['HOME'] + '/'
  90  
  91  GetPodcast( "http://radio.weblogs.com/0001014/categories/dailySourceCode/rss.xml",
  92                  strHomeDir + "Podcasts/DailySourceCode")
  93  GetPodcast( "http://www.morningcoffeenotes.com/rss.xml",
  94                  strHomeDir + "Podcasts/CoffeeNotes")

Filed under: mp3 python rss

1 Comment

I've still got to wait till August before I can update my phone to one that plays mp3's. When I do I have decided that this is going to be my ringtone. It makes crazy frog look cool. I've saved the file in case the link dies in 6 months time.


Filed under: mp3 phone

Add a comment

I like to listen to the Daily Source Code podcast while rowing. I've always liked talk radio and this is like talk radio with F words.

The podcast files are about 20Megs and they take a few minutes to download on my 750k broadband connection. I wanted to have my Ubuntu box download them automatically so they would be ready for me (as was the original vision of podcasting).

I decided to knock up a python script to do it for me as I didn't want a gui tool and the only other script I found was written in ruby :sick:. This script downloads the rss feed from the podcasting site, looking for mp3 files. Any that it finds it will download. It remembers which files it has downloaded so you can listen to them and delete them and they won't be downloaded again. It doesn't play the files, thats done by Totem.

Other podcasts can be added easily enough.

   1  #
   2  # Download podcasts
   3  #
   4  import xml.parsers.expat
   5  import re
   6  import os
   7  import traceback
   8  import sys
   9  
  10  class FeedParser:
  11    # 3 handler functions
  12    def __init__( self):
  13      self.oElementStack = []
  14      self.bItem = False
  15      self.oItem = None
  16  
  17    def Parse( self, strFeed, strRETitle, strTargetDir):
  18      #
  19      # Parse feed, given url and regular expression describing podcast title.
  20      #
  21      self.oRETitle = re.compile( strRETitle)
  22      self.strTargetDir = strTargetDir
  23  
  24    #
  25    # Open database to remember what files have been dealt with
  26    #
  27      try:
  28        self.oDB = open( strTargetDir + '.pypodder.db').read().split( '\n')
  29      except:
  30        self.oDB = []
  31  
  32      p = xml.parsers.expat.ParserCreate()
  33  
  34      p.StartElementHandler = self.start_element
  35      p.EndElementHandler = self.end_element
  36      p.CharacterDataHandler = self.char_data
  37  
  38      #
  39      # Read feeed using wget as it is robust.
  40      #
  41      strRSS = os.popen4( 'wget -q -O - "%s"' % strFeed)[1].read()
  42  #    print strRSS
  43      p.Parse( strRSS)
  44  
  45    def start_element(self, name, attrs):
  46      #
  47      # Put element on element stack alog with empty data array
  48      #
  49      self.oElementStack.append( [name, []])
  50  
  51      #
  52      # If this is the start of an item then reset the item contents
  53      #
  54      if name == 'item':
  55        self.bItem = True
  56        self.oItem = {}
  57      elif name == 'enclosure':
  58        #
  59        # If element is an enclosure then get the url
  60        #
  61        strUrl = attrs.get( 'url')
  62        if strUrl:
  63          if self.bItem:
  64            self.oItem['enclosure']=strUrl
  65  
  66    def end_element(self, name):
  67      #
  68      # Pop complete element from the element stack
  69      #
  70      strElement, strData = self.oElementStack.pop()
  71  
  72      #
  73      # Check for sillies
  74      #
  75      if strElement != name:
  76        raise "Element mismatch: %s != %s" % (name, strElement)
  77  
  78      if strElement != 'item':
  79        #
  80        # Get data associated with element and store in item
  81        #
  82        if self.bItem:
  83          strData = "".join( strData).strip()
  84  
  85          self.oItem[strElement] = strData
  86      else:
  87        #
  88        # Item is complete.
  89        # See if item title matches the re provided
  90        #
  91        if self.oRETitle.match( self.oItem.get( 'title', '').encode()):
  92          #
  93          # Try to get url of mp3 file
  94          #
  95          strUrl = self.oItem.get( 'enclosure')
  96          if not strUrl:
  97            #
  98            # No enclosure, try the 'link' field.
  99            #
 100            strUrl = self.oItem.get( 'link', '').encode()
 101  
 102          if strUrl and strUrl[-4:].lower() == '.mp3':
 103            #
 104            # See if item has a guid
 105            #
 106            strGuid = self.oItem.get( 'guid').encode()
 107            if not strGuid:
 108              #
 109              # If no guid then use the link url as a guid
 110              #
 111              strGuid = strUrl
 112  
 113            #
 114            # See if guid has already been processed in the database
 115            #
 116            if not strGuid in self.oDB:
 117              #
 118              # try to download the file
 119              # Use wget as a more robust way to download big mp3 files
 120              #
 121              os.chdir( self.strTargetDir)
 122              strResults = os.popen4( 'wget -q "%s"' % strUrl)[1].read()
 123  
 124              strFileName = self.strTargetDir + os.path.basename( strUrl)
 125              print 'Downloaded file %s' % strFileName
 126              print strResults
 127  
 128              #
 129              # Remember that the file has been processed, don't download it again.
 130              #
 131              self.oDB.append( strGuid)
 132              open( self.strTargetDir + '.pypodder.db', 'wt').write( "\n".join( self.oDB))
 133  
 134        self.oItem = None
 135        self.bItem = False
 136  
 137    def char_data(self, data):
 138      #
 139      # Append data to element.
 140      #
 141      self.oElementStack[-1][1].append( data)
 142  
 143  FeedParser().Parse( "http://radio.weblogs.com/0001014/categories/dailySourceCode/rss.xml",
 144                         "Daily Source Code for.*", "/home/peter/DailySourceCode/")

I've set up cron to do this for me at 5:11pm every day, just before I get home from work for a row before eating (I don't recommend a half hour rowing with a full stomach).

crontab -e

11 17 * * * /usr/bin/python /home/peter/pypodder.py

Update: I have altered the script above. There are three main changes:

  • It now uses wget to do the downloading as it is more robust than using urllib2 which had a tendancy to timeout.
  • It is now using the proper Daily Source Code RSS feed, rather than Adam Curry's Weblog as the latter sometimes got the file names wrong.
  • The history of what has been downloaded is now a simple text file, making it easy to delete lines if necessary.

Filed under: mp3 python rss ubuntu

4 Comments

Upgraded to latest iTunes with intention of buying wife some Celine Dion and myself some Korn. However, their server seems to be overloaded this evening and won't let me register.

Anyway, decided to let Quicktime become the default mp3 player. One of my gripes with using Windows Media Player to play podcasts, particularly the Daily Source Code (which I listen to while rowing) is that I have to wait for the entire 20M or so file to download before it starts playing, which takes a couple of minutes and is a bind: I can't start rowing.

I had been thinking that surely a decent player would be able to start playing the audio stream while the file was still downloading and, sure enough, I tried it with QuickTime 6 and it works! No need to wait. Maybe Windows Media Player doesn't do this as part of an evil plan to discredit mp3 files.


Filed under: mp3 windows

Add a comment

My wife wanted me to rip a CD to put some mp3 files on her Creative MuVo flash player. I haven't done this since I got my new pc and wasn't sure I had a ripper. I went through a few options:

  • Looked at RealOne. I only use Real to listen to BBC Radio. This wouldn't rip mp3's unless I upgraded it to the premium version.
  • Decided Ubuntu must have an mp3 ripper. Fired up the Ubuntu box, looked in the applications menu and found something called Juicer. This rips Ogg and a couple of other things but the mp3 option was greyed out. Search on web to find awkward machinations required to download mp3 codec, register it etc which I couldn't be bothered with.
  • On a hunch, tried the antithesis of Ubuntu, Windows Media Player. Yes, they done it again, it ripped the CD in about two minutes, It tried to nag me to use wma but I insisted. I copied the files to the MuVo via USB Mass Storage and it Just Worked.

I find it odd that something as basic in 2005 as ripping a CD to mp3 is not supported by Ubuntu in a straightforward way, via the applications menu.


Filed under: mp3 ubuntu windows

14 Comments

My wife has had her phone for a year so down to the O2 shop for an upgrade. She fancied a change from Nokia and liked the colour of the Motorola V600 but unfortunately that is discontinued, it has been replaced by the V547 so I got her one of those. For free smile. It has:

  • Clamshell design
  • Bluetooth
  • Big clear screen
  • Camera: slightly better than nokia cameras (e.g. my 6610i, wife's old 7250i) don't look quite so much like they were taken through the bottom of a dirty jam jar. Still no match for a digital camera.
  • MP3 ringtones! Cool, was able to download the crazy frog which has everyone in stitches.
  • Good build quality
  • The keyboard has a nicer feel than the Nokias which are a bit cheap and clicky.
  • The UI is rather like my late lamented Sony-ericsson T68i: fiddly and annoying.
  • Good predictive text: it quickly learns that you want to type 'am home' more often than 'an good'.

With the free phone I got 25% off a Jabra BT200 FreeSpeak Bluetooth Headset and a car charger for £5.

The Jabra headset Just Worked with the phone and it is indeed cool. My wife was delighted with it, she wants me to ring her whenever she goes out so she can pose with it. I set it up to voice dial and told her she can leave the phone in her handbag.

I wanted to try the headset with Skype so I tried reinstalling my existing bluetooth USB dongles:

Smart Modular Technologies
I downloaded their latest blueopal drivers and installed them. On first installation the Audio drivers and some other bits failed to install. It did manage to install an OBEX network driver and I was able to copy files to and from the phone. This is how I installed the crazy frog .mp3 file which I downloaded above. (Am I missing something? Was I supposed to pay for it?). I tried reinstalling the blueopal drivers to get headset support and was rewarded with my first every BSOD under windows XP. The setup program kept trying to reinstall, giving more BSOD's so I had to uninstall it manually by deleting files and picking the nasty bits out of the registry by hand.
MicroStar International (MSI) dongle
Luckily I had an MSI dongle as well. I downloaded the latest SP1 drivers for this (carefully avoiding the XP SP2 version that uses the new Microsoft USB stack but that not support a headset, not until MS get into the VOIP business) and installed them with no problems.

The headset gives new microphone and audio devices so I redirected everything to the headset and again it Just Worked. Skype worked ok and talking to someone in the same room you can hear a delay of about a second between them speaking and it coming through the headset. Ragarding range, the MSI dongle is supposed to have a 100m range and with the laptop downstairs the headset can receive anywhere in the house, although at the furthest reaches the sound gets a bit choppy. I won't try Skype over Wifi, my Wifi is too flaky.

Peter's vision of the future (well maybe not that visionary):

  • full mp3 players in cell phones. If an iPod shuffle is the size of a stick of gum, why not make the cell phone a little bit bigger for a 500M flash memory chip?
  • death of land line phones, ripped apart by mobile phones and VOIP.
  • Nokia had better pull their fingers out, the V547 makes the Nokia phones look very dull.

8 Comments

Installed new linux system on my server. Actually I intend to use it as a TV... anyway I finally decided on a distribution.

Gentoo:

  • previous distribution
  • too much hard work and nursing and random breaking

Knoppix:

  • confused as to whether it is supposed to be installed and used or just booted from live CDs as a party trick
  • worked with my TV card

Redhat:

  • the MS of the linux world. Used 7.1 yonks ago and was not impressed.

Suse:

  • Used for a long time (6.1, 6.3)
  • Slow ftp servers however many years ago
  • Ended up compiling everything as I could never find rpm's

Slackware:

  • First ever distribution I tried, years ago, from a cover disk on a magazine
  • Is it still going?

Ubuntu:

  • related to Gnoppix and Debian
  • very hard to remember the spelling. I think of it as umbongo. Umbongo, Umbongo, they drink it in the congo.
  • tried live CD (600M, 2 hour bittorrent download) and PC went into a constant rebooting loop
  • tried installation CD (600M, 2 hour bittorrent download) and PC went into a constant rebooting loop
  • don't remember a linux installation ever failing so bad.
  • it's boot screen just shows Ubuntu, a logo and a progress bar: I want boot logs.

Finally went back to Debian Woody:

  • It's low level enough for me without the Gentoo level of hastle and constant breaking.
  • I like apt: want to try something? It's installed in minutes.

Filed under: gentoo knoppix linux mp3 ubuntu

2 Comments

Had my first taste of a podcast. This is a kind of audio blog. The one I listened to was this. It comes across as being like a techy radio show, talking about mobile phones and the like. It was kind of interesting to listen to while I was on the rowing machine. I just downloaded the mp3 file and played it on the latest app to grab the association with mp3 files, Real Player in this case.

I could set up an aggregator capable of downloading these files as they appear and listen to them all the time but my rowing time is about the only time I have for this kind of thing. Rowing is like ironing, I need something interesting to watch on tv or listen to that will take my mind off my suffering.

Don't worry, I won't be generating podcasts any time soon.


Filed under: blog mp3 rowing

1 Comment