View Single Post
Posts: 42 | Thanked: 16 times | Joined on Oct 2007 @ Nottingham
#13
If you are happy with a command line interface, I use a python script, it's quite fast. Has absolutely no frills.

If you can follow these instructions, you would not need my script, if you can't well please don't even try. The only pre-requisite that I am aware of needing is standard package: maemo-python-device-env

Directory /media/mmc1/podcasts/ is hardcoded (nice!) as the working and configuration directory.

For each podcast subscription, create a file named podcastx.url containing one line, which is the RSS, XML URL. eg:
YouLookNiceToday.url
Code:
http://feeds.feedburner.com/YouLookNiceToday?format=xml
When the script is run, it will download the latest RSS feed, and create an xml file in the same directory. It should then compare the feed with an earlier version and download the latest, newest linked media file to a subdirectory. The url, xml and directory all share the same name, bar the extension.

Then you're on your own with file manager, media player or mplayer to find and play the podcasts.

This is the first version of something like a gpodder competitor but as it works for me, I stopped developing.

ppodder.py:
Code:
#!/usr/bin/env python

import sys

from xml.sax import make_parser, handler
from xml.sax.saxutils import DefaultHandler

from email.Utils import parsedate
import time
#
import os
import urllib

# --- The ContentHandler

class RSSHandler(DefaultHandler):

    def __init__(self, pc):
        self._pc=pc
        self._text = ""
        self._parent = None
        self._title = None
        self._link = None
        self._encURL=None
        self._date = None
        self._xml_stack = ['Root']
        self._pc._parseFail=False

    def ReadIn(self, xml):
        self._xml=xml
        parser=make_parser()
        parser.setContentHandler(self)
        try:
           parser.parse(self._xml)
        except:
           print "XML Parse fail"
           self._pc._parseFail=True

    # ContentHandler methods
    def startElement(self, name, attrs):
        self._xml_stack.append(name)
        self._text = ""
        if name=="enclosure" and self._xml_stack[-2]=="item":
          self._encURL=attrs.get("url")
        

    def endElement(self, name):
        self._xml_stack.pop()
        #self._parent=self._xml_stack[len(self._xml_stack)-1]
        self._parent=self._xml_stack[-1]
        if self._parent == "channel":
            if name == "title":
		self._pc._Title=self._text
            elif name == "description":
	        self._pc._Desc=self._text
            elif name == "lastBuildDate":
                self._pc._RSSDate=parsedate(self._text)
            elif name == "pubDate":
                self._pc._RSSDate=parsedate(self._text)

        elif self._parent == "item":
            if name == "title":
                self._title = self._text
            elif name == "link":
                self._link = self._text
            elif name == "pubDate":
                self._date = parsedate(self._text)
            elif name == "description":
                self._descr = self._text

        if name == "item":
            self._pc._Episodes.append([self._encURL, self._title,self._date])
            self._title = None
	    self._date=None
            self._link = None
            self._descr = ""

    def characters(self, content):
        self._text = self._text + content

class PodcastClass():
    def __init__(self):
        self._Title=""
        self._Episodes=[]
        self._Desc=""
        self._RSSDate=None
        self._machineName=""
        self._prevRSSDate=None
        self._parseFail=False

    def upDated(self):
        if self._RSSDate==None:
          for ee in self._Episodes:
            if ee[2]>self._RSSDate or self._RSSDate==None:
              self._RSSDate=ee[2]
        return self._RSSDate

    def newEpisodes(self):
        g=[]
        if self._prevRSSDate==None:
          g=self._Episodes
        else:
          for ee in self._Episodes:
            if ee[2]>self._prevRSSDate:
              g.append(ee)
        return g
          
    def shortName(self):                                                   
        if self._machineName=="":                                           
           for c in self._Title.lower():                                                               
             if c.isalnum():
                self._machineName=self._machineName+c 
        return self._machineName

    def newest(self):
        re=None
        for gg in self.newEpisodes():
          if re==None or re[2]<gg[2]:
            re=gg

        return re
        

def myReportHook(count, blockSize, totalSize):
    print count, count*blockSize, totalSize, int(100 *  count*blockSize/totalSize),"\r",


def uncracklink(urlfile):
    f=open(urlfile,"r")
    u=f.readline()                                                                                                                
    f.close()
    return u

#---+----+---+---+

sDir="/media/mmc1/podcasts/"

d=os.listdir(sDir)
for f in d:
   if f.lower().endswith(".url"):
     print "Reading file", f.lower()
     sPodCast=f[:-4]
     sURL=uncracklink(sDir+"/"+f)
     if not os.path.isdir(sDir+"/"+sPodCast):
       os.mkdir(sDir+"/"+sPodCast)
       print "NB: creating podcast directory"

     prevPC=PodcastClass()
     if sPodCast+".xml" in d: 
       print "Reading previous XML"
       prevPCr=RSSHandler(prevPC)
       prevPCr.ReadIn(sDir+"/"+sPodCast+".xml") 
       if prevPC.upDated()!=None:
         print "Podcast", prevPC._Title, time.strftime("%Y-%m-%d %H:%M:%S",prevPC.upDated())
     else:
       print "No previous XML"

     print "Downloading newest RSS XML"
     try:
       x=urllib.urlretrieve(sURL,sDir+"/"+sPodCast+".1.xml",myReportHook)
     except urllib.ContentTooShortError:
       print "retrieve fail"

     if x[0]!=None:   
       newPC=PodcastClass()
       newPCr=RSSHandler(newPC)
       newPCr.ReadIn(x[0])
       newPC._prevRSSDate=prevPC.upDated()
       if newPC.upDated()!=None:
         print "retrieved", newPC._Title, time.strftime("%Y-%m-%d %H:%M:%S",newPC.upDated())
     
       PCtoget=newPC.newest()
       if PCtoget!=None and len(PCtoget[0])>0: 
         print "New episode:", PCtoget[1] 
         print "url:", len(PCtoget[0])
         try:
           x2=urllib.urlretrieve(PCtoget[0],sDir+"/"+sPodCast+"/"+PCtoget[0].split("/")[-1],myReportHook)
         except urllib.ContentTooShortError:
           print "retrieve fail"
         else:
           os.rename(x[0],sDir+"/"+sPodCast+".xml")

       if os.path.exists(x[0]):
         os.unlink(x[0])
It is quick and dirty, doesn't have a GUI, or multi-thread, but deals with the feeds I need. Feedback, interest, questions welcome.

To run the script from a menu, I use:
/usr/share/applications/hildon/ppodder.desktop
Code:
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Name=PPodder
Comment=myPPodder
Exec=/home/user/ppodder.py
Icon=qgn_list_rss
Type=Application
 

The Following User Says Thank You to ptaffs For This Useful Post: