mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 14:22:01 +08:00
Merge branch 'master' into fs_emboss
This commit is contained in:
commit
b7b472f467
@ -3238,6 +3238,20 @@ static inline void fill_expolygons_generate_paths(
|
|||||||
fill_expolygons_generate_paths(dst, std::move(expolygons), filler, fill_params, density, role, flow);
|
fill_expolygons_generate_paths(dst, std::move(expolygons), filler, fill_params, density, role, flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Polylines draw_perimeters(const ExPolygon &expoly, double clip_length)
|
||||||
|
{
|
||||||
|
// Draw the perimeters.
|
||||||
|
Polylines polylines;
|
||||||
|
polylines.reserve(expoly.holes.size() + 1);
|
||||||
|
for (size_t i = 0; i <= expoly.holes.size(); ++ i) {
|
||||||
|
Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points);
|
||||||
|
pl.points.emplace_back(pl.points.front());
|
||||||
|
pl.clip_end(clip_length);
|
||||||
|
polylines.emplace_back(std::move(pl));
|
||||||
|
}
|
||||||
|
return polylines;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tree_supports_generate_paths(
|
static inline void tree_supports_generate_paths(
|
||||||
ExtrusionEntitiesPtr &dst,
|
ExtrusionEntitiesPtr &dst,
|
||||||
const Polygons &polygons,
|
const Polygons &polygons,
|
||||||
@ -3336,7 +3350,20 @@ static inline void tree_supports_generate_paths(
|
|||||||
const double clip_length = spacing * 0.15;
|
const double clip_length = spacing * 0.15;
|
||||||
const double anchor_length = spacing * 6.;
|
const double anchor_length = spacing * 6.;
|
||||||
ClipperLib_Z::Paths anchor_candidates;
|
ClipperLib_Z::Paths anchor_candidates;
|
||||||
for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) {
|
for (ExPolygon& expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width()))) {
|
||||||
|
double area = expoly.area();
|
||||||
|
if (area > sqr(scaled<double>(5.))) {
|
||||||
|
// Make the tree branch stable by adding another perimeter.
|
||||||
|
ExPolygons level2 = offset2_ex({ expoly }, -1.5 * flow.scaled_width(), 0.5 * flow.scaled_width());
|
||||||
|
if (level2.size() == 1) {
|
||||||
|
Polylines polylines;
|
||||||
|
extrusion_entities_append_paths(dst, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height(),
|
||||||
|
// Disable reversal of the path, always start with the anchor, always print CCW.
|
||||||
|
false);
|
||||||
|
expoly = level2.front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Try to produce one more perimeter to place the seam anchor.
|
// Try to produce one more perimeter to place the seam anchor.
|
||||||
// First genrate a 2nd perimeter loop as a source for anchor candidates.
|
// First genrate a 2nd perimeter loop as a source for anchor candidates.
|
||||||
// The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection.
|
// The anchor candidate points are annotated with an index of the source contour or with -1 if on intersection.
|
||||||
@ -3466,9 +3493,9 @@ static inline void fill_expolygons_with_sheath_generate_paths(
|
|||||||
fill_params.density = density;
|
fill_params.density = density;
|
||||||
fill_params.dont_adjust = true;
|
fill_params.dont_adjust = true;
|
||||||
|
|
||||||
double spacing = flow.scaled_spacing();
|
const double spacing = flow.scaled_spacing();
|
||||||
// Clip the sheath path to avoid the extruder to get exactly on the first point of the loop.
|
// Clip the sheath path to avoid the extruder to get exactly on the first point of the loop.
|
||||||
double clip_length = spacing * 0.15;
|
const double clip_length = spacing * 0.15;
|
||||||
|
|
||||||
for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) {
|
for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) {
|
||||||
// Don't reorder the skirt and its infills.
|
// Don't reorder the skirt and its infills.
|
||||||
@ -3478,16 +3505,7 @@ static inline void fill_expolygons_with_sheath_generate_paths(
|
|||||||
eec->no_sort = true;
|
eec->no_sort = true;
|
||||||
}
|
}
|
||||||
ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst;
|
ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst;
|
||||||
// Draw the perimeters.
|
extrusion_entities_append_paths(out, draw_perimeters(expoly, clip_length), erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height());
|
||||||
Polylines polylines;
|
|
||||||
polylines.reserve(expoly.holes.size() + 1);
|
|
||||||
for (size_t i = 0; i <= expoly.holes.size(); ++ i) {
|
|
||||||
Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points);
|
|
||||||
pl.points.emplace_back(pl.points.front());
|
|
||||||
pl.clip_end(clip_length);
|
|
||||||
polylines.emplace_back(std::move(pl));
|
|
||||||
}
|
|
||||||
extrusion_entities_append_paths(out, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height());
|
|
||||||
// Fill in the rest.
|
// Fill in the rest.
|
||||||
fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
|
fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow);
|
||||||
if (no_sort && ! eec->empty())
|
if (no_sort && ! eec->empty())
|
||||||
|
@ -3534,7 +3534,8 @@ static void draw_branches(
|
|||||||
for (size_t i = 0; i < projections.size(); ++ i) {
|
for (size_t i = 0; i < projections.size(); ++ i) {
|
||||||
const SupportElement &element = *elements_with_link_down[i].first;
|
const SupportElement &element = *elements_with_link_down[i].first;
|
||||||
const int below = elements_with_link_down[i].second;
|
const int below = elements_with_link_down[i].second;
|
||||||
if (pts[i] != projections[i]) {
|
const bool locked = below == -1 && element.state.layer_idx > 0;
|
||||||
|
if (! locked && pts[i] != projections[i]) {
|
||||||
// Nudge the circle center away from the collision.
|
// Nudge the circle center away from the collision.
|
||||||
Vec3d v{ projections[i].x() - pts[i].x(), projections[i].y() - pts[i].y(), projections[i].z() - pts[i].z() };
|
Vec3d v{ projections[i].x() - pts[i].x(), projections[i].y() - pts[i].y(), projections[i].z() - pts[i].z() };
|
||||||
double depth = v.norm();
|
double depth = v.norm();
|
||||||
@ -3555,7 +3556,7 @@ static void draw_branches(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Laplacian smoothing
|
// Laplacian smoothing
|
||||||
if (! element.parents.empty() && (below != -1 || element.state.layer_idx == 0)) {
|
if (! locked && ! element.parents.empty()) {
|
||||||
Vec2d avg{ 0, 0 };
|
Vec2d avg{ 0, 0 };
|
||||||
const SupportElements &above = move_bounds[element.state.layer_idx + 1];
|
const SupportElements &above = move_bounds[element.state.layer_idx + 1];
|
||||||
const size_t offset_above = linear_data_layers[element.state.layer_idx + 1];
|
const size_t offset_above = linear_data_layers[element.state.layer_idx + 1];
|
||||||
|
@ -2192,6 +2192,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path)
|
format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
notification_manager->close_notification_of_type(NotificationType::ExportFinished);
|
||||||
notification_manager->push_notification(NotificationType::CustomNotification,
|
notification_manager->push_notification(NotificationType::CustomNotification,
|
||||||
NotificationManager::NotificationLevel::ErrorNotificationLevel,
|
NotificationManager::NotificationLevel::ErrorNotificationLevel,
|
||||||
format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path)
|
format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path)
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
|
||||||
#include <Dbt.h>
|
#include <Dbt.h>
|
||||||
|
#include <Setupapi.h>
|
||||||
|
#include <cfgmgr32.h>
|
||||||
#else
|
#else
|
||||||
// unix, linux & OSX includes
|
// unix, linux & OSX includes
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -72,6 +72,192 @@ std::vector<DriveData> RemovableDriveManager::search_for_removable_drives() cons
|
|||||||
return current_drives;
|
return current_drives;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// returns the device instance handle of a storage volume or 0 on error
|
||||||
|
// called from eject_inner, based on https://stackoverflow.com/a/58848961
|
||||||
|
DEVINST get_dev_inst_by_device_number(long device_number, UINT drive_type, WCHAR* dos_device_name)
|
||||||
|
{
|
||||||
|
bool is_floppy = (wcsstr(dos_device_name, L"\\Floppy") != NULL); // TODO: could be tested better?
|
||||||
|
GUID* guid;
|
||||||
|
switch (drive_type) {
|
||||||
|
case DRIVE_REMOVABLE:
|
||||||
|
if (is_floppy) {
|
||||||
|
// we are interested only in SD cards or USB sticks
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is floppy disk.";
|
||||||
|
return 0;
|
||||||
|
//guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
|
||||||
|
} else {
|
||||||
|
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DRIVE_FIXED:
|
||||||
|
// we are interested only in SD cards or USB sticks
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is harddisk.";
|
||||||
|
return 0;
|
||||||
|
//guid = (GUID*)&GUID_DEVINTERFACE_DISK;
|
||||||
|
//break;
|
||||||
|
case DRIVE_CDROM:
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Drive is cd-rom.";
|
||||||
|
// we are interested only in SD cards or USB sticks
|
||||||
|
return 0;
|
||||||
|
//guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
|
||||||
|
//break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get device interface info set handle for all devices attached to system
|
||||||
|
HDEVINFO h_dev_info = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||||
|
|
||||||
|
if (h_dev_info == INVALID_HANDLE_VALUE) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Invalid dev info handle.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve a context structure for a device interface of a device information set
|
||||||
|
BYTE buf[1024];
|
||||||
|
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buf;
|
||||||
|
SP_DEVICE_INTERFACE_DATA spdid;
|
||||||
|
SP_DEVINFO_DATA spdd;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
spdid.cbSize = sizeof(spdid);
|
||||||
|
|
||||||
|
// Loop through devices and compare device numbers
|
||||||
|
for (DWORD index = 0; SetupDiEnumDeviceInterfaces(h_dev_info, NULL, guid, index, &spdid); ++index) {
|
||||||
|
SetupDiGetDeviceInterfaceDetail(h_dev_info, &spdid, NULL, 0, &size, NULL);
|
||||||
|
// check the buffer size
|
||||||
|
if (size == 0 || size > sizeof(buf)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// prepare structures
|
||||||
|
pspdidd->cbSize = sizeof(*pspdidd);
|
||||||
|
ZeroMemory(&spdd, sizeof(spdd));
|
||||||
|
spdd.cbSize = sizeof(spdd);
|
||||||
|
// fill structures
|
||||||
|
long res = SetupDiGetDeviceInterfaceDetail(h_dev_info, &spdid, pspdidd, size, &size, &spdd);
|
||||||
|
if (!res) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// open the drive with pspdidd->DevicePath to compare device numbers
|
||||||
|
HANDLE drive_handle = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (drive_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// get its device number
|
||||||
|
STORAGE_DEVICE_NUMBER sdn;
|
||||||
|
DWORD bytes_returned = 0;
|
||||||
|
res = DeviceIoControl(drive_handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL);
|
||||||
|
CloseHandle(drive_handle);
|
||||||
|
if (!res) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//compare
|
||||||
|
if (device_number != (long)sdn.DeviceNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// this is the drive, return the device instance
|
||||||
|
SetupDiDestroyDeviceInfoList(h_dev_info);
|
||||||
|
return spdd.DevInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupDiDestroyDeviceInfoList(h_dev_info);
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "get_dev_inst_by_device_number failed: Enmurating couldn't find the drive.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform eject using CM_Request_Device_EjectW.
|
||||||
|
// Returns 0 if success.
|
||||||
|
int eject_inner(const std::string& path)
|
||||||
|
{
|
||||||
|
// Following implementation is based on https://stackoverflow.com/a/58848961
|
||||||
|
assert(path.size() > 0);
|
||||||
|
std::wstring wpath = std::wstring();
|
||||||
|
wpath += boost::nowide::widen(path)[0]; // drive letter wide
|
||||||
|
wpath[0] &= ~0x20; // make sure drive letter is uppercase
|
||||||
|
assert(wpath[0] >= 'A' && wpath[0] <= 'Z');
|
||||||
|
std::wstring root_path = wpath + L":\\"; // for GetDriveType
|
||||||
|
std::wstring device_path = wpath + L":"; //for QueryDosDevice
|
||||||
|
std::wstring volume_access_path = L"\\\\.\\" + wpath + L":"; // for CreateFile
|
||||||
|
long device_number = -1;
|
||||||
|
|
||||||
|
// open the storage volume
|
||||||
|
HANDLE volume_handle = CreateFileW(volume_access_path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
|
||||||
|
if (volume_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid value of file handle.", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the volume's device number
|
||||||
|
STORAGE_DEVICE_NUMBER sdn;
|
||||||
|
DWORD bytes_returned = 0;
|
||||||
|
long res = DeviceIoControl(volume_handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL);
|
||||||
|
if (res) {
|
||||||
|
device_number = sdn.DeviceNumber;
|
||||||
|
}
|
||||||
|
CloseHandle(volume_handle);
|
||||||
|
|
||||||
|
if (device_number == -1) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid device number.", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the drive type which is required to match the device numbers correctely
|
||||||
|
UINT drive_type = GetDriveTypeW(root_path.c_str());
|
||||||
|
|
||||||
|
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not
|
||||||
|
WCHAR dos_device_name[MAX_PATH];
|
||||||
|
res = QueryDosDeviceW(device_path.c_str(), dos_device_name, MAX_PATH);
|
||||||
|
if (!res) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid dos device name.", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
|
||||||
|
DEVINST dev_inst = get_dev_inst_by_device_number(device_number, drive_type, dos_device_name);
|
||||||
|
|
||||||
|
if (dev_inst == 0) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Invalid device instance handle.", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PNP_VETO_TYPE veto_type = PNP_VetoTypeUnknown;
|
||||||
|
WCHAR veto_name[MAX_PATH];
|
||||||
|
veto_name[0] = 0;
|
||||||
|
|
||||||
|
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
|
||||||
|
DEVINST dev_inst_parent = 0;
|
||||||
|
res = CM_Get_Parent(&dev_inst_parent, dev_inst, 0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// loop with several tries and sleep (this is running on main UI thread)
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
veto_name[0] = 0;
|
||||||
|
// CM_Query_And_Remove_SubTree doesn't work for restricted users
|
||||||
|
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
|
||||||
|
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP)
|
||||||
|
res = CM_Request_Device_EjectW(dev_inst_parent, &veto_type, veto_name, MAX_PATH, 0);
|
||||||
|
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
|
||||||
|
if (res == CR_SUCCESS && veto_type == PNP_VetoTypeUnknown) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Wait for next try.
|
||||||
|
// This is main thread!
|
||||||
|
Sleep(500);
|
||||||
|
}
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
// perform eject
|
||||||
|
res = CM_Request_Device_EjectW(dev_inst_parent, &veto_type, veto_name, MAX_PATH, 0);
|
||||||
|
if (res == CR_SUCCESS && veto_type == PNP_VetoTypeUnknown) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(error) << GUI::format("Ejecting of %1% has failed: Request to eject device has failed.", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
// Called from UI therefore it blocks the UI thread.
|
// Called from UI therefore it blocks the UI thread.
|
||||||
// It also blocks updates at the worker thread.
|
// It also blocks updates at the worker thread.
|
||||||
// Win32 implementation.
|
// Win32 implementation.
|
||||||
@ -86,6 +272,28 @@ void RemovableDriveManager::eject_drive()
|
|||||||
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
|
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
|
||||||
std::scoped_lock<std::mutex> lock(m_drives_mutex);
|
std::scoped_lock<std::mutex> lock(m_drives_mutex);
|
||||||
auto it_drive_data = this->find_last_save_path_drive_data();
|
auto it_drive_data = this->find_last_save_path_drive_data();
|
||||||
|
if (it_drive_data != m_current_drives.end()) {
|
||||||
|
if (!eject_inner(m_last_save_path)) {
|
||||||
|
// success
|
||||||
|
assert(m_callback_evt_handler);
|
||||||
|
if (m_callback_evt_handler)
|
||||||
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true)));
|
||||||
|
} else {
|
||||||
|
// failed to eject
|
||||||
|
// this should not happen, throwing exception might be the way here
|
||||||
|
assert(m_callback_evt_handler);
|
||||||
|
if (m_callback_evt_handler)
|
||||||
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// drive not found in m_current_drives
|
||||||
|
assert(m_callback_evt_handler);
|
||||||
|
if (m_callback_evt_handler)
|
||||||
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>({"",""}, false)));
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// Implementation used until 2.5.x version
|
||||||
|
// Some usb drives does not eject properly (still visible in file explorer). Some even does not write all content and eject.
|
||||||
if (it_drive_data != m_current_drives.end()) {
|
if (it_drive_data != m_current_drives.end()) {
|
||||||
// get handle to device
|
// get handle to device
|
||||||
std::string mpath = "\\\\.\\" + m_last_save_path;
|
std::string mpath = "\\\\.\\" + m_last_save_path;
|
||||||
@ -102,16 +310,16 @@ void RemovableDriveManager::eject_drive()
|
|||||||
//these 3 commands should eject device safely but they dont, the device does disappear from file explorer but the "device was safely remove" notification doesnt trigger.
|
//these 3 commands should eject device safely but they dont, the device does disappear from file explorer but the "device was safely remove" notification doesnt trigger.
|
||||||
//sd cards does trigger WM_DEVICECHANGE messege, usb drives dont
|
//sd cards does trigger WM_DEVICECHANGE messege, usb drives dont
|
||||||
BOOL e1 = DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
BOOL e1 = DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
||||||
BOOST_LOG_TRIVIAL(debug) << "FSCTL_LOCK_VOLUME " << e1 << " ; " << deviceControlRetVal << " ; " << GetLastError();
|
BOOST_LOG_TRIVIAL(error) << "FSCTL_LOCK_VOLUME " << e1 << " ; " << deviceControlRetVal << " ; " << GetLastError();
|
||||||
BOOL e2 = DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
BOOL e2 = DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
||||||
BOOST_LOG_TRIVIAL(debug) << "FSCTL_DISMOUNT_VOLUME " << e2 << " ; " << deviceControlRetVal << " ; " << GetLastError();
|
BOOST_LOG_TRIVIAL(error) << "FSCTL_DISMOUNT_VOLUME " << e2 << " ; " << deviceControlRetVal << " ; " << GetLastError();
|
||||||
// some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here but it returns error to me
|
// some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here with FALSE as third parameter, which should set PreventMediaRemoval
|
||||||
BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed (IOCTL_STORAGE_EJECT_MEDIA)" << deviceControlRetVal << " " << GetLastError();
|
BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed (IOCTL_STORAGE_EJECT_MEDIA)" << deviceControlRetVal << " " << GetLastError();
|
||||||
assert(m_callback_evt_handler);
|
assert(m_callback_evt_handler);
|
||||||
if (m_callback_evt_handler)
|
if (m_callback_evt_handler)
|
||||||
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -122,6 +330,7 @@ void RemovableDriveManager::eject_drive()
|
|||||||
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true)));
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true)));
|
||||||
m_current_drives.erase(it_drive_data);
|
m_current_drives.erase(it_drive_data);
|
||||||
}
|
}
|
||||||
|
#endif // 0
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RemovableDriveManager::get_removable_drive_path(const std::string &path)
|
std::string RemovableDriveManager::get_removable_drive_path(const std::string &path)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user