1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
11 from xml.etree import cElementTree as ElementTree
13 from xml.etree import ElementTree
15 from Cura.util import profile
17 _removableCacheUpdateThread = None
20 def _parseStupidPListXML(e):
22 return _parseStupidPListXML(list(e)[0])
26 ret.append(_parseStupidPListXML(c))
35 ret[key] = _parseStupidPListXML(c)
44 def _findInTree(t, n):
47 if '_name' in t and t['_name'] == n:
49 for k, v in t.items():
50 ret += _findInTree(v, n)
53 ret += _findInTree(v, n)
56 def getPossibleSDcardDrives():
57 global _removableCache, _removableCacheUpdateThread
59 if profile.getPreference('auto_detect_sd') == 'False':
62 if _removableCacheUpdateThread is None:
63 _removableCacheUpdateThread = threading.Thread(target=_updateCache)
64 _removableCacheUpdateThread.daemon = True
65 _removableCacheUpdateThread.start()
66 return _removableCache
69 global _removableCache
73 if platform.system() == "Windows":
74 from ctypes import windll
76 bitmask = windll.kernel32.GetLogicalDrives()
77 for letter in string.uppercase:
78 if letter != 'A' and letter != 'B' and bitmask & 1 and windll.kernel32.GetDriveTypeA(letter + ':/') == 2:
80 nameBuffer = ctypes.create_unicode_buffer(1024)
81 if windll.kernel32.GetVolumeInformationW(ctypes.c_wchar_p(letter + ':/'), nameBuffer, ctypes.sizeof(nameBuffer), None, None, None, None, 0) == 0:
82 volumeName = nameBuffer.value
84 volumeName = 'NO NAME'
86 freeBytes = ctypes.c_longlong(0)
87 if windll.kernel32.GetDiskFreeSpaceExA(letter + ':/', ctypes.byref(freeBytes), None, None) == 0:
89 if freeBytes.value < 1:
91 drives.append(('%s (%s:)' % (volumeName, letter), letter + ':/', volumeName))
93 elif platform.system() == "Darwin":
94 p = subprocess.Popen(['system_profiler', 'SPUSBDataType', '-xml'], stdout=subprocess.PIPE)
95 xml = ElementTree.fromstring(p.communicate()[0])
98 xml = _parseStupidPListXML(xml)
99 for dev in _findInTree(xml, 'Mass Storage Device'):
100 if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
101 for vol in dev['volumes']:
102 if 'mount_point' in vol:
103 volume = vol['mount_point']
104 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
106 p = subprocess.Popen(['system_profiler', 'SPCardReaderDataType', '-xml'], stdout=subprocess.PIPE)
107 xml = ElementTree.fromstring(p.communicate()[0])
110 xml = _parseStupidPListXML(xml)
112 if '_items' in entry:
113 for item in entry['_items']:
114 for dev in item['_items']:
115 if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
116 for vol in dev['volumes']:
117 if 'mount_point' in vol:
118 volume = vol['mount_point']
119 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
121 for volume in glob.glob('/media/*'):
122 if os.path.ismount(volume):
123 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
124 elif volume == '/media/'+os.getenv('USER'):
125 for volume in glob.glob('/media/'+os.getenv('USER')+'/*'):
126 if os.path.ismount(volume):
127 drives.append((os.path.basename(volume), volume + '/', os.path.basename(volume)))
129 _removableCache = drives
132 def ejectDrive(driveName):
133 if platform.system() == "Windows":
134 cmd = [os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'EjectMedia.exe')), driveName]
135 elif platform.system() == "Darwin":
136 cmd = ["diskutil", "eject", driveName]
138 cmd = ["umount", driveName]
141 if subprocess.mswindows:
142 su = subprocess.STARTUPINFO()
143 su.dwFlags |= subprocess.STARTF_USESHOWWINDOW
144 su.wShowWindow = subprocess.SW_HIDE
145 kwargs['startupinfo'] = su
146 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
147 output = p.communicate()
156 if __name__ == '__main__':
157 print getPossibleSDcardDrives()