Merge branch '2.1'

Conflicts:
	plugins/RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py
	plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py
	plugins/USBPrinting/PrinterConnection.py
	resources/machines/fdmprinter.json
	resources/profiles/ultimaker2+/abs_0.4_high.curaprofile
This commit is contained in:
Ghostkeeper 2016-03-17 15:24:00 +01:00
commit de9a66e1f4
47 changed files with 248 additions and 154 deletions

View file

@ -43,7 +43,7 @@ class OSXRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
return drives
def performEjectDevice(self, device):
p = subprocess.Popen(["diskutil", "eject", device.getId()], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(["diskutil", "eject", device.getId()], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
output = p.communicate()
Logger.log("d", "umount returned: %s.", repr(output))

View file

@ -25,6 +25,7 @@ class RemovableDriveOutputDevice(OutputDevice):
self._writing = False
def requestWrite(self, node, file_name = None, filter_by_machine = False):
filter_by_machine = True # This plugin is indended to be used by machine (regardless of what it was told to do)
if self._writing:
raise OutputDeviceError.DeviceBusyError()

View file

@ -6,9 +6,10 @@ import time
from UM.Message import Message
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.Logger import Logger
from . import RemovableDriveOutputDevice
from UM.Logger import Logger
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
@ -37,11 +38,14 @@ class RemovableDrivePlugin(OutputDevicePlugin):
def ejectDevice(self, device):
try:
Logger.log("i", "Attempting to eject the device")
result = self.performEjectDevice(device)
except Exception as e:
Logger.log("e", "Ejection failed due to: %s" % str(e))
result = False
if result:
Logger.log("i", "Succesfully ejected the device")
message = Message(catalog.i18nc("@info:status", "Ejected {0}. You can now safely remove the drive.").format(device.getName()))
message.show()
else:

View file

@ -10,6 +10,9 @@ from . import RemovableDrivePlugin
import string
import ctypes
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
# WinAPI Constants that we need
# Hardcoded here due to stupid WinDLL stuff that does not give us access to these values.
DRIVE_REMOVABLE = 2 # [CodeStyle: Windows Enum value]
@ -24,6 +27,21 @@ IOCTL_STORAGE_EJECT_MEDIA = 2967560 # [CodeStyle: Windows Enum value]
OPEN_EXISTING = 3 # [CodeStyle: Windows Enum value]
# Setup the DeviceIoControl function arguments and return type.
# See ctypes documentation for details on how to call C functions from python, and why this is important.
windll.kernel32.DeviceIoControl.argtypes = [
wintypes.HANDLE, # _In_ HANDLE hDevice
wintypes.DWORD, # _In_ DWORD dwIoControlCode
wintypes.LPVOID, # _In_opt_ LPVOID lpInBuffer
wintypes.DWORD, # _In_ DWORD nInBufferSize
wintypes.LPVOID, # _Out_opt_ LPVOID lpOutBuffer
wintypes.DWORD, # _In_ DWORD nOutBufferSize
ctypes.POINTER(wintypes.DWORD), # _Out_opt_ LPDWORD lpBytesReturned
wintypes.LPVOID # _Inout_opt_ LPOVERLAPPED lpOverlapped
]
windll.kernel32.DeviceIoControl.restype = wintypes.BOOL
## Removable drive support for windows
class WindowsRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
def checkRemovableDrives(self):
@ -75,16 +93,31 @@ class WindowsRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
handle = ctypes.windll.kernel32.CreateFileA("\\\\.\\{0}".format(device.getId()[:-1]).encode("ascii"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0, None )
if handle == -1:
print(ctypes.windll.kernel32.GetLastError())
return
# ctypes.WinError sets up an GetLastError API call for windows as an Python OSError exception.
# So we use this to raise the error to our caller.
raise ctypes.WinError()
# The DeviceIoControl requires a bytes_returned pointer to be a valid pointer.
# So create a ctypes DWORD to reference. (Without this pointer the DeviceIoControl function will crash with an access violation after doing its job.
bytes_returned = wintypes.DWORD(0)
error = None
result = None
# Then, try and tell it to eject
if not ctypes.windll.kernel32.DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, None, None, None, None, None, None):
result = False
else:
result = True
return_code = windll.kernel32.DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, None, 0, None, 0, ctypes.pointer(bytes_returned), None)
# DeviceIoControl with IOCTL_STORAGE_EJECT_MEDIA return 0 on error.
if return_code == 0:
# ctypes.WinError sets up an GetLastError API call for windows as an Python OSError exception.
# So we use this to raise the error to our caller.
error = ctypes.WinError()
# Do not raise an error here yet, so we can properly close the handle.
# Finally, close the handle
ctypes.windll.kernel32.CloseHandle(handle)
return result
windll.kernel32.CloseHandle(handle)
# If an error happened in the DeviceIoControl, raise it now.
if error:
raise error
# Return success
return True