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 from Cura.util import profile
16 _removeableCache = None
17 _removeableCacheTime = None
19 def _parseStupidPListXML(e):
21 return _parseStupidPListXML(list(e)[0])
25 ret.append(_parseStupidPListXML(c))
34 ret[key] = _parseStupidPListXML(c)
43 def _findInTree(t, n):
46 if '_name' in t and t['_name'] == n:
48 for k, v in t.items():
49 ret += _findInTree(v, n)
52 ret += _findInTree(v, n)
55 def getPossibleSDcardDrives():
56 global _removeableCache, _removeableCacheTime
57 if _removeableCache is not None and time.time() - _removeableCacheTime < 5.0:
58 return _removeableCache
60 if profile.getPreference('auto_detect_sd') == 'False':
64 if platform.system() == "Windows":
65 from ctypes import windll
67 bitmask = windll.kernel32.GetLogicalDrives()
68 for letter in string.uppercase:
69 if bitmask & 1 and windll.kernel32.GetDriveTypeA(letter + ':/') == 2:
71 nameBuffer = ctypes.create_unicode_buffer(1024)
72 if windll.kernel32.GetVolumeInformationW(ctypes.c_wchar_p(letter + ':/'), nameBuffer, ctypes.sizeof(nameBuffer), None, None, None, None, 0) == 0:
73 volumeName = nameBuffer.value
75 volumeName = 'NO NAME'
77 freeBytes = ctypes.c_longlong(0)
78 if windll.kernel32.GetDiskFreeSpaceExA(letter + ':/', ctypes.byref(freeBytes), None, None) == 0:
80 if freeBytes.value < 1:
82 drives.append(('%s (%s:)' % (volumeName, letter), letter + ':/', volumeName))
84 elif platform.system() == "Darwin":
85 p = subprocess.Popen(['system_profiler', 'SPUSBDataType', '-xml'], stdout=subprocess.PIPE)
86 xml = ElementTree.fromstring(p.communicate()[0])
89 xml = _parseStupidPListXML(xml)
90 for dev in _findInTree(xml, 'Mass Storage Device'):
91 if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
92 for vol in dev['volumes']:
93 if 'mount_point' in vol:
94 volume = vol['mount_point']
95 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
97 p = subprocess.Popen(['system_profiler', 'SPCardReaderDataType', '-xml'], stdout=subprocess.PIPE)
98 xml = ElementTree.fromstring(p.communicate()[0])
101 xml = _parseStupidPListXML(xml)
103 if '_items' in entry:
104 for item in entry['_items']:
105 for dev in item['_items']:
106 if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
107 for vol in dev['volumes']:
108 if 'mount_point' in vol:
109 volume = vol['mount_point']
110 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
112 for volume in glob.glob('/media/*'):
113 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
115 _removeableCache = drives
116 _removeableCacheTime = time.time()
119 def ejectDrive(driveName):
120 if platform.system() == "Windows":
121 cmd = [os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'EjectMedia.exe')), driveName]
122 elif platform.system() == "Darwin":
123 cmd = ["diskutil", "eject", driveName]
125 cmd = ["umount", driveName]
128 if subprocess.mswindows:
129 su = subprocess.STARTUPINFO()
130 su.dwFlags |= subprocess.STARTF_USESHOWWINDOW
131 su.wShowWindow = subprocess.SW_HIDE
132 kwargs['startupinfo'] = su
133 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
134 output = p.communicate()
143 if __name__ == '__main__':
144 print getPossibleSDcardDrives()