mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
5ea2953092
@ -1,19 +1,38 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__author__ = 'Kovid Goyal and Sujata Raman, Lorenzo Vigentini'
|
||||||
|
__copyright__ = '2009, Kovid Goyal and Sujata Raman'
|
||||||
|
__version__ = 'v1.02'
|
||||||
|
__date__ = '10, January 2010'
|
||||||
|
__description__ = 'Providing context and clarity on national and international news, peoples and cultures'
|
||||||
|
|
||||||
|
'''csmonitor.com'''
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from calibre import strftime
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class ChristianScienceMonitor(BasicNewsRecipe):
|
class ChristianScienceMonitor(BasicNewsRecipe):
|
||||||
|
|
||||||
title = 'Christian Science Monitor'
|
author = 'Kovid Goyal, Sujata Raman and Lorenzo Vigentini'
|
||||||
description = 'Providing context and clarity on national and international news, peoples and cultures'
|
description = 'Providing context and clarity on national and international news, peoples and cultures'
|
||||||
max_articles_per_feed = 20
|
|
||||||
__author__ = 'Kovid Goyal and Sujata Raman'
|
cover_url = 'http://www.csmonitor.com/extension/csm_base/design/csm_design/images/csmlogo_179x46.gif'
|
||||||
|
title = 'Christian Science Monitor'
|
||||||
|
publisher = 'The Christian Science Monitor'
|
||||||
|
category = 'News, politics, culture, economy, general interest'
|
||||||
|
|
||||||
language = 'en'
|
language = 'en'
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
no_stylesheets = True
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
use_embedded_content = False
|
|
||||||
|
|
||||||
|
oldest_article = 16
|
||||||
|
max_articles_per_feed = 20
|
||||||
|
use_embedded_content = False
|
||||||
|
recursion = 10
|
||||||
|
|
||||||
|
remove_javascript = True
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
|
||||||
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
|
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
|
||||||
@ -55,33 +74,15 @@ class ChristianScienceMonitor(BasicNewsRecipe):
|
|||||||
]
|
]
|
||||||
|
|
||||||
keep_only_tags = [
|
keep_only_tags = [
|
||||||
dict(name='div', attrs={'id':['story','main']}),
|
dict(name='div', attrs={'id':'mainColumn'}),
|
||||||
]
|
]
|
||||||
|
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name='div', attrs={'id':['story-tools','videoPlayer','storyRelatedBottom','enlarge-photo','photo-paginate']}),
|
dict(name='div', attrs={'id':['story-tools','videoPlayer','storyRelatedBottom','enlarge-photo','photo-paginate']}),
|
||||||
dict(name='div', attrs={'class':[ 'spacer3','divvy spacer7','comment','storyIncludeBottom']}),
|
dict(name='div', attrs={'class':['storyToolbar cfx','podStoryRel','spacer3','divvy spacer7','comment','storyIncludeBottom']}),
|
||||||
dict(name='ul', attrs={'class':[ 'centerliststories']}) ,
|
dict(name='ul', attrs={'class':[ 'centerliststories']}) ,
|
||||||
dict(name='form', attrs={'id':[ 'commentform']}) ,
|
dict(name='form', attrs={'id':[ 'commentform']}) ,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
remove_tags_after = [ dict(name='div', attrs={'class':[ 'ad csmAd']})]
|
||||||
|
|
||||||
def find_articles(self, section):
|
|
||||||
ans = []
|
|
||||||
for x in section.findAll('head4'):
|
|
||||||
title = ' '.join(x.findAll(text=True)).strip()
|
|
||||||
a = x.find('a')
|
|
||||||
if not a: continue
|
|
||||||
href = a['href']
|
|
||||||
ans.append({'title':title, 'url':href, 'description':'', 'date': strftime('%a, %d %b')})
|
|
||||||
|
|
||||||
#for x in ans:
|
|
||||||
# x['url'] += '/output/print'
|
|
||||||
return ans
|
|
||||||
|
|
||||||
def postprocess_html(self, soup, first_fetch):
|
|
||||||
html = soup.find('html')
|
|
||||||
if html is None:
|
|
||||||
return soup
|
|
||||||
html.extract()
|
|
||||||
return html
|
|
||||||
|
@ -48,7 +48,9 @@ class NYTimes(BasicNewsRecipe):
|
|||||||
return 'NY Times'
|
return 'NY Times'
|
||||||
|
|
||||||
def parse_index(self):
|
def parse_index(self):
|
||||||
|
self.encoding = 'cp1252'
|
||||||
soup = self.index_to_soup('http://www.nytimes.com/pages/todayspaper/index.html')
|
soup = self.index_to_soup('http://www.nytimes.com/pages/todayspaper/index.html')
|
||||||
|
self.encoding = None
|
||||||
|
|
||||||
def feed_title(div):
|
def feed_title(div):
|
||||||
return ''.join(div.findAll(text=True, recursive=False)).strip()
|
return ''.join(div.findAll(text=True, recursive=False)).strip()
|
||||||
|
@ -9,6 +9,8 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
|
|
||||||
class Slashdot(BasicNewsRecipe):
|
class Slashdot(BasicNewsRecipe):
|
||||||
title = u'Slashdot.org'
|
title = u'Slashdot.org'
|
||||||
|
description = '''Tech news. WARNING: This recipe downloads a lot
|
||||||
|
of content and can result in your IP being banned from slashdot.org'''
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
@ -5,7 +5,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
Device drivers.
|
Device drivers.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import sys, os, time, pprint
|
import sys, time, pprint
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ def strftime(epoch, zone=time.gmtime):
|
|||||||
|
|
||||||
def debug(ioreg_to_tmp=False, buf=None):
|
def debug(ioreg_to_tmp=False, buf=None):
|
||||||
from calibre.customize.ui import device_plugins
|
from calibre.customize.ui import device_plugins
|
||||||
from calibre.devices.scanner import DeviceScanner
|
from calibre.devices.scanner import DeviceScanner, win_pnp_drives
|
||||||
from calibre.constants import iswindows, isosx, __version__
|
from calibre.constants import iswindows, isosx, __version__
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
oldo, olde = sys.stdout, sys.stderr
|
oldo, olde = sys.stdout, sys.stderr
|
||||||
@ -37,19 +37,11 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
if buf is None:
|
if buf is None:
|
||||||
buf = StringIO()
|
buf = StringIO()
|
||||||
sys.stdout = sys.stderr = buf
|
sys.stdout = sys.stderr = buf
|
||||||
if iswindows:
|
|
||||||
import pythoncom
|
|
||||||
pythoncom.CoInitialize()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
out = partial(prints, file=buf)
|
out = partial(prints, file=buf)
|
||||||
out('Version:', __version__)
|
out('Version:', __version__)
|
||||||
wmi = Wmi =None
|
|
||||||
if iswindows:
|
|
||||||
wmi = __import__('wmi', globals(), locals(), [], -1)
|
|
||||||
Wmi = wmi.WMI(find_classes=False)
|
|
||||||
s = DeviceScanner()
|
s = DeviceScanner()
|
||||||
s.wmi = Wmi
|
|
||||||
s.scan()
|
s.scan()
|
||||||
devices = (s.devices)
|
devices = (s.devices)
|
||||||
if not iswindows:
|
if not iswindows:
|
||||||
@ -60,21 +52,9 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
out('USB devices on system:')
|
out('USB devices on system:')
|
||||||
out(pprint.pformat(devices))
|
out(pprint.pformat(devices))
|
||||||
if iswindows:
|
if iswindows:
|
||||||
drives = []
|
drives = win_pnp_drives(debug=True)
|
||||||
out('Drives detected:')
|
out('Drives detected:')
|
||||||
out('\t', '(ID, Partitions, Drive letter)')
|
out(pprint.pformat(drives))
|
||||||
for drive in Wmi.Win32_DiskDrive():
|
|
||||||
if drive.Partitions == 0:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
partition = drive.associators("Win32_DiskDriveToDiskPartition")[0]
|
|
||||||
logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0]
|
|
||||||
prefix = logical_disk.DeviceID+os.sep
|
|
||||||
drives.append((str(drive.PNPDeviceID), drive.Index, prefix))
|
|
||||||
except IndexError:
|
|
||||||
drives.append((str(drive.PNPDeviceID), 'No mount points found'))
|
|
||||||
for drive in drives:
|
|
||||||
out('\t', drive)
|
|
||||||
|
|
||||||
ioreg = None
|
ioreg = None
|
||||||
if isosx:
|
if isosx:
|
||||||
@ -84,13 +64,10 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
ioreg = 'Output from mount:\n\n'+mount+'\n\n'+ioreg
|
ioreg = 'Output from mount:\n\n'+mount+'\n\n'+ioreg
|
||||||
connected_devices = []
|
connected_devices = []
|
||||||
for dev in device_plugins():
|
for dev in device_plugins():
|
||||||
owmi = getattr(dev, 'wmi', None)
|
|
||||||
dev.wmi = Wmi
|
|
||||||
out('Looking for', dev.__class__.__name__)
|
out('Looking for', dev.__class__.__name__)
|
||||||
connected, det = s.is_device_connected(dev, debug=True)
|
connected, det = s.is_device_connected(dev, debug=True)
|
||||||
if connected:
|
if connected:
|
||||||
connected_devices.append((dev, det))
|
connected_devices.append((dev, det))
|
||||||
dev.wmi = owmi
|
|
||||||
|
|
||||||
errors = {}
|
errors = {}
|
||||||
success = False
|
success = False
|
||||||
@ -102,8 +79,6 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
out(' ')
|
out(' ')
|
||||||
for dev, det in connected_devices:
|
for dev, det in connected_devices:
|
||||||
out('Trying to open', dev.name, '...', end=' ')
|
out('Trying to open', dev.name, '...', end=' ')
|
||||||
owmi = getattr(dev, 'wmi', None)
|
|
||||||
dev.wmi = Wmi
|
|
||||||
try:
|
try:
|
||||||
dev.reset(detected_device=det)
|
dev.reset(detected_device=det)
|
||||||
dev.open()
|
dev.open()
|
||||||
@ -113,8 +88,6 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
errors[dev] = traceback.format_exc()
|
errors[dev] = traceback.format_exc()
|
||||||
out('failed')
|
out('failed')
|
||||||
continue
|
continue
|
||||||
finally:
|
|
||||||
dev.wmi = owmi
|
|
||||||
success = True
|
success = True
|
||||||
if hasattr(dev, '_main_prefix'):
|
if hasattr(dev, '_main_prefix'):
|
||||||
out('Main memory:', repr(dev._main_prefix))
|
out('Main memory:', repr(dev._main_prefix))
|
||||||
@ -142,7 +115,4 @@ def debug(ioreg_to_tmp=False, buf=None):
|
|||||||
finally:
|
finally:
|
||||||
sys.stdout = oldo
|
sys.stdout = oldo
|
||||||
sys.stderr = olde
|
sys.stderr = olde
|
||||||
if iswindows:
|
|
||||||
import pythoncom
|
|
||||||
pythoncom.CoUninitialize()
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class DevicePlugin(Plugin):
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def is_usb_connected_windows(self, devices_on_system, pnp_id_iterator, debug=False):
|
def is_usb_connected_windows(self, devices_on_system, debug=False):
|
||||||
|
|
||||||
def id_iterator():
|
def id_iterator():
|
||||||
if hasattr(self.VENDOR_ID, 'keys'):
|
if hasattr(self.VENDOR_ID, 'keys'):
|
||||||
@ -85,7 +85,7 @@ class DevicePlugin(Plugin):
|
|||||||
self.test_bcd_windows(device_id, bcd):
|
self.test_bcd_windows(device_id, bcd):
|
||||||
if debug:
|
if debug:
|
||||||
self.print_usb_device_info(device_id)
|
self.print_usb_device_info(device_id)
|
||||||
if self.can_handle_windows(device_id, pnp_id_iterator, debug=debug):
|
if self.can_handle_windows(device_id, debug=debug):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ class DevicePlugin(Plugin):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_usb_connected(self, devices_on_system, pnp_id_iterator, debug=False):
|
def is_usb_connected(self, devices_on_system, debug=False):
|
||||||
'''
|
'''
|
||||||
Return True, device_info if a device handled by this plugin is currently connected.
|
Return True, device_info if a device handled by this plugin is currently connected.
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ class DevicePlugin(Plugin):
|
|||||||
'''
|
'''
|
||||||
if iswindows:
|
if iswindows:
|
||||||
return self.is_usb_connected_windows(devices_on_system,
|
return self.is_usb_connected_windows(devices_on_system,
|
||||||
pnp_id_iterator, debug=debug), None
|
debug=debug), None
|
||||||
|
|
||||||
vendors_on_system = set([x[0] for x in devices_on_system])
|
vendors_on_system = set([x[0] for x in devices_on_system])
|
||||||
vendors = self.VENDOR_ID if hasattr(self.VENDOR_ID, '__len__') else [self.VENDOR_ID]
|
vendors = self.VENDOR_ID if hasattr(self.VENDOR_ID, '__len__') else [self.VENDOR_ID]
|
||||||
@ -147,7 +147,7 @@ class DevicePlugin(Plugin):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def can_handle_windows(self, device_id, pnp_id_iterator, debug=False):
|
def can_handle_windows(self, device_id, debug=False):
|
||||||
'''
|
'''
|
||||||
Optional method to perform further checks on a device to see if this driver
|
Optional method to perform further checks on a device to see if this driver
|
||||||
is capable of handling it. If it is not it should return False. This method
|
is capable of handling it. If it is not it should return False. This method
|
||||||
|
@ -9,7 +9,7 @@ For usage information run the script.
|
|||||||
import StringIO, sys, time, os
|
import StringIO, sys, time, os
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
from calibre import __version__, iswindows, __appname__
|
from calibre import __version__, __appname__
|
||||||
from calibre.devices.errors import PathError
|
from calibre.devices.errors import PathError
|
||||||
from calibre.utils.terminfo import TerminalController
|
from calibre.utils.terminfo import TerminalController
|
||||||
from calibre.devices.errors import ArgumentError, DeviceError, DeviceLocked
|
from calibre.devices.errors import ArgumentError, DeviceError, DeviceLocked
|
||||||
@ -198,14 +198,9 @@ def main():
|
|||||||
args = args[1:]
|
args = args[1:]
|
||||||
dev = None
|
dev = None
|
||||||
scanner = DeviceScanner()
|
scanner = DeviceScanner()
|
||||||
if iswindows:
|
|
||||||
import wmi, pythoncom
|
|
||||||
pythoncom.CoInitialize()
|
|
||||||
scanner.wmi = wmi.WMI(find_classes=False)
|
|
||||||
scanner.scan()
|
scanner.scan()
|
||||||
connected_devices = []
|
connected_devices = []
|
||||||
for d in device_plugins():
|
for d in device_plugins():
|
||||||
d.wmi = scanner.wmi
|
|
||||||
ok, det = scanner.is_device_connected(d)
|
ok, det = scanner.is_device_connected(d)
|
||||||
if ok:
|
if ok:
|
||||||
dev = d
|
dev = d
|
||||||
|
@ -6,6 +6,7 @@ manner.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
from threading import RLock
|
||||||
|
|
||||||
from calibre import iswindows, isosx, plugins, islinux
|
from calibre import iswindows, isosx, plugins, islinux
|
||||||
|
|
||||||
@ -22,6 +23,54 @@ elif isosx:
|
|||||||
except:
|
except:
|
||||||
raise RuntimeError('Failed to load the usbobserver plugin: %s'%plugins['usbobserver'][1])
|
raise RuntimeError('Failed to load the usbobserver plugin: %s'%plugins['usbobserver'][1])
|
||||||
|
|
||||||
|
class WinPNPScanner(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.scanner = None
|
||||||
|
if iswindows:
|
||||||
|
self.scanner = plugins['winutil'][0].get_removable_drives
|
||||||
|
self.lock = RLock()
|
||||||
|
|
||||||
|
def drive_is_ok(self, letter, debug=False):
|
||||||
|
import win32api, win32file
|
||||||
|
with self.lock:
|
||||||
|
oldError = win32api.SetErrorMode(1) #SEM_FAILCRITICALERRORS = 1
|
||||||
|
try:
|
||||||
|
ans = True
|
||||||
|
try:
|
||||||
|
win32file.GetDiskFreeSpaceEx(letter+':\\')
|
||||||
|
except:
|
||||||
|
ans = False
|
||||||
|
return ans
|
||||||
|
finally:
|
||||||
|
win32api.SetErrorMode(oldError)
|
||||||
|
|
||||||
|
def __call__(self, debug=False):
|
||||||
|
if self.scanner is None:
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
drives = self.scanner(debug)
|
||||||
|
except:
|
||||||
|
drives = {}
|
||||||
|
if debug:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
remove = set([])
|
||||||
|
for letter in drives:
|
||||||
|
if not self.drive_is_ok(letter, debug=debug):
|
||||||
|
remove.add(letter)
|
||||||
|
for letter in remove:
|
||||||
|
drives.pop(letter)
|
||||||
|
ans = {}
|
||||||
|
for key, val in drives.items():
|
||||||
|
val = [x.upper() for x in val]
|
||||||
|
val = [x for x in val if 'USBSTOR' in x]
|
||||||
|
if val:
|
||||||
|
ans[key+':\\'] = val[-1]
|
||||||
|
return ans
|
||||||
|
|
||||||
|
win_pnp_drives = WinPNPScanner()
|
||||||
|
|
||||||
class LinuxScanner(object):
|
class LinuxScanner(object):
|
||||||
|
|
||||||
SYSFS_PATH = os.environ.get('SYSFS_PATH', '/sys')
|
SYSFS_PATH = os.environ.get('SYSFS_PATH', '/sys')
|
||||||
@ -85,26 +134,13 @@ class DeviceScanner(object):
|
|||||||
raise RuntimeError('DeviceScanner requires the /sys filesystem to work.')
|
raise RuntimeError('DeviceScanner requires the /sys filesystem to work.')
|
||||||
self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner
|
self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner
|
||||||
self.devices = []
|
self.devices = []
|
||||||
self.wmi = None
|
|
||||||
self.pnp_ids = set([])
|
|
||||||
self.rescan_pnp_ids = True
|
|
||||||
|
|
||||||
def scan(self):
|
def scan(self):
|
||||||
'''Fetch list of connected USB devices from operating system'''
|
'''Fetch list of connected USB devices from operating system'''
|
||||||
self.devices = self.scanner()
|
self.devices = self.scanner()
|
||||||
if self.rescan_pnp_ids:
|
|
||||||
self.pnp_ids = set([])
|
|
||||||
|
|
||||||
def pnp_id_iterator(self):
|
|
||||||
if self.wmi is not None and not self.pnp_ids:
|
|
||||||
for drive in self.wmi.Win32_DiskDrive():
|
|
||||||
if drive.Partitions > 0:
|
|
||||||
self.pnp_ids.add(str(drive.PNPDeviceID))
|
|
||||||
for x in self.pnp_ids:
|
|
||||||
yield x
|
|
||||||
|
|
||||||
def is_device_connected(self, device, debug=False):
|
def is_device_connected(self, device, debug=False):
|
||||||
return device.is_usb_connected(self.devices, self.pnp_id_iterator, debug=debug)
|
return device.is_usb_connected(self.devices, debug=debug)
|
||||||
|
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
|
@ -203,18 +203,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def windows_get_drive_prefix(self, drive):
|
|
||||||
prefix = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
partition = drive.associators("Win32_DiskDriveToDiskPartition")[0]
|
|
||||||
logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0]
|
|
||||||
prefix = logical_disk.DeviceID + os.sep
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return prefix
|
|
||||||
|
|
||||||
def windows_sort_drives(self, drives):
|
def windows_sort_drives(self, drives):
|
||||||
'''
|
'''
|
||||||
Called to disambiguate main memory and storage card for devices that
|
Called to disambiguate main memory and storage card for devices that
|
||||||
@ -223,8 +211,10 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
'''
|
'''
|
||||||
return drives
|
return drives
|
||||||
|
|
||||||
def can_handle_windows(self, device_id, pnp_id_iterator, debug=False):
|
def can_handle_windows(self, device_id, debug=False):
|
||||||
for pnp_id in pnp_id_iterator():
|
from calibre.devices.scanner import win_pnp_drives
|
||||||
|
drives = win_pnp_drives()
|
||||||
|
for pnp_id in drives.values():
|
||||||
if self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM'):
|
if self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM'):
|
||||||
return True
|
return True
|
||||||
if debug:
|
if debug:
|
||||||
@ -232,29 +222,20 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def open_windows(self):
|
def open_windows(self):
|
||||||
|
from calibre.devices.scanner import win_pnp_drives
|
||||||
|
|
||||||
def matches_q(drive, attr):
|
time.sleep(5)
|
||||||
q = getattr(self, attr)
|
|
||||||
if q is None: return False
|
|
||||||
if isinstance(q, basestring):
|
|
||||||
q = [q]
|
|
||||||
pnp = str(drive.PNPDeviceID)
|
|
||||||
for x in q:
|
|
||||||
if x in pnp:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
time.sleep(8)
|
|
||||||
drives = {}
|
drives = {}
|
||||||
c = self.wmi
|
for drive, pnp_id in win_pnp_drives().items():
|
||||||
for drive in c.Win32_DiskDrive():
|
if self.windows_match_device(pnp_id, 'WINDOWS_CARD_A_MEM') and \
|
||||||
pnp_id = str(drive.PNPDeviceID)
|
not drives.get('carda', False):
|
||||||
if self.windows_match_device(pnp_id, 'WINDOWS_CARD_A_MEM') and not drives.get('carda', None):
|
drives['carda'] = drive
|
||||||
drives['carda'] = self.windows_get_drive_prefix(drive)
|
elif self.windows_match_device(pnp_id, 'WINDOWS_CARD_B_MEM') and \
|
||||||
elif self.windows_match_device(pnp_id, 'WINDOWS_CARD_B_MEM') and not drives.get('cardb', None):
|
not drives.get('cardb', False):
|
||||||
drives['cardb'] = self.windows_get_drive_prefix(drive)
|
drives['cardb'] = drive
|
||||||
elif self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM') and not drives.get('main', None):
|
elif self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM') and \
|
||||||
drives['main'] = self.windows_get_drive_prefix(drive)
|
not drives.get('main', False):
|
||||||
|
drives['main'] = drive
|
||||||
|
|
||||||
if 'main' in drives.keys() and 'carda' in drives.keys() and \
|
if 'main' in drives.keys() and 'carda' in drives.keys() and \
|
||||||
'cardb' in drives.keys():
|
'cardb' in drives.keys():
|
||||||
|
@ -168,6 +168,7 @@ class Stylizer(object):
|
|||||||
self.rules = rules
|
self.rules = rules
|
||||||
self._styles = {}
|
self._styles = {}
|
||||||
class_sel_pat = re.compile(r'\.[a-z]+', re.IGNORECASE)
|
class_sel_pat = re.compile(r'\.[a-z]+', re.IGNORECASE)
|
||||||
|
capital_sel_pat = re.compile(r'h|[A-Z]+')
|
||||||
for _, _, cssdict, text, _ in rules:
|
for _, _, cssdict, text, _ in rules:
|
||||||
try:
|
try:
|
||||||
selector = CSSSelector(text)
|
selector = CSSSelector(text)
|
||||||
@ -176,6 +177,15 @@ class Stylizer(object):
|
|||||||
SelectorSyntaxError):
|
SelectorSyntaxError):
|
||||||
continue
|
continue
|
||||||
matches = selector(tree)
|
matches = selector(tree)
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
ntext = capital_sel_pat.sub(lambda m: m.group().lower(), text)
|
||||||
|
if ntext != text:
|
||||||
|
self.logger.warn('Transformed CSS selector', text, 'to',
|
||||||
|
ntext)
|
||||||
|
selector = CSSSelector(ntext)
|
||||||
|
matches = selector(tree)
|
||||||
|
|
||||||
if not matches and class_sel_pat.match(text):
|
if not matches and class_sel_pat.match(text):
|
||||||
found = False
|
found = False
|
||||||
for x in tree.xpath('//*[@class]'):
|
for x in tree.xpath('//*[@class]'):
|
||||||
|
@ -13,7 +13,6 @@ from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
|
|||||||
from calibre.customize.ui import available_input_formats, available_output_formats, \
|
from calibre.customize.ui import available_input_formats, available_output_formats, \
|
||||||
device_plugins
|
device_plugins
|
||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
from calibre.constants import iswindows
|
|
||||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||||
from calibre.utils.ipc.job import BaseJob
|
from calibre.utils.ipc.job import BaseJob
|
||||||
from calibre.devices.scanner import DeviceScanner
|
from calibre.devices.scanner import DeviceScanner
|
||||||
@ -85,7 +84,6 @@ class DeviceManager(Thread):
|
|||||||
self.job_manager = job_manager
|
self.job_manager = job_manager
|
||||||
self.current_job = None
|
self.current_job = None
|
||||||
self.scanner = DeviceScanner()
|
self.scanner = DeviceScanner()
|
||||||
self.wmi = None
|
|
||||||
self.connected_device = None
|
self.connected_device = None
|
||||||
self.ejected_devices = set([])
|
self.ejected_devices = set([])
|
||||||
|
|
||||||
@ -133,7 +131,6 @@ class DeviceManager(Thread):
|
|||||||
self.connected_device = None
|
self.connected_device = None
|
||||||
|
|
||||||
def detect_device(self):
|
def detect_device(self):
|
||||||
self.scanner.rescan_pnp_ids = not self.is_device_connected
|
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
if self.is_device_connected:
|
if self.is_device_connected:
|
||||||
connected, detected_device = \
|
connected, detected_device = \
|
||||||
@ -170,30 +167,18 @@ class DeviceManager(Thread):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if iswindows:
|
while self.keep_going:
|
||||||
import pythoncom
|
self.detect_device()
|
||||||
pythoncom.CoInitialize()
|
while True:
|
||||||
wmi = __import__('wmi', globals(), locals(), [], -1)
|
job = self.next()
|
||||||
self.wmi = wmi.WMI(find_classes=False)
|
if job is not None:
|
||||||
self.scanner.wmi = self.wmi
|
self.current_job = job
|
||||||
for x in self.devices:
|
self.device.set_progress_reporter(job.report_progress)
|
||||||
x.wmi = self.wmi
|
self.current_job.run()
|
||||||
try:
|
self.current_job = None
|
||||||
while self.keep_going:
|
else:
|
||||||
self.detect_device()
|
break
|
||||||
while True:
|
time.sleep(self.sleep_time)
|
||||||
job = self.next()
|
|
||||||
if job is not None:
|
|
||||||
self.current_job = job
|
|
||||||
self.device.set_progress_reporter(job.report_progress)
|
|
||||||
self.current_job.run()
|
|
||||||
self.current_job = None
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
time.sleep(self.sleep_time)
|
|
||||||
finally:
|
|
||||||
if iswindows:
|
|
||||||
pythoncom.CoUninitialize()
|
|
||||||
|
|
||||||
|
|
||||||
def create_job(self, func, done, description, args=[], kwargs={}):
|
def create_job(self, func, done, description, args=[], kwargs={}):
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>838</width>
|
<width>884</width>
|
||||||
<height>730</height>
|
<height>730</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -89,7 +89,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>562</width>
|
<width>608</width>
|
||||||
<height>683</height>
|
<height>683</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -171,7 +171,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
if self._add_formats(paths):
|
if self._add_formats(paths):
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def remove_format(self, x=None):
|
def remove_format(self, *args):
|
||||||
rows = self.formats.selectionModel().selectedRows(0)
|
rows = self.formats.selectionModel().selectedRows(0)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
self.formats.takeItem(row.row())
|
self.formats.takeItem(row.row())
|
||||||
|
@ -23,9 +23,10 @@ KEY = Qt.UserRole + 3
|
|||||||
|
|
||||||
class Customize(QFrame, Ui_Frame):
|
class Customize(QFrame, Ui_Frame):
|
||||||
|
|
||||||
def __init__(self, dup_check, parent=None):
|
def __init__(self, index, dup_check, parent=None):
|
||||||
QFrame.__init__(self, parent)
|
QFrame.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
self.data_model = index.model()
|
||||||
self.setFocusPolicy(Qt.StrongFocus)
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
self.setAutoFillBackground(True)
|
self.setAutoFillBackground(True)
|
||||||
self.custom.toggled.connect(self.custom_toggled)
|
self.custom.toggled.connect(self.custom_toggled)
|
||||||
@ -86,12 +87,21 @@ class Delegate(QStyledItemDelegate):
|
|||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QStyledItemDelegate.__init__(self, parent)
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
self.editing_indices = {}
|
self.editing_indices = {}
|
||||||
|
self.closeEditor.connect(self.editing_done)
|
||||||
|
|
||||||
def to_doc(self, index):
|
def to_doc(self, index):
|
||||||
doc = QTextDocument()
|
doc = QTextDocument()
|
||||||
doc.setHtml(index.data().toString())
|
doc.setHtml(index.data().toString())
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
def editing_done(self, editor, hint):
|
||||||
|
remove = None
|
||||||
|
for row, w in self.editing_indices.items():
|
||||||
|
remove = (row, w.data_model.index(row))
|
||||||
|
if remove is not None:
|
||||||
|
self.editing_indices.pop(remove[0])
|
||||||
|
self.sizeHintChanged.emit(remove[1])
|
||||||
|
|
||||||
def sizeHint(self, option, index):
|
def sizeHint(self, option, index):
|
||||||
if index.row() in self.editing_indices:
|
if index.row() in self.editing_indices:
|
||||||
return QSize(200, 200)
|
return QSize(200, 200)
|
||||||
@ -111,7 +121,7 @@ class Delegate(QStyledItemDelegate):
|
|||||||
painter.restore()
|
painter.restore()
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
w = Customize(index.model().duplicate_check, parent=parent)
|
w = Customize(index, index.model().duplicate_check, parent=parent)
|
||||||
self.editing_indices[index.row()] = w
|
self.editing_indices[index.row()] = w
|
||||||
self.sizeHintChanged.emit(index)
|
self.sizeHintChanged.emit(index)
|
||||||
return w
|
return w
|
||||||
@ -135,8 +145,6 @@ class Delegate(QStyledItemDelegate):
|
|||||||
setattr(editor, 'shortcut%d'%(x+1), seq)
|
setattr(editor, 'shortcut%d'%(x+1), seq)
|
||||||
|
|
||||||
def setModelData(self, editor, model, index):
|
def setModelData(self, editor, model, index):
|
||||||
self.editing_indices.pop(index.row())
|
|
||||||
self.sizeHintChanged.emit(index)
|
|
||||||
self.closeEditor.emit(editor, self.NoHint)
|
self.closeEditor.emit(editor, self.NoHint)
|
||||||
custom = []
|
custom = []
|
||||||
if editor.custom.isChecked():
|
if editor.custom.isChecked():
|
||||||
|
@ -141,8 +141,8 @@ class FormatList(QListWidget):
|
|||||||
if event.key() == Qt.Key_Delete:
|
if event.key() == Qt.Key_Delete:
|
||||||
self.emit(SIGNAL('delete_format()'))
|
self.emit(SIGNAL('delete_format()'))
|
||||||
else:
|
else:
|
||||||
QListWidget.keyPressEvent(self, event)
|
return QListWidget.keyPressEvent(self, event)
|
||||||
|
|
||||||
|
|
||||||
class ImageView(QLabel):
|
class ImageView(QLabel):
|
||||||
|
|
||||||
|
@ -204,23 +204,22 @@ get_registry_property(HDEVINFO hDevInfo, DWORD index, DWORD property, BOOL *iter
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
check_device_id(LPTSTR buffer, unsigned int vid, unsigned int pid) {
|
check_device_id(LPTSTR buffer, unsigned int vid, unsigned int pid) {
|
||||||
WCHAR xVid[9], dVid[9], xPid[9], dPid[9];
|
WCHAR xVid[9], dVid[9], xPid[9], dPid[9];
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
swprintf(xVid, L"vid_%4.4x", vid);
|
_snwprintf_s(xVid, 9, _TRUNCATE, L"vid_%4.4x", vid);
|
||||||
swprintf(dVid, L"vid_%4.4d", vid);
|
_snwprintf_s(dVid, 9, _TRUNCATE, L"vid_%4.4d", vid);
|
||||||
swprintf(xPid, L"pid_%4.4x", pid);
|
_snwprintf_s(xPid, 9, _TRUNCATE, L"pid_%4.4x", pid);
|
||||||
swprintf(dPid, L"pid_%4.4d", pid);
|
_snwprintf_s(dPid, 9, _TRUNCATE, L"pid_%4.4d", pid);
|
||||||
|
|
||||||
for (j = 0; j < wcslen(buffer); j++) buffer[j] = tolower(buffer[j]);
|
for (j = 0; j < wcslen(buffer); j++) buffer[j] = tolower(buffer[j]);
|
||||||
|
|
||||||
return ( (wcsstr(buffer, xVid) != NULL || wcsstr(buffer, dVid) != NULL ) &&
|
return ( (wcsstr(buffer, xVid) != NULL || wcsstr(buffer, dVid) != NULL ) &&
|
||||||
(wcsstr(buffer, xPid) != NULL || wcsstr(buffer, dPid) != NULL )
|
(wcsstr(buffer, xPid) != NULL || wcsstr(buffer, dPid) != NULL )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static HDEVINFO
|
static HDEVINFO
|
||||||
create_device_info_set(LPGUID guid, PCTSTR enumerator, HWND parent, DWORD flags) {
|
create_device_info_set(LPGUID guid, PCTSTR enumerator, HWND parent, DWORD flags) {
|
||||||
HDEVINFO hDevInfo;
|
HDEVINFO hDevInfo;
|
||||||
@ -286,7 +285,7 @@ get_all_removable_disks(struct tagDrives *g_drives)
|
|||||||
if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE))
|
if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE))
|
||||||
{
|
{
|
||||||
g_drives[g_count].letter = caDrive[0];
|
g_drives[g_count].letter = caDrive[0];
|
||||||
wcscpy(g_drives[g_count].volume, volume);
|
wcscpy_s(g_drives[g_count].volume, BUFSIZE, volume);
|
||||||
g_count ++;
|
g_count ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,15 +514,17 @@ winutil_eject_drive(PyObject *self, PyObject *args) {
|
|||||||
|
|
||||||
|
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA
|
PSP_DEVICE_INTERFACE_DETAIL_DATA
|
||||||
get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_id,
|
get_device_ancestors(HDEVINFO hDevInfo, DWORD index, PyObject *candidates, BOOL *iterate, BOOL ddebug) {
|
||||||
BOOL *iterate) {
|
|
||||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||||
SP_DEVINFO_DATA devInfoData;
|
SP_DEVINFO_DATA devInfoData;
|
||||||
BOOL status;
|
BOOL status;
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||||
DWORD interfaceDetailDataSize,
|
DWORD interfaceDetailDataSize,
|
||||||
reqSize;
|
reqSize;
|
||||||
DEVINST parent;
|
DEVINST parent, pos;
|
||||||
|
wchar_t temp[BUFSIZE];
|
||||||
|
int i;
|
||||||
|
PyObject *devid;
|
||||||
|
|
||||||
interfaceData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
|
interfaceData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
|
||||||
devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
|
devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
|
||||||
@ -549,7 +550,7 @@ get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_i
|
|||||||
);
|
);
|
||||||
|
|
||||||
interfaceDetailDataSize = reqSize;
|
interfaceDetailDataSize = reqSize;
|
||||||
interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+10);
|
interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+50);
|
||||||
if ( interfaceDetailData == NULL ) {
|
if ( interfaceDetailData == NULL ) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -563,38 +564,49 @@ get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_i
|
|||||||
interfaceDetailDataSize, // Interface detail data size
|
interfaceDetailDataSize, // Interface detail data size
|
||||||
&reqSize, // Buffer size required to get the detail data
|
&reqSize, // Buffer size required to get the detail data
|
||||||
&devInfoData); // Interface device info
|
&devInfoData); // Interface device info
|
||||||
|
if (ddebug) printf("Getting ancestors\n"); fflush(stdout);
|
||||||
|
|
||||||
if ( status == FALSE ) {PyErr_SetFromWindowsErr(0); PyMem_Free(interfaceDetailData); return NULL;}
|
if ( status == FALSE ) {PyErr_SetFromWindowsErr(0); PyMem_Free(interfaceDetailData); return NULL;}
|
||||||
|
|
||||||
// Get the device instance of parent. This points to USBSTOR.
|
pos = devInfoData.DevInst;
|
||||||
CM_Get_Parent(&parent, devInfoData.DevInst, 0);
|
|
||||||
// Get the device ID of the USBSTORAGE volume
|
for(i = 0; i < 10; i++) {
|
||||||
CM_Get_Device_ID(parent, volume_id, BUFSIZE, 0);
|
// Get the device instance of parent.
|
||||||
// Get the device instance of grand parent. This points to USB root.
|
if (CM_Get_Parent(&parent, pos, 0) != CR_SUCCESS) break;
|
||||||
CM_Get_Parent(&parent, parent, 0);
|
if (CM_Get_Device_ID(parent, temp, BUFSIZE, 0) == CR_SUCCESS) {
|
||||||
// Get the device ID of the USB root.
|
if (ddebug) wprintf(L"device id: %s\n", temp); fflush(stdout);
|
||||||
CM_Get_Device_ID(parent, buf, BUFSIZE, 0);
|
devid = PyUnicode_FromWideChar(temp, wcslen(temp));
|
||||||
|
if (devid) {
|
||||||
|
PyList_Append(candidates, devid);
|
||||||
|
Py_DECREF(devid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos = parent;
|
||||||
|
}
|
||||||
|
|
||||||
return interfaceDetailData;
|
return interfaceDetailData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
winutil_get_mounted_volumes_for_usb_device(PyObject *self, PyObject *args) {
|
winutil_get_removable_drives(PyObject *self, PyObject *args) {
|
||||||
unsigned int vid, pid, length, j;
|
HDEVINFO hDevInfo;
|
||||||
HDEVINFO hDevInfo;
|
BOOL iterate = TRUE, ddebug = FALSE;
|
||||||
BOOL iterate = TRUE;
|
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
WCHAR buf[BUFSIZE], volume[BUFSIZE], volume_id[BUFSIZE];
|
unsigned int j, length;
|
||||||
|
WCHAR volume[BUFSIZE];
|
||||||
struct tagDrives g_drives[MAX_DRIVES];
|
struct tagDrives g_drives[MAX_DRIVES];
|
||||||
PyObject *volumes, *key, *val;
|
PyObject *volumes, *key, *candidates, *pdebug = Py_False, *temp;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "ii", &vid, &pid)) {
|
if (!PyArg_ParseTuple(args, "|O", &pdebug)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddebug = PyObject_IsTrue(pdebug);
|
||||||
|
|
||||||
volumes = PyDict_New();
|
volumes = PyDict_New();
|
||||||
if (volumes == NULL) return NULL;
|
if (volumes == NULL) return NULL;
|
||||||
|
|
||||||
|
|
||||||
for (j = 0; j < MAX_DRIVES; j++) g_drives[j].letter = 0;
|
for (j = 0; j < MAX_DRIVES; j++) g_drives[j].letter = 0;
|
||||||
|
|
||||||
@ -609,47 +621,44 @@ winutil_get_mounted_volumes_for_usb_device(PyObject *self, PyObject *args) {
|
|||||||
|
|
||||||
// Enumerate through the set
|
// Enumerate through the set
|
||||||
for (i=0; iterate; i++) {
|
for (i=0; iterate; i++) {
|
||||||
interfaceDetailData = get_device_grandparent(hDevInfo, i, buf, volume_id, &iterate);
|
candidates = PyList_New(0);
|
||||||
|
if (candidates == NULL) return PyErr_NoMemory();
|
||||||
|
|
||||||
|
interfaceDetailData = get_device_ancestors(hDevInfo, i, candidates, &iterate, ddebug);
|
||||||
if (interfaceDetailData == NULL) {
|
if (interfaceDetailData == NULL) {
|
||||||
PyErr_Print(); continue;
|
PyErr_Print(); continue;
|
||||||
}
|
}
|
||||||
debug("Device num: %d Device Id: %ws\n\n", i, buf);
|
|
||||||
if (check_device_id(buf, vid, pid)) {
|
|
||||||
debug("Device matches\n\n");
|
|
||||||
length = wcslen(interfaceDetailData->DevicePath);
|
|
||||||
interfaceDetailData->DevicePath[length] = '\\';
|
|
||||||
interfaceDetailData->DevicePath[length+1] = 0;
|
|
||||||
if(GetVolumeNameForVolumeMountPoint(interfaceDetailData->DevicePath, volume, BUFSIZE)) {
|
|
||||||
|
|
||||||
for(j = 0; j < MAX_DRIVES; j++) {
|
length = wcslen(interfaceDetailData->DevicePath);
|
||||||
// Compare volume mount point with the one stored earlier.
|
interfaceDetailData->DevicePath[length] = L'\\';
|
||||||
// If both match, return the corresponding drive letter.
|
interfaceDetailData->DevicePath[length+1] = 0;
|
||||||
if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0)
|
|
||||||
{
|
if (ddebug) wprintf(L"Device path: %s\n", interfaceDetailData->DevicePath); fflush(stdout);
|
||||||
key = PyUnicode_FromWideChar(volume_id, wcslen(volume_id));
|
// On Vista+ DevicePath contains the information we need.
|
||||||
val = PyString_FromFormat("%c", (char)g_drives[j].letter);
|
temp = PyUnicode_FromWideChar(interfaceDetailData->DevicePath, length);
|
||||||
if (key == NULL || val == NULL) {
|
if (temp == NULL) return PyErr_NoMemory();
|
||||||
PyErr_NoMemory();
|
PyList_Append(candidates, temp);
|
||||||
PyMem_Free(interfaceDetailData);
|
Py_DECREF(temp);
|
||||||
return NULL;
|
if(GetVolumeNameForVolumeMountPointW(interfaceDetailData->DevicePath, volume, BUFSIZE)) {
|
||||||
}
|
if (ddebug) wprintf(L"Volume: %s\n", volume); fflush(stdout);
|
||||||
PyDict_SetItem(volumes, key, val);
|
|
||||||
}
|
for(j = 0; j < MAX_DRIVES; j++) {
|
||||||
|
if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0) {
|
||||||
|
if (ddebug) printf("Found drive: %c\n", (char)g_drives[j].letter); fflush(stdout);
|
||||||
|
key = PyBytes_FromFormat("%c", (char)g_drives[j].letter);
|
||||||
|
if (key == NULL) return PyErr_NoMemory();
|
||||||
|
PyDict_SetItem(volumes, key, candidates);
|
||||||
|
Py_DECREF(candidates);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
debug("Failed to get volume name for volume mount point:\n");
|
|
||||||
if (DEBUG) debug("%ws\n\n", format_last_error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyMem_Free(interfaceDetailData);
|
|
||||||
}
|
}
|
||||||
|
PyMem_Free(interfaceDetailData);
|
||||||
} //for
|
} //for
|
||||||
|
|
||||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||||
return volumes;
|
return volumes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -876,21 +885,22 @@ static PyMethodDef WinutilMethods[] = {
|
|||||||
"script being run. So to replace sys.argv, you should use "
|
"script being run. So to replace sys.argv, you should use "
|
||||||
"sys.argv[1:] = argv()[1:]."},
|
"sys.argv[1:] = argv()[1:]."},
|
||||||
|
|
||||||
{"is_usb_device_connected", winutil_is_usb_device_connected, METH_VARARGS,
|
{"is_usb_device_connected", winutil_is_usb_device_connected, METH_VARARGS,
|
||||||
"is_usb_device_connected(vid, pid) -> bool\n\n"
|
"is_usb_device_connected(vid, pid) -> bool\n\n"
|
||||||
"Check if the USB device identified by VendorID: vid (integer) and"
|
"Check if the USB device identified by VendorID: vid (integer) and"
|
||||||
" ProductID: pid (integer) is currently connected."},
|
" ProductID: pid (integer) is currently connected."},
|
||||||
|
|
||||||
{"get_usb_devices", winutil_get_usb_devices, METH_VARARGS,
|
{"get_usb_devices", winutil_get_usb_devices, METH_VARARGS,
|
||||||
"get_usb_devices() -> list of strings\n\n"
|
"get_usb_devices() -> list of strings\n\n"
|
||||||
"Return a list of the hardware IDs of all USB devices "
|
"Return a list of the hardware IDs of all USB devices "
|
||||||
"connected to the system."},
|
"connected to the system."},
|
||||||
|
|
||||||
{"get_mounted_volumes_for_usb_device", winutil_get_mounted_volumes_for_usb_device, METH_VARARGS,
|
{"get_removable_drives", winutil_get_removable_drives, METH_VARARGS,
|
||||||
"get_mounted_volumes_for_usb_device(vid, pid) -> dict\n\n"
|
"get_removable_drives(debug=False) -> dict\n\n"
|
||||||
"Return a dictionary of volume_id:drive_letter for all"
|
"Return mapping of all removable drives in the system. Maps drive letters "
|
||||||
"volumes mounted on the system that belong to the"
|
"to a list of device id strings, atleast one of which will carry the information "
|
||||||
"usb device specified by vid (integer) and pid (integer)."},
|
"needed for device matching. On Vista+ it is always the last string in the list. "
|
||||||
|
"Note that you should upper case all strings."},
|
||||||
|
|
||||||
{"set_debug", winutil_set_debug, METH_VARARGS,
|
{"set_debug", winutil_set_debug, METH_VARARGS,
|
||||||
"set_debug(bool)\n\nSet debugging mode."
|
"set_debug(bool)\n\nSet debugging mode."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user