Sync to trunk.

This commit is contained in:
John Schember 2009-06-06 07:33:23 -04:00
commit 1e072040ba
9 changed files with 269 additions and 58 deletions

View File

@ -230,7 +230,7 @@ _check_symlinks_prescript()
all_functions = main_functions['console'] + main_functions['gui']
print
print 'Adding PoDoFo'
pdf = glob.glob(os.path.expanduser('/Volumes/sw/podofo/*.dylib'))[0]
pdf = glob.glob(os.path.expanduser('/Volumes/sw/podofo/libpodofo.0.7.00.dylib'))[0]
shutil.copyfile(pdf, os.path.join(frameworks_dir, os.path.basename(pdf)))
@ -264,6 +264,14 @@ _check_symlinks_prescript()
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree('/usr/local/etc/fonts', dst, symlinks=False)
for x in os.listdir('/usr/local/etc/fonts'):
dst = os.path.join(frameworks_dir, x)
y = os.path.join('/usr/local/etc/fonts', x)
if os.path.isdir(dst):
if os.path.exists(dst): shutil.rmtree(dst)
shutil.copytree(y, dst)
else:
os.link(y, dst)
print
print 'Adding IPython'

View File

@ -62,9 +62,9 @@ if __name__ == '__main__':
podofo_inc = '/usr/include/podofo' if islinux else \
'C:\\podofo\\include\\podofo' if iswindows else \
'/Volumes/sw/podofo/include/podofo'
'/usr/local/include/podofo'
podofo_lib = '/usr/lib' if islinux else r'C:\podofo' if iswindows else \
'/Volumes/sw/podofo/lib'
'/usr/local/lib'
podofo_inc = os.environ.get('PODOFO_INC_DIR', podofo_inc)
if os.path.exists(os.path.join(podofo_inc, 'podofo.h')):
optional.append(Extension('calibre.plugins.podofo',

View File

@ -403,7 +403,8 @@ def fix_ids(main, carda, cardb):
for child in db.root_element.childNodes:
if child.nodeType == child.ELEMENT_NODE and child.hasAttribute('id'):
id_map[child.getAttribute('id')] = str(cid)
child.setAttribute("sourceid", '1')
child.setAttribute("sourceid",
'0' if getattr(child, 'tagName', '').endswith('playlist') else '1')
child.setAttribute('id', str(cid))
cid += 1

View File

@ -7,14 +7,7 @@ intended to be subclassed with the relevant parts implemented for a particular
device. This class handles device detection.
'''
import glob
import os
import re
import struct
import subprocess
import sys
import time
import os, subprocess, time, re, sys, glob
from itertools import repeat
from calibre.devices.interface import DevicePlugin
@ -499,29 +492,26 @@ class Device(DeviceConfig, DevicePlugin):
self.open_osx()
def eject_windows(self):
win32file = __import__('win32file', globals(), locals(), [], -1)
win32con = __import__('win32con', globals(), locals(), [], -1)
win32shell = __import__('win32com.shell.shell', globals(), locals(), [], -1)
win32shellcon = __import__('win32com.shell.shellcon', globals(), locals(), [], -1)
FSCTL_LOCK_VOLUME = 0x0090018
FSCTL_DISMOUNT_VOLUME = 0x00090020
IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804
IOCTL_STORAGE_EJECT_MEDIA = 0x002D4808
from calibre.constants import plugins
from threading import Thread
winutil, winutil_err = plugins['winutil']
drives = []
for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):
x = getattr(self, x, None)
if x is not None:
vol = win32file.CreateFile(x, win32con.GENERIC_READ | win32con.GENERIC_WRITE, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, None, win32con.OPEN_EXISTING, 0, None)
drives.append(x[0].upper())
def do_it(drives):
for d in drives:
try:
win32file.DeviceIoControl(vol, FSCTL_LOCK_VOLUME, '', 0, None)
win32file.DeviceIoControl(vol, FSCTL_DISMOUNT_VOLUME, '', 0, None)
win32file.DeviceIoControl(vol, IOCTL_STORAGE_MEDIA_REMOVAL, struct.pack('B', 0), 0, None)
win32file.DeviceIoControl(vol, IOCTL_STORAGE_EJECT_MEDIA, '', 0, None)
time.sleep(2)
win32shell.SHChangeNotify(win32shellcon.SHCNE_DRIVEREMOVED, win32shellcon.SHCNF_PATH, x)
finally:
win32file.CloseHandle(vol)
winutil.eject_drive(d)
except:
pass
t = Thread(target=do_it, args=[drives])
t.daemon = True
t.start()
self.__save_win_eject_thread = t
def eject_osx(self):
for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):

View File

@ -63,9 +63,12 @@ def roman(num):
def fmt_sidx(i, fmt='%.2f', use_roman=False):
if i is None:
i = 1
if int(i) == i:
return roman(i) if use_roman else '%d'%i
return fmt%i
if int(i) == float(i):
return roman(int(i)) if use_roman else '%d'%int(i)
try:
return fmt%i
except TypeError:
return fmt%float(i)
class Resource(object):

View File

@ -77,6 +77,7 @@ class Query(object):
if verbose:
print 'Query:', self.url
feed = etree.fromstring(browser.open(self.url).read())
#print etree.tostring(feed, pretty_print=True)
total = int(total_results(feed)[0].text)
start = int(start_index(feed)[0].text)
entries = entry(feed)
@ -104,12 +105,9 @@ class ResultList(list):
except:
report(verbose)
def get_title(self, entry):
candidates = [x.text for x in title(entry)]
candidates.sort(cmp=lambda x,y: cmp(len(x), len(y)), reverse=True)
return candidates[0]
return ': '.join(candidates)
def get_authors(self, entry):
m = creator(entry)
@ -182,7 +180,7 @@ class ResultList(list):
self.get_identifiers(x, mi)
mi.tags = self.get_tags(x, verbose)
mi.publisher = self.get_publisher(x, verbose)
mi.timestamp = self.get_date(x, verbose)
mi.pubdate = self.get_date(x, verbose)
mi.language = self.get_language(x, verbose)
self.append(mi)

View File

@ -7,14 +7,18 @@ __docformat__ = 'restructuredtext en'
HTTP server for remote access to the calibre database.
'''
import sys, textwrap, operator, os, re, logging
import sys, textwrap, operator, os, re, logging, cStringIO
from itertools import repeat
from logging.handlers import RotatingFileHandler
from datetime import datetime
from threading import Thread
import cherrypy
from PyQt4.Qt import QImage, QApplication, QByteArray, Qt, QBuffer
try:
from PIL import Image as PILImage
PILImage
except ImportError:
import Image as PILImage
from calibre.constants import __version__, __appname__
from calibre.utils.genshi.template import MarkupTemplate
@ -195,25 +199,21 @@ class LibraryServer(object):
updated = datetime.utcfromtimestamp(os.stat(path).st_mtime) if path and os.access(path, os.R_OK) else build_time
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
try:
if QApplication.instance() is None:
QApplication([])
im = QImage()
im.loadFromData(cover)
if im.isNull():
f = cStringIO.StringIO(cover)
try:
im = PILImage.open(f)
except IOError:
raise cherrypy.HTTPError(404, 'No valid cover found')
width, height = im.width(), im.height()
width, height = im.size
scaled, width, height = fit_image(width, height,
60 if thumbnail else self.max_cover_width,
80 if thumbnail else self.max_cover_height)
if not scaled:
return cover
im = im.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
ba = QByteArray()
buf = QBuffer(ba)
buf.open(QBuffer.WriteOnly)
im.save(buf, 'PNG')
return str(ba.data())
im = im.resize((int(width), int(height)), PILImage.ANTIALIAS)
of = cStringIO.StringIO()
im.convert('RGB').save(of, 'JPEG')
return of.getvalue()
except Exception, err:
import traceback
traceback.print_exc()
@ -294,7 +294,7 @@ class LibraryServer(object):
series = record[FIELD_MAP['series']]
if series:
extra.append('SERIES: %s [%s]<br />'%(series,
fmt_sidx(record[FIELD_MAP['series_index']])))
fmt_sidx(float(record[FIELD_MAP['series_index']]))))
fmt = 'epub' if 'EPUB' in r else 'pdb'
mimetype = guess_type('dummy.'+fmt)[0]
books.append(self.STANZA_ENTRY.generate(
@ -343,7 +343,7 @@ class LibraryServer(object):
for record in items[start:start+num]:
aus = record[2] if record[2] else __builtins__._('Unknown')
authors = '|'.join([i.replace('|', ',') for i in aus.split(',')])
r[10] = fmt_sidx(r[10])
record[10] = fmt_sidx(float(record[10]))
books.append(book.generate(r=record, authors=authors).render('xml').decode('utf-8'))
updated = self.db.last_modified()

View File

@ -271,7 +271,7 @@ get_all_removable_disks(struct tagDrives *g_drives)
// Loop for all drives (MAX_DRIVES = 26)
for(nLoopIndex = 0; nLoopIndex< MAX_DRIVES; nLoopIndex++)
for(nLoopIndex = 0; nLoopIndex < MAX_DRIVES; nLoopIndex++)
{
// if a drive is present,
if(dwDriveMask & 1)
@ -306,6 +306,213 @@ get_all_removable_disks(struct tagDrives *g_drives)
}
static DEVINST
GetDrivesDevInstByDeviceNumber(long DeviceNumber,
UINT DriveType, char* szDosDeviceName)
{
GUID *guid;
HDEVINFO hDevInfo;
DWORD dwIndex, dwBytesReturned;
BOOL bRet, IsFloppy;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd;
long res;
HANDLE hDrive;
STORAGE_DEVICE_NUMBER sdn;
IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // is there a better way?
switch (DriveType) {
case DRIVE_REMOVABLE:
if ( IsFloppy ) {
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
} else {
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
}
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
PyErr_SetString(PyExc_ValueError, "Invalid drive type");
return 0;
}
// Get device interface info set handle
// for all devices attached to system
hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
PyErr_SetString(PyExc_ValueError, "Invalid handle value");
return 0;
}
// Retrieve a context structure for a device interface
// of a device information set.
dwIndex = 0;
bRet = FALSE;
pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while ( TRUE ) {
bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL,
guid, dwIndex, &spdid);
if ( !bRet ) {
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&spdid, NULL, 0, &dwSize, NULL);
if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
res =
SetupDiGetDeviceInterfaceDetail(hDevInfo, &
spdid, pspdidd,
dwSize, &dwSize,
&spdd);
if ( res ) {
hDrive = CreateFile(pspdidd->DevicePath,0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if ( hDrive != INVALID_HANDLE_VALUE ) {
dwBytesReturned = 0;
res = DeviceIoControl(hDrive,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof(sdn),
&dwBytesReturned, NULL);
if ( res ) {
if ( DeviceNumber == (long)sdn.DeviceNumber ) {
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
PyErr_SetString(PyExc_ValueError, "Invalid device number");
return 0;
}
static BOOL
eject_drive_letter(char DriveLetter) {
char szRootPath[4], szDevicePath[3], szVolumeAccessPath[7], szDosDeviceName[MAX_PATH];
long DeviceNumber, res, tries;
HANDLE hVolume;
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned;
DEVINST DevInst;
ULONG Status;
ULONG ProblemNumber;
PNP_VETO_TYPE VetoType;
WCHAR VetoNameW[MAX_PATH];
BOOL bSuccess;
DEVINST DevInstParent;
szRootPath[0] = DriveLetter; szRootPath[1] = ':'; szRootPath[2] = '\\'; szRootPath[3] = (char)0;
szDevicePath[0] = DriveLetter; szDevicePath[1] = ':'; szDevicePath[2] = (char)0;
szVolumeAccessPath[0] = '\\'; szVolumeAccessPath[1] = '\\'; szVolumeAccessPath[2] = '.';
szVolumeAccessPath[3] = '\\'; szVolumeAccessPath[4] = DriveLetter; szVolumeAccessPath[5] = ':';
szVolumeAccessPath[6] = (char)0;
DeviceNumber = -1;
hVolume = CreateFile(szVolumeAccessPath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hVolume == INVALID_HANDLE_VALUE) {
PyErr_SetString(PyExc_ValueError, "Invalid handle value for drive letter");
return FALSE;
}
dwBytesReturned = 0;
res = DeviceIoControl(hVolume,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof(sdn),
&dwBytesReturned, NULL);
if ( res ) {
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if ( DeviceNumber == -1 ) {
PyErr_SetString(PyExc_ValueError, "Can't find drive number");
return FALSE;
}
res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
if ( !res ) {
PyErr_SetString(PyExc_ValueError, "Can't find dos device");
return FALSE;
}
DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber,
DriveType, szDosDeviceName);
if (DevInst == 0) return FALSE;
DevInstParent = 0;
Status = 0;
ProblemNumber = 0;
PNP_VETO_TYPE VetoType;
bSuccess = FALSE;
res = CM_Get_Parent(&DevInstParent, DevInst, 0);
for ( tries = 0; tries < 3; tries++ ) {
VetoNameW[0] = 0;
res = CM_Request_Device_EjectW(DevInstParent,
&VetoType, VetoNameW, MAX_PATH, 0);
bSuccess = (res==CR_SUCCESS &&
VetoType==PNP_VetoTypeUnknown);
if ( bSuccess ) {
break;
}
Sleep(500); // required to give the next tries a chance!
}
if (!bSuccess) PyErr_SetString(PyExc_ValueError, "Failed to eject drive after three tries");
return bSuccess;
}
static PyObject *
winutil_eject_drive(PyObject *self, PyObject *args) {
char DriveLetter;
if (!PyArg_ParseTuple(args, "c", &DriveLetter)) return NULL;
if (!eject_drive_letter(DriveLetter)) return NULL;
Py_RETURN_NONE;
}
PSP_DEVICE_INTERFACE_DETAIL_DATA
get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_id,
BOOL *iterate) {
@ -697,6 +904,10 @@ is not present, current time as returned by localtime() is used. format must\n\
be a unicode string. Returns unicode strings."
},
{"eject_drive", winutil_eject_drive, METH_VARARGS,
"eject_drive(drive_letter)\n\nEject a drive. Raises an exception on failure."
},
{NULL, NULL, 0, NULL}
};

View File

@ -548,7 +548,7 @@ class build_windows(VMInstaller):
class build_osx(VMInstaller):
description = 'Build OS X app bundle'
VM = '/vmware/Mac OSX/Mac OSX.vmx'
VM = '/mnt/backup/calibre_os_x/Mac OSX.vmx'
if not os.path.exists(VM):
VM = '/home/kovid/calibre_os_x/Mac OSX.vmx'