1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
10 from xml.etree import cElementTree as ElementTree
12 from xml.etree import ElementTree
14 _removeableCache = None
15 _removeableCacheTime = None
17 def _parseStupidPListXML(e):
19 return _parseStupidPListXML(list(e)[0])
23 ret.append(_parseStupidPListXML(c))
32 ret[key] = _parseStupidPListXML(c)
41 def _findInTree(t, n):
44 if '_name' in t and t['_name'] == n:
46 for k, v in t.items():
47 ret += _findInTree(v, n)
50 ret += _findInTree(v, n)
53 def getPossibleSDcardDrives():
54 global _removeableCache, _removeableCacheTime
55 if _removeableCache is not None and time.time() - _removeableCacheTime < 5.0:
56 return _removeableCache
59 if platform.system() == "Windows":
60 from ctypes import windll
62 bitmask = windll.kernel32.GetLogicalDrives()
63 for letter in string.uppercase:
64 if bitmask & 1 and windll.kernel32.GetDriveTypeA(letter + ':/') == 2:
66 nameBuffer = ctypes.create_unicode_buffer(1024)
67 if windll.kernel32.GetVolumeInformationW(ctypes.c_wchar_p(letter + ':/'), nameBuffer, ctypes.sizeof(nameBuffer), None, None, None, None, 0) == 0:
68 volumeName = nameBuffer.value
70 volumeName = 'NO NAME'
72 freeBytes = ctypes.c_longlong(0)
73 if windll.kernel32.GetDiskFreeSpaceExA(letter + ':/', ctypes.byref(freeBytes), None, None) == 0:
75 if freeBytes.value < 1:
77 drives.append(('%s (%s:)' % (volumeName, letter), letter + ':/', volumeName))
79 elif platform.system() == "Darwin":
80 p = subprocess.Popen(['system_profiler', 'SPUSBDataType', '-xml'], stdout=subprocess.PIPE)
81 xml = ElementTree.fromstring(p.communicate()[0])
84 xml = _parseStupidPListXML(xml)
85 for dev in _findInTree(xml, 'Mass Storage Device'):
86 if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
87 for vol in dev['volumes']:
88 if 'mount_point' in vol:
89 volume = vol['mount_point']
90 drives.append((os.path.basename(volume), volume, os.path.basename(volume)))
92 for volume in glob.glob('/media/*'):
93 drives.append((os.path.basename(volume), volume, os.path.basename(volume)))
95 _removeableCache = drives
96 _removeableCacheTime = time.time()
99 def ejectDrive(driveName):
100 if platform.system() == "Windows":
101 cmd = '"%s" %s>NUL' % (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'EjectMedia.exe')), driveName)
102 elif platform.system() == "Darwin":
103 cmd = "diskutil eject '%s' > /dev/null 2>&1" % (driveName)
105 cmd = "umount '%s' > /dev/null 2>&1" % (driveName)
111 if __name__ == '__main__':
112 print getPossibleSDcardDrives()