listing of books

This commit is contained in:
Kovid Goyal 2006-11-16 06:15:12 +00:00
parent e456f6e828
commit a44a2e578b
2 changed files with 107 additions and 7 deletions

View File

@ -46,6 +46,11 @@ The public interface of class L{PRS500Device} defines the methods for performing
""" """
import usb, sys, os, time import usb, sys, os, time
from array import array from array import array
from xml.sax.handler import ContentHandler
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces
from base64 import b64decode as decode
from tempfile import TemporaryFile
from prstypes import * from prstypes import *
from errors import * from errors import *
@ -62,6 +67,54 @@ def _log_packet(packet, header, stream=sys.stderr):
print >>stream, packet print >>stream, packet
print >>stream, "--" print >>stream, "--"
class FindBooks(ContentHandler):
""" Used to parse the cache.xml/media.xml files on the PRS 500 """
class Book(dict):
def __init__(self, src):
dict.__init__(self, src)
if not self.has_key("author") or len(self["author"].rstrip()) == 0:
self["author"] = "Unknown"
self["title"] = self["title"].strip()
def __repr__(self):
return self["title"] + " by " + self["author"] + " at " + self["path"]
def __str__(self):
return self.__repr__()
def __init__(self, type="media", root="/Data/media/"):
ContentHandler.__init__(self)
self.books = []
self.root = root
self.thumbnail = ""
self.in_book = False
self.in_thumbnail = False
self.book_name = "text"
self.thumbnail_name = "thumbnail"
if type == "media":
self.book_name = "xs1:" + self.book_name
self.thumbnail_name = "xs1:" + self.thumbnail_name
def startElement(self, name, attrs):
if name == self.book_name:
data = FindBooks.Book(attrs)
data["path"] = self.root + data["path"]
self.books.append(data)
self.in_book = True
elif self.in_book and name == self.thumbnail_name:
self.in_thumbnail = True
def characters(self, ch):
if self.in_thumbnail:
self.thumbnail += ch
def endElement(self, name):
if self.in_book and name == self.thumbnail_name:
if len(self.books) > 0: self.books[len(self.books)-1]["thumbnail"] = decode(self.thumbnail)
self.thumbnail, self.in_thumbnail = "", False
elif name == self.book_name: self.in_book = False
class File(object): class File(object):
""" Wrapper that allows easy access to all information about files/directories """ """ Wrapper that allows easy access to all information about files/directories """
def __init__(self, file): def __init__(self, file):
@ -530,10 +583,48 @@ class PRS500Device(object):
if res.code != 0: if res.code != 0:
raise ProtocolError("Failed to delete directory " + path + ". Response code: " + hex(res.code)) raise ProtocolError("Failed to delete directory " + path + ". Response code: " + hex(res.code))
@safe
def books(self):
"""
Return a list of all ebooks on the device
@return: A two element tuple. The first element is the books in the main memory and the second is the books on the storage card.
Each element is a list of dictionaries. Important fields in each dictionary are "title", "author", "path" and "thumbnail".
"""
buffer = TemporaryFile()
media = self.get_file("/Data/database/cache/media.xml", buffer, end_session=False)
parser = make_parser()
parser.setFeature(feature_namespaces, 0)
finder = FindBooks()
parser.setContentHandler(finder)
buffer.seek(0)
parser.parse(buffer)
buffer.close()
books = finder.books
root = "a:/"
buffer = TemporaryFile()
cbooks = []
try:
self.get_file("a:/Sony Reader/database/cache.xml", buffer, end_session=False)
except PathError:
try:
self.get_file("b:/Sony Reader/database/cache.xml", buffer, end_session=False)
root = "b:/"
except PathError:
pass
if buffer.tell() > 0:
finder = FindBooks(type="cache", root=root)
buffer.seek(0)
parser.setContentHandler(finder)
parser.parse(buffer)
buffer.close()
cbooks = finder.books
return books, cbooks
#dev = PRS500Device(log_packets=False)
#dev.open() ##dev = PRS500Device(log_packets=False)
#print dev.get_file("/etc/sysctl.conf", sys.stdout) ##dev.open()
#dev.close() ##print dev.books()
##dev.close()

View File

@ -165,7 +165,7 @@ def main():
term = TerminalController() term = TerminalController()
cols = term.COLS cols = term.COLS
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, df, ls, cp, mkdir, touch, cat or rm\n\n"+ parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, books, df, ls, cp, mkdir, touch, cat or rm\n\n"+
"For help on a particular command: %prog command", version="libprs500 version: " + VERSION) "For help on a particular command: %prog command", version="libprs500 version: " + VERSION)
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\ parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
"The numbers in the left column are byte offsets that allow the packet size to be read off easily.", "The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
@ -189,6 +189,15 @@ def main():
total, free, used, percent = human_readable(datum[2]), human_readable(datum[1]), human_readable(datum[2]-datum[1]), \ total, free, used, percent = human_readable(datum[2]), human_readable(datum[1]), human_readable(datum[2]-datum[1]), \
str(0 if datum[2]==0 else int(100*(datum[2]-datum[1])/(datum[2]*1.)))+"%" str(0 if datum[2]==0 else int(100*(datum[2]-datum[1])/(datum[2]*1.)))+"%"
print "%-10s\t%s\t%s\t%s\t%s"%(datum[0], total, used, free, percent) print "%-10s\t%s\t%s\t%s\t%s"%(datum[0], total, used, free, percent)
elif command == "books":
main, card = dev.books()
print "Books in main memory:"
for book in main:
print book
print
print "Books on storage card:"
for book in card:
print book
elif command == "mkdir": elif command == "mkdir":
parser = OptionParser(usage="usage: %prog mkdir [options] path\n\npath must begin with /,a:/ or b:/") parser = OptionParser(usage="usage: %prog mkdir [options] path\n\npath must begin with /,a:/ or b:/")
if len(args) != 1: if len(args) != 1: