mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Windows PRS505 support
This commit is contained in:
parent
8d46e046d4
commit
4312aff2cf
@ -103,7 +103,7 @@ _check_symlinks_prescript()
|
|||||||
else:
|
else:
|
||||||
debug = 0
|
debug = 0
|
||||||
return find_modules(
|
return find_modules(
|
||||||
scripts=scripts['console'] + scripts['gui'],
|
scripts=scripts['console'] + scripts['gui'][1:],
|
||||||
includes=list(self.includes) + main_modules['console'],
|
includes=list(self.includes) + main_modules['console'],
|
||||||
packages=self.packages,
|
packages=self.packages,
|
||||||
excludes=self.excludes,
|
excludes=self.excludes,
|
||||||
|
@ -32,9 +32,10 @@ class TimeoutError(ProtocolError):
|
|||||||
|
|
||||||
class DeviceError(ProtocolError):
|
class DeviceError(ProtocolError):
|
||||||
""" Raised when device is not found """
|
""" Raised when device is not found """
|
||||||
def __init__(self):
|
def __init__(self, msg=None):
|
||||||
ProtocolError.__init__(self, \
|
if msg is None:
|
||||||
"Unable to find SONY Reader. Is it connected?")
|
msg = "Unable to find SONY Reader. Is it connected?"
|
||||||
|
ProtocolError.__init__(self, msg)
|
||||||
|
|
||||||
class DeviceBusy(ProtocolError):
|
class DeviceBusy(ProtocolError):
|
||||||
""" Raised when device is busy """
|
""" Raised when device is busy """
|
||||||
|
@ -46,8 +46,18 @@ class Device(object):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_connected(cls):
|
def get_fdi(cls):
|
||||||
'''Return True iff the device is physically connected to the computer'''
|
'''Return the FDI description of this device for HAL on linux.'''
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_connected(cls, helper=None):
|
||||||
|
'''
|
||||||
|
Return True iff the device is physically connected to the computer
|
||||||
|
|
||||||
|
@param helper: Platform dependent helper object. For e.g. on windows
|
||||||
|
an instantiated WMI interface.
|
||||||
|
'''
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def set_progress_reporter(self, report_progress):
|
def set_progress_reporter(self, report_progress):
|
||||||
|
@ -18,11 +18,18 @@ import shutil
|
|||||||
from libprs500.devices.interface import Device
|
from libprs500.devices.interface import Device
|
||||||
from libprs500.devices.errors import DeviceError, FreeSpaceError
|
from libprs500.devices.errors import DeviceError, FreeSpaceError
|
||||||
from libprs500.devices.prs500.books import BookList
|
from libprs500.devices.prs500.books import BookList
|
||||||
|
from libprs500 import iswindows, islinux, isosx
|
||||||
|
if not iswindows:
|
||||||
|
from libprs500.devices.libusb import get_device_by_id
|
||||||
|
|
||||||
from libprs500 import islinux, iswindows
|
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _winreg
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
class File(object):
|
class File(object):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
stats = os.stat(path)
|
stats = os.stat(path)
|
||||||
@ -40,43 +47,117 @@ class File(object):
|
|||||||
class PRS505(Device):
|
class PRS505(Device):
|
||||||
VENDOR_ID = 0x054c #: SONY Vendor Id
|
VENDOR_ID = 0x054c #: SONY Vendor Id
|
||||||
PRODUCT_ID = 0x031e #: Product Id for the PRS-505
|
PRODUCT_ID = 0x031e #: Product Id for the PRS-505
|
||||||
PRODUCT_NAME = 'Sony Portable Reader System'
|
PRODUCT_NAME = 'PRS-505'
|
||||||
|
VENDOR_NAME = 'SONY'
|
||||||
|
|
||||||
MEDIA_XML = 'database/cache/media.xml'
|
MEDIA_XML = 'database/cache/media.xml'
|
||||||
CACHE_XML = 'Sony Reader/database/cache.xml'
|
CACHE_XML = 'Sony Reader/database/cache.xml'
|
||||||
|
|
||||||
LINUX_DEVICE_NODE = 'sony_prs_505'
|
MAIN_MEMORY_VOLUME_LABEL = 'Sony Reader Main Memory'
|
||||||
LINUX_DEVICE_PATH = os.path.join('/dev', LINUX_DEVICE_NODE)
|
STORAGE_CARD_VOLUME_LABEL = 'Sony Reader Storage Card'
|
||||||
|
|
||||||
|
FDI_TEMPLATE = \
|
||||||
|
'''
|
||||||
|
<device>
|
||||||
|
<match key="info.category" string="volume">
|
||||||
|
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.vendor_id" int="%(vendor_id)s">
|
||||||
|
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.product_id" int="%(product_id)s">
|
||||||
|
<match key="volume.is_partition" bool="false">
|
||||||
|
<merge key="volume.label" type="string">%(main_memory)s</merge>
|
||||||
|
<merge key="libprs500.mainvolume" type="string">%(deviceclass)s</merge>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</device>
|
||||||
|
<device>
|
||||||
|
<match key="info.category" string="volume">
|
||||||
|
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.vendor_id" int="%(vendor_id)s">
|
||||||
|
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.product_id" int="%(product_id)s">
|
||||||
|
<match key="volume.is_partition" bool="true">
|
||||||
|
<merge key="volume.label" type="string">%(storage_card)s</merge>
|
||||||
|
<merge key="libprs500.cardvolume" type="string">%(deviceclass)s</merge>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</device>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._main_prefix = self._card_prefix = None
|
self._main_prefix = self._card_prefix = None
|
||||||
self.hm = None
|
|
||||||
if islinux:
|
|
||||||
import dbus
|
|
||||||
self.bus = dbus.SystemBus()
|
|
||||||
self.hm = dbus.Interface(self.bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager"), "org.freedesktop.Hal.Manager")
|
|
||||||
|
|
||||||
def is_connected(self):
|
@classmethod
|
||||||
if self.hm is not None: # linux
|
def get_fdi(cls):
|
||||||
devs = self.hm.FindDeviceStringMatch('info.product', 'Sony Portable Reader System')
|
return cls.FDI_TEMPLATE%dict(
|
||||||
for dev in devs:
|
deviceclass=cls.__name__,
|
||||||
obj = self.bus.get_object("org.freedesktop.Hal", dev)
|
vendor_id=hex(cls.VENDOR_ID),
|
||||||
if obj.GetPropertyInteger('usb_device.product_id', dbus_interface='org.freedesktop.Hal.Device') == self.__class__.PRODUCT_ID:
|
product_id=hex(cls.PRODUCT_ID),
|
||||||
|
main_memory=cls.MAIN_MEMORY_VOLUME_LABEL,
|
||||||
|
storage_card=cls.STORAGE_CARD_VOLUME_LABEL,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_device(cls, device_id):
|
||||||
|
if 'VEN_'+cls.VENDOR_NAME in device_id.upper() and \
|
||||||
|
'PROD_'+cls.PRODUCT_NAME in device_id.upper():
|
||||||
|
return True
|
||||||
|
vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:]
|
||||||
|
if len(vid) < 4: vid = '0'+vid
|
||||||
|
if len(pid) < 4: pid = '0'+pid
|
||||||
|
if 'VID_'+vid in device_id.upper() and \
|
||||||
|
'PID_'+pid in device_id.upper():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def open_linux(self):
|
@classmethod
|
||||||
|
def is_connected(cls, helper=None):
|
||||||
|
if iswindows:
|
||||||
|
for c in helper.USBControllerDevice():
|
||||||
|
if cls.is_device(c.Dependent.DeviceID):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return get_device_by_id(cls.VENDOR_ID, cls.PRODUCT_ID) != None
|
||||||
|
|
||||||
|
|
||||||
|
def open_windows(self):
|
||||||
|
import wmi
|
||||||
|
c = wmi.WMI()
|
||||||
|
for drive in c.Win32_DiskDrive():
|
||||||
|
if self.__class__.is_device(drive.PNPDeviceID):
|
||||||
|
if drive.Partitions == 0:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
mm = self.hm.FindDeviceStringMatch('volume.label', 'Sony Reader Main Memory')[0]
|
partition = drive.associators("Win32_DiskDriveToDiskPartition")[0]
|
||||||
|
except IndexError:
|
||||||
|
continue
|
||||||
|
logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0]
|
||||||
|
prefix = logical_disk.DeviceID+os.sep
|
||||||
|
if drive.Index == 1:
|
||||||
|
self._main_prefix = prefix
|
||||||
|
else:
|
||||||
|
self._card_prefix = prefix
|
||||||
|
if self._main_prefix is None:
|
||||||
|
raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,))
|
||||||
|
|
||||||
|
|
||||||
|
def open_linux(self):
|
||||||
|
import dbus
|
||||||
|
bus = dbus.SystemBus()
|
||||||
|
hm = dbus.Interface(self.bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager"), "org.freedesktop.Hal.Manager")
|
||||||
|
try:
|
||||||
|
mm = hm.FindDeviceStringMatch('libprs500.mainvolume', self.__class__.__name__)[0]
|
||||||
except:
|
except:
|
||||||
raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,))
|
raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,))
|
||||||
try:
|
try:
|
||||||
sc = self.hm.FindDeviceStringMatch('volume.label', 'Sony Reader Storage Card')[0]
|
sc = hm.FindDeviceStringMatch('libprs500.cardvolume', self.__class__.__name__)[0]
|
||||||
except:
|
except:
|
||||||
sc = None
|
sc = None
|
||||||
|
|
||||||
def conditional_mount(dev):
|
def conditional_mount(dev):
|
||||||
mmo = self.bus.get_object("org.freedesktop.Hal", dev)
|
mmo = bus.get_object("org.freedesktop.Hal", dev)
|
||||||
label = mmo.GetPropertyString('volume.label', dbus_interface='org.freedesktop.Hal.Device')
|
label = mmo.GetPropertyString('volume.label', dbus_interface='org.freedesktop.Hal.Device')
|
||||||
is_mounted = mmo.GetPropertyString('volume.is_mounted', dbus_interface='org.freedesktop.Hal.Device')
|
is_mounted = mmo.GetPropertyString('volume.is_mounted', dbus_interface='org.freedesktop.Hal.Device')
|
||||||
mount_point = mmo.GetPropertyString('volume.mount_point', dbus_interface='org.freedesktop.Hal.Device')
|
mount_point = mmo.GetPropertyString('volume.mount_point', dbus_interface='org.freedesktop.Hal.Device')
|
||||||
@ -93,8 +174,10 @@ class PRS505(Device):
|
|||||||
self._card_prefix = conditional_mount(sc)+os.sep
|
self._card_prefix = conditional_mount(sc)+os.sep
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if self.hm is not None: # linux
|
if islinux:
|
||||||
self.open_linux()
|
self.open_linux()
|
||||||
|
if iswindows:
|
||||||
|
self.open_windows()
|
||||||
|
|
||||||
def set_progress_reporter(self, pr):
|
def set_progress_reporter(self, pr):
|
||||||
self.report_progress = pr
|
self.report_progress = pr
|
||||||
@ -105,29 +188,43 @@ class PRS505(Device):
|
|||||||
def card_prefix(self, end_session=True):
|
def card_prefix(self, end_session=True):
|
||||||
return self._card_prefix
|
return self._card_prefix
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _windows_space(cls, prefix):
|
||||||
|
if prefix is None:
|
||||||
|
return 0, 0
|
||||||
|
import win32file
|
||||||
|
sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters = \
|
||||||
|
win32file.GetDiskFreeSpace(prefix[:-1])
|
||||||
|
mult = sectors_per_cluster * bytes_per_sector
|
||||||
|
return total_clusters * mult, free_clusters * mult
|
||||||
|
|
||||||
def total_space(self, end_session=True):
|
def total_space(self, end_session=True):
|
||||||
|
msz = csz = 0
|
||||||
if not iswindows:
|
if not iswindows:
|
||||||
msz = 0
|
|
||||||
if self._main_prefix is not None:
|
if self._main_prefix is not None:
|
||||||
stats = os.statvfs(self._main_prefix)
|
stats = os.statvfs(self._main_prefix)
|
||||||
msz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
|
msz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
|
||||||
csz = 0
|
|
||||||
if self._card_prefix is not None:
|
if self._card_prefix is not None:
|
||||||
stats = os.statvfs(self._card_prefix)
|
stats = os.statvfs(self._card_prefix)
|
||||||
csz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
|
csz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
|
||||||
|
else:
|
||||||
|
msz = self._windows_space(self._main_prefix)[0]
|
||||||
|
csz = self._windows_space(self._card_prefix)[0]
|
||||||
|
|
||||||
return (msz, 0, csz)
|
return (msz, 0, csz)
|
||||||
|
|
||||||
def free_space(self, end_session=True):
|
def free_space(self, end_session=True):
|
||||||
|
msz = csz = 0
|
||||||
if not iswindows:
|
if not iswindows:
|
||||||
msz = 0
|
|
||||||
if self._main_prefix is not None:
|
if self._main_prefix is not None:
|
||||||
stats = os.statvfs(self._main_prefix)
|
stats = os.statvfs(self._main_prefix)
|
||||||
msz = stats.f_bsize * stats.f_bavail
|
msz = stats.f_bsize * stats.f_bavail
|
||||||
csz = 0
|
|
||||||
if self._card_prefix is not None:
|
if self._card_prefix is not None:
|
||||||
stats = os.statvfs(self._card_prefix)
|
stats = os.statvfs(self._card_prefix)
|
||||||
csz = stats.f_bsize * stats.f_bavail
|
csz = stats.f_bsize * stats.f_bavail
|
||||||
|
else:
|
||||||
|
msz = self._windows_space(self._main_prefix)[1]
|
||||||
|
csz = self._windows_space(self._card_prefix)[1]
|
||||||
|
|
||||||
return (msz, 0, csz)
|
return (msz, 0, csz)
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
## You should have received a copy of the GNU General Public License along
|
## You should have received a copy of the GNU General Public License along
|
||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
||||||
|
from libprs500 import iswindows
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
from PyQt4.QtCore import QThread, SIGNAL, QObject
|
from PyQt4.QtCore import QThread, SIGNAL, QObject
|
||||||
@ -42,10 +43,15 @@ class DeviceDetector(QThread):
|
|||||||
QThread.__init__(self)
|
QThread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
helper = None
|
||||||
|
if iswindows:
|
||||||
|
import wmi, pythoncom
|
||||||
|
pythoncom.CoInitialize()
|
||||||
|
helper = wmi.WMI()
|
||||||
while True:
|
while True:
|
||||||
for device in self.devices:
|
for device in self.devices:
|
||||||
try:
|
try:
|
||||||
connected = device[0].is_connected()
|
connected = device[0].is_connected(helper=helper)
|
||||||
except:
|
except:
|
||||||
connected = False
|
connected = False
|
||||||
if connected and not device[1]:
|
if connected and not device[1]:
|
||||||
|
@ -14,9 +14,15 @@
|
|||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
||||||
import shutil
|
import shutil
|
||||||
''' Post installation script for linux '''
|
''' Post installation script for linux '''
|
||||||
import sys, os, stat
|
import sys, os
|
||||||
|
|
||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
from libprs500 import __version__
|
from libprs500 import __version__, __appname__
|
||||||
|
|
||||||
|
from libprs500.devices.prs500.driver import PRS500
|
||||||
|
from libprs500.devices.prs505.driver import PRS505
|
||||||
|
|
||||||
|
DEVICES = (PRS500, PRS505)
|
||||||
|
|
||||||
def options(option_parser):
|
def options(option_parser):
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
@ -182,36 +188,24 @@ def setup_udev_rules():
|
|||||||
'''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="%s"\n'''%(group,)
|
'''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="%s"\n'''%(group,)
|
||||||
)
|
)
|
||||||
udev.close()
|
udev.close()
|
||||||
open('/usr/share/hal/fdi/policy/20thirdparty/10-libprs500.fdi', 'w').write(
|
fdi = open('/usr/share/hal/fdi/policy/20thirdparty/10-libprs500.fdi', 'w')
|
||||||
'''\
|
fdi.write('<?xml version="1.0" encoding="UTF-8"?>\n\n<deviceinfo version="0.2">\n')
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
for cls in DEVICES:
|
||||||
|
fdi.write(\
|
||||||
<deviceinfo version="0.2">
|
'''
|
||||||
<device>
|
<device>
|
||||||
<match key="info.category" string="volume">
|
<match key="usb_device.vendor_id" int="%(vendor_id)s">
|
||||||
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.vendor_id" int="0x054c">
|
<match key="usb_device.product_id" int="%(product_id)s">
|
||||||
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.product_id" int="0x031e">
|
<merge key="libprs500.deviceclass" type="string">%(cls)s</merge>
|
||||||
<match key="volume.is_partition" bool="false">
|
<append key="info.callouts.add" type="strlist">%(prog)s</merge>
|
||||||
<merge key="volume.label" type="string">Sony Reader Main Memory</merge>
|
|
||||||
</match>
|
|
||||||
</match>
|
|
||||||
</match>
|
</match>
|
||||||
</match>
|
</match>
|
||||||
</device>
|
</device>
|
||||||
<device>
|
'''%dict(cls=cls.__name__, vendor_id=cls.VENDOR_ID, product_id=cls.PRODUCT_ID,
|
||||||
<match key="info.category" string="volume">
|
prog=__appname__))
|
||||||
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.vendor_id" int="0x054c">
|
fdi.write('\n'+cls.get_fdi())
|
||||||
<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.product_id" int="0x031e">
|
fdi.write('\n</deviceinfo>\n')
|
||||||
<match key="volume.is_partition" bool="true">
|
fdi.close()
|
||||||
<merge key="volume.label" type="string">Sony Reader Storage Card</merge>
|
|
||||||
</match>
|
|
||||||
</match>
|
|
||||||
</match>
|
|
||||||
</match>
|
|
||||||
</device>
|
|
||||||
|
|
||||||
</deviceinfo>
|
|
||||||
''')
|
|
||||||
check_call('/etc/init.d/hald restart', shell=True)
|
check_call('/etc/init.d/hald restart', shell=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -446,11 +446,14 @@ setup(
|
|||||||
options = { 'py2exe' : {'compressed': 1,
|
options = { 'py2exe' : {'compressed': 1,
|
||||||
'optimize' : 2,
|
'optimize' : 2,
|
||||||
'dist_dir' : PY2EXE_DIR,
|
'dist_dir' : PY2EXE_DIR,
|
||||||
'includes' : ['sip', 'pkg_resources', 'PyQt4.QtSvg', 'mechanize', 'ClientForm'],
|
'includes' : ['sip', 'pkg_resources', 'PyQt4.QtSvg',
|
||||||
|
'mechanize', 'ClientForm', 'wmi',
|
||||||
|
'win32file', 'pythoncom'],
|
||||||
'packages' : ['PIL'],
|
'packages' : ['PIL'],
|
||||||
'excludes' : ["Tkconstants", "Tkinter", "tcl",
|
'excludes' : ["Tkconstants", "Tkinter", "tcl",
|
||||||
"_imagingtk", "ImageTk", "FixTk",
|
"_imagingtk", "ImageTk", "FixTk",
|
||||||
'pydoc'],
|
'pydoc'],
|
||||||
|
'dll_excludes' : ['mswsock.dll'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user