2005-11-21 19:21:25 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# gPodder
|
|
|
|
# Copyright (c) 2005 Thomas Perl <thp@perli.net>
|
|
|
|
# Released under the GNU General Public License (GPL)
|
|
|
|
#
|
|
|
|
|
|
|
|
#
|
|
|
|
# libpodcasts.py -- data classes for gpodder
|
|
|
|
# thomas perl <thp@perli.net> 20051029
|
|
|
|
#
|
|
|
|
#
|
|
|
|
|
|
|
|
import gtk
|
|
|
|
import gobject
|
2006-03-19 18:44:47 +01:00
|
|
|
import htmlentitydefs
|
2005-11-21 19:21:25 +01:00
|
|
|
|
2006-02-04 11:37:23 +01:00
|
|
|
import libgpodder
|
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
from os.path import exists
|
|
|
|
|
2006-02-04 11:37:23 +01:00
|
|
|
from liblocdbwriter import writeLocalDB
|
|
|
|
from liblocdbreader import readLocalDB
|
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
from threading import Event
|
|
|
|
from libwget import downloadThread
|
2006-02-26 00:13:29 +01:00
|
|
|
import re
|
|
|
|
|
2005-11-21 19:21:25 +01:00
|
|
|
class podcastChannel(object):
|
2006-03-03 21:04:25 +01:00
|
|
|
"""holds data for a complete channel"""
|
2005-11-21 19:21:25 +01:00
|
|
|
def __init__( self, url = "", title = "", link = "", description = ""):
|
|
|
|
self.url = url
|
|
|
|
self.title = title
|
|
|
|
self.link = link
|
2006-02-26 00:13:29 +01:00
|
|
|
self.description = stripHtml( description)
|
2005-11-21 19:21:25 +01:00
|
|
|
self.items = []
|
2006-03-03 21:04:25 +01:00
|
|
|
self.image = None
|
|
|
|
self.shortname = None
|
|
|
|
self.downloaded = None
|
|
|
|
self.__filename = None
|
|
|
|
self.__download_dir = None
|
|
|
|
|
|
|
|
# Create all the properties
|
|
|
|
def get_filename(self):
|
|
|
|
if self.__filename == None:
|
|
|
|
self.__filename = ""
|
|
|
|
|
|
|
|
for char in self.title.lower():
|
|
|
|
if (char >= 'a' and char <= 'z') or (char >= 'A' and char <= 'Z') or (char >= '1' and char <= '9'):
|
|
|
|
self.__filename = self.__filename + char
|
|
|
|
|
|
|
|
if self.__filename == "":
|
|
|
|
self.__filename = "__unknown__"
|
|
|
|
|
|
|
|
return self.__filename
|
|
|
|
|
|
|
|
def set_filename(self, value):
|
|
|
|
self.__filename = value
|
|
|
|
|
|
|
|
filename = property(fget=get_filename,
|
|
|
|
fset=set_filename)
|
2005-11-21 19:21:25 +01:00
|
|
|
|
|
|
|
def addItem( self, item):
|
|
|
|
self.items.append( item)
|
2006-02-04 11:37:23 +01:00
|
|
|
|
|
|
|
def addDownloadedItem( self, item):
|
2006-03-24 20:08:59 +01:00
|
|
|
# no multithreaded access
|
2006-03-19 15:21:48 +01:00
|
|
|
libgpodder.getLock()
|
2006-03-04 21:45:01 +01:00
|
|
|
localdb = self.index_file
|
2006-02-04 11:37:23 +01:00
|
|
|
if libgpodder.isDebugging():
|
|
|
|
print "localdb: " + localdb
|
|
|
|
|
|
|
|
try:
|
|
|
|
locdb_reader = readLocalDB()
|
2006-02-04 18:29:17 +01:00
|
|
|
locdb_reader.parseXML( localdb)
|
2006-02-04 11:37:23 +01:00
|
|
|
self.downloaded = locdb_reader.channel
|
|
|
|
except:
|
|
|
|
print "no local db found or local db error: creating new.."
|
|
|
|
self.downloaded = podcastChannel( self.url, self.title, self.link, self.description)
|
2006-02-04 18:29:17 +01:00
|
|
|
|
2006-02-04 11:37:23 +01:00
|
|
|
self.downloaded.items.append( item)
|
|
|
|
writeLocalDB( localdb, self.downloaded)
|
2006-03-19 15:21:48 +01:00
|
|
|
libgpodder.releaseLock()
|
2005-11-21 19:21:25 +01:00
|
|
|
|
|
|
|
def printChannel( self):
|
2006-03-03 21:04:25 +01:00
|
|
|
print '- Channel: "' + self.title + '"'
|
2005-11-21 19:21:25 +01:00
|
|
|
for item in self.items:
|
2006-03-03 21:04:25 +01:00
|
|
|
print '-- Item: "' + item.title + '"'
|
2005-11-22 14:30:28 +01:00
|
|
|
|
2005-12-24 15:58:55 +01:00
|
|
|
def isDownloaded( self, item):
|
2006-02-04 11:37:23 +01:00
|
|
|
return libgpodder.gPodderLib().podcastFilenameExists( self, item.url)
|
2005-11-22 14:30:28 +01:00
|
|
|
|
2005-11-21 19:21:25 +01:00
|
|
|
def getItemsModel( self):
|
2005-11-22 14:30:28 +01:00
|
|
|
new_model = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING)
|
2005-11-21 19:21:25 +01:00
|
|
|
|
|
|
|
for item in self.items:
|
2005-11-22 14:30:28 +01:00
|
|
|
# Skip items with no download url
|
|
|
|
if item.url != "":
|
2005-12-24 15:58:55 +01:00
|
|
|
if self.isDownloaded(item):
|
|
|
|
background_color = "#eeeeee"
|
|
|
|
else:
|
|
|
|
background_color = "white"
|
2005-11-22 14:30:28 +01:00
|
|
|
new_iter = new_model.append()
|
|
|
|
new_model.set( new_iter, 0, item.url)
|
|
|
|
new_model.set( new_iter, 1, item.title)
|
|
|
|
new_model.set( new_iter, 2, item.getSize())
|
|
|
|
new_model.set( new_iter, 3, True)
|
|
|
|
new_model.set( new_iter, 4, background_color)
|
2005-11-21 19:21:25 +01:00
|
|
|
|
|
|
|
return new_model
|
|
|
|
|
|
|
|
def getActiveByUrl( self, url):
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
for item in self.items:
|
|
|
|
if item.url == url:
|
|
|
|
return i
|
|
|
|
i = i + 1
|
|
|
|
|
|
|
|
return -1
|
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
def downloadRss( self, force_update = True):
|
|
|
|
|
|
|
|
if (self.filename == "__unknown__" or exists( self.cache_file) == False) or force_update:
|
|
|
|
event = Event()
|
|
|
|
downloadThread(self.url, self.cache_file, event).download()
|
|
|
|
|
|
|
|
while event.isSet() == False:
|
|
|
|
event.wait( 0.2)
|
|
|
|
#FIXME: we do not want gtk code when not needed
|
|
|
|
while gtk.events_pending():
|
|
|
|
gtk.main_iteration( False)
|
|
|
|
|
|
|
|
return self.cache_file
|
|
|
|
|
|
|
|
def get_save_dir(self):
|
|
|
|
savedir = self.download_dir + self.filename + "/"
|
|
|
|
libgpodder.gPodderLib().createIfNecessary( savedir)
|
|
|
|
return savedir
|
|
|
|
|
|
|
|
save_dir = property(fget=get_save_dir)
|
|
|
|
|
|
|
|
def get_download_dir(self):
|
|
|
|
if self.__download_dir == None:
|
|
|
|
return libgpodder.gPodderLib().downloaddir
|
|
|
|
else:
|
|
|
|
return self.__download_dir
|
2005-11-21 19:21:25 +01:00
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
def set_download_dir(self, value):
|
|
|
|
self.__download_dir = value
|
|
|
|
libgpodder.gPodderLib().createIfNecessary(self.__download_dir)
|
2006-03-03 21:08:41 +01:00
|
|
|
if libgpodder.isDebugging():
|
|
|
|
print "set_download_dir: ", self, self.__download_dir
|
2006-03-03 21:04:25 +01:00
|
|
|
|
|
|
|
download_dir = property (fget=get_download_dir,
|
|
|
|
fset=set_download_dir)
|
|
|
|
|
|
|
|
def get_cache_file(self):
|
|
|
|
return libgpodder.gPodderLib().cachedir + self.filename + ".xml"
|
|
|
|
|
|
|
|
cache_file = property(fget=get_cache_file)
|
|
|
|
|
|
|
|
def get_index_file(self):
|
|
|
|
# gets index xml filename for downloaded channels list
|
|
|
|
return self.save_dir + "index.xml"
|
2005-11-21 19:21:25 +01:00
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
index_file = property(fget=get_index_file)
|
|
|
|
|
2006-03-24 20:08:59 +01:00
|
|
|
def deleteDownloadedItemByUrlAndTitle(self, url, title):
|
|
|
|
if libgpodder.isDebugging():
|
|
|
|
print "deleteDownloadedItemByUrlAndTitle: " + title + " (" + url + ")"
|
|
|
|
# no multithreaded access
|
|
|
|
libgpodder.getLock()
|
|
|
|
nr_items = 0
|
|
|
|
localdb = self.index_file
|
|
|
|
if libgpodder.isDebugging():
|
|
|
|
print "localdb: " + localdb
|
|
|
|
try:
|
|
|
|
locdb_reader = readLocalDB()
|
|
|
|
locdb_reader.parseXML( localdb)
|
|
|
|
self.downloaded = locdb_reader.channel
|
|
|
|
for item in self.downloaded.items:
|
|
|
|
if item.title == title and item.url == url:
|
|
|
|
nr_items += 1
|
|
|
|
self.downloaded.items.remove(item)
|
|
|
|
except:
|
|
|
|
print "no local db found or local db error"
|
|
|
|
if libgpodder.isDebugging():
|
|
|
|
print " found", nr_items, "matching item(s)"
|
|
|
|
if nr_items > 0:
|
|
|
|
writeLocalDB( localdb, self.downloaded)
|
|
|
|
libgpodder.releaseLock()
|
|
|
|
if nr_items > 0:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2006-03-03 21:04:25 +01:00
|
|
|
class podcastItem(object):
|
|
|
|
"""holds data for one object in a channel"""
|
|
|
|
def __init__( self,
|
|
|
|
url = "",
|
|
|
|
title = "",
|
|
|
|
length = "0",
|
|
|
|
mimetype = "",
|
|
|
|
guid = "",
|
|
|
|
description = "",
|
|
|
|
link = ""):
|
2005-11-21 19:21:25 +01:00
|
|
|
self.url = url
|
|
|
|
self.title = title
|
|
|
|
self.length = length
|
|
|
|
self.mimetype = mimetype
|
|
|
|
self.guid = guid
|
2006-02-26 00:13:29 +01:00
|
|
|
self.description = stripHtml( description)
|
2005-11-21 19:21:25 +01:00
|
|
|
self.link = ""
|
|
|
|
|
|
|
|
def getSize( self):
|
|
|
|
kilobyte = 1024
|
|
|
|
megabyte = kilobyte * 1024
|
|
|
|
gigabyte = megabyte * 1024
|
|
|
|
|
|
|
|
size = int( self.length)
|
|
|
|
if size > gigabyte:
|
|
|
|
return str( size / gigabyte) + " GB"
|
|
|
|
if size > megabyte:
|
|
|
|
return str( size / megabyte) + " MB"
|
|
|
|
if size > kilobyte:
|
|
|
|
return str( size / kilobyte) + " KB"
|
|
|
|
|
|
|
|
return str( size) + " Bytes"
|
|
|
|
|
|
|
|
def channelsToModel( channels):
|
|
|
|
new_model = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_OBJECT)
|
|
|
|
|
|
|
|
for channel in channels:
|
|
|
|
new_iter = new_model.append()
|
|
|
|
new_model.set( new_iter, 0, channel.url)
|
2006-03-04 21:45:01 +01:00
|
|
|
new_model.set( new_iter, 1, channel.title) # + " ("+channel.url+")")
|
2005-11-21 19:21:25 +01:00
|
|
|
#if channel.image != None:
|
|
|
|
# new_model.set( new_iter, 2, gtk.gdk.pixbuf_new_from_file_at_size( channel.image, 60, 60))
|
|
|
|
#else:
|
|
|
|
# new_model.set( new_iter, 2, None)
|
|
|
|
|
|
|
|
return new_model
|
|
|
|
|
2006-02-26 00:13:29 +01:00
|
|
|
def stripHtml( html):
|
|
|
|
# strips html from a string (fix for <description> tags containing html)
|
2006-03-19 18:44:47 +01:00
|
|
|
dict = htmlentitydefs.entitydefs
|
2006-02-26 00:13:29 +01:00
|
|
|
rexp = re.compile( "<[^>]*>")
|
2006-03-19 18:44:47 +01:00
|
|
|
stripstr = rexp.sub( "", html)
|
|
|
|
# strips html entities
|
|
|
|
for key in dict.keys():
|
|
|
|
stripstr = stripstr.replace( '&'+unicode(key,'iso-8859-1')+';', unicode(dict[key], 'iso-8859-1'))
|
|
|
|
return stripstr
|
|
|
|
|