#!/usr/bin/python
# as described in http://www.sven.de/librie/Librie/MgrTabFormat
# this is what goes in /mssony/librie/booklist/MgrTbl.dat
import sys
import os
import rfc822
import struct
import time
import LrfFile
import xml.dom.minidom
def pack_to(len, bytes):
return (bytes + struct.pack("x" * len))[:len]
class xml_attrs:
def __init__(self, s=None, node=None):
if s:
self.xpp = xml.dom.minidom.parseString(s)
else:
self.xpp = node
def __getattr__(self, a):
return xml_attrs(node=self.xpp.getElementsByTagName(a)[0])
def Text(self):
return self.xpp.childNodes[0].wholeText
def unlink(self):
return self.xpp.unlink()
# this lets "" encode to ""
def encode_utf16(s):
if not s: return ""
return s.encode("utf-16")
# "<" for all, little endian; "H" for all of these 2-byte fields
class MgrField:
def __init__(self, lrfname):
self.lrfname = os.path.basename(lrfname)
self.title = u""
self.titlereading = u""
self.author = u""
self.authorreading = u""
self.publisher = u""
self.location = ""
lrf = LrfFile.LrfFile(lrfname)
# this is the full cover - should thumbnail it
# (use PIL, or double-pipe - avoid the tmpfile)
# http://permalink.gmane.org/gmane.linux.hardware.sony.librie/1545
# says "60x80" for the thumbnail...
conv = os.popen("convert -scale 20% - /tmp/x.gif", "w")
conv.write(lrf.gif)
conv.close()
self.cover_image_data = open("/tmp/x.gif").read()
self.cover_image_type = 0x14
# lrf.uinfo also has CreationDate, Title, Author, BookID, Publisher...
xlrf = xml_attrs(lrf.uinfo.rstrip("\0"))
xbook = xlrf.Info.BookInfo
self.id = xbook.BookID.Text()
self.publisher = xbook.Publisher.Text()
self.author = xbook.Author.Text()
self.title = xbook.Title.Text()
xdoc = xlrf.Info.DocInfo
self.when = xdoc.CreationDate.Text()
xlrf.unlink()
def import_fields(self, fields):
for k,v in fields.items():
setattr(self, k.lower(), v.decode("iso-8859-1"))
def set_size(self, size):
self.size = size
def set_mtime(self, mtime):
self.unixtime = mtime
def prep(self):
# some things are derived...
if not hasattr(self, "id"):
self.id = unicode(self.lrfname.replace(".lrf","",1))
# self.id = "zdVnISprTxmeHKjx"
if not hasattr(self, "when"):
self.when = time.strftime("%Y-%m-%d", time.gmtime(self.unixtime))
if not hasattr(self, "cover_image_data"):
# read and convert, later
self.cover_image_data = open("/usr/share/galeon/general.png", "r").read()
# 0x11 for JPEG, 0x12 for PNG, 0x13 for BMP and 0x14 for GIF.
self.cover_image_type = 0x12
# if not self.titlereading:
# self.titlereading = self.title
# if not self.authorreading:
# self.authorreading = self.author
if not self.location:
# BookListItem.cs makes this upper case
self.location = "a:/ebook/bbeb/book/" + self.lrfname
def marshall(self):
bytes = []
# emit the headerfields
bytes.append(struct.pack("<H", 0)) # dummy recordlen
bytes.append(struct.pack("<H", len(encode_utf16(self.title))))
bytes.append(struct.pack("<H", len(encode_utf16(self.titlereading))))
bytes.append(struct.pack("<H", len(encode_utf16(self.author))))
bytes.append(struct.pack("<H", len(encode_utf16(self.authorreading))))
bytes.append(struct.pack("<H", len(encode_utf16(self.publisher))))
bytes.append(struct.pack("<H", len(self.location.encode("ascii"))))
bytes.append(struct.pack("<H", len(self.cover_image_data)))
bytes.append(struct.pack("<H", 0x60)) # unknown
bytes.append(struct.pack("x" * 15))
# now add the values
bytes.append(pack_to(32, encode_utf16(self.id)))
bytes.append(pack_to(15, self.when.encode("ascii")))
bytes.append(encode_utf16(self.title))
bytes.append(encode_utf16(self.titlereading))
bytes.append(encode_utf16(self.author))
bytes.append(encode_utf16(self.authorreading))
bytes.append(encode_utf16(self.publisher))
bytes.append(self.location.encode("ascii"))
bytes.append(struct.pack("<L", self.size))
bytes.append(struct.pack("x" * 16))
bytes.append(struct.pack("B", self.cover_image_type))
bytes.append(self.cover_image_data)
# now fix the length
bytes[0] = struct.pack("<H", len("".join(bytes)))
return "".join(bytes)
def get_keys(lrfname):
fp = open(lrfname.replace(".lrf", ".info", 1), "r")
m = rfc822.Message(fp)
return m.dict
def write_datafile(stickbase):
mgrtbl_name = os.path.join(stickbase, "mssony/librie/booklist/MgrTbl.dat")
mgrtbl = open(mgrtbl_name, "w")
bookdir = os.path.join(stickbase, "ebook/bbeb/book")
for lrfname in os.listdir(bookdir):
if not lrfname.endswith(".lrf"): continue
bookname = os.path.join(bookdir, lrfname)
mgr = MgrField(bookname)
# metadata = get_keys(bookname)
# mgr.import_fields(metadata)
mgr.set_size(os.path.getsize(bookname))
mgr.set_mtime(os.path.getmtime(bookname))
mgr.prep()
mgrtbl.write(mgr.marshall())
mgrtbl.close()
if __name__ == "__main__":
prog, stickbase = sys.argv
write_datafile(stickbase)