2019-11-26 13:19:29 +00:00
# include "RemovableDriveManager.hpp"
# include <iostream>
2019-11-27 10:33:36 +00:00
# include "boost/nowide/convert.hpp"
2019-11-26 13:19:29 +00:00
2019-11-26 14:52:18 +00:00
# if _WIN32
# include <windows.h>
# include <tchar.h>
2019-11-27 10:33:36 +00:00
# include <winioctl.h>
2019-11-27 12:30:45 +00:00
# include <shlwapi.h>
2019-12-05 13:07:02 +00:00
2019-12-06 15:51:04 +00:00
# include <Dbt.h>
GUID WceusbshGUID = { 0x25dbce51 , 0x6c8f , 0x4a72 ,
0x8a , 0x6d , 0xb5 , 0x4c , 0x2b , 0x4f , 0xc8 , 0x35 } ;
2019-12-05 13:07:02 +00:00
2019-11-26 14:52:18 +00:00
# else
//linux includes
# include <errno.h>
# include <sys/mount.h>
# include <sys/stat.h>
# include <glob.h>
# include <libgen.h>
2019-11-28 15:35:22 +00:00
# include <pwd.h>
2019-12-19 15:27:48 +00:00
# include <filesystem>
2019-11-26 14:52:18 +00:00
# endif
2019-11-26 13:19:29 +00:00
namespace Slic3r {
2019-12-03 09:09:53 +00:00
namespace GUI {
2019-11-26 14:52:18 +00:00
# if _WIN32
2019-12-06 15:51:04 +00:00
INT_PTR WINAPI WinProcCallback ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) ;
2019-11-27 10:33:36 +00:00
void RemovableDriveManager : : search_for_drives ( )
2019-11-26 13:19:29 +00:00
{
2019-11-27 10:33:36 +00:00
m_current_drives . clear ( ) ;
2019-12-13 10:52:08 +00:00
//get logical drives flags by letter in alphabetical order
2019-11-27 13:30:10 +00:00
DWORD drives_mask = GetLogicalDrives ( ) ;
2019-11-26 13:19:29 +00:00
for ( size_t i = 0 ; i < 26 ; i + + )
{
2019-11-27 13:30:10 +00:00
if ( drives_mask & ( 1 < < i ) )
2019-11-26 13:19:29 +00:00
{
std : : string path ( 1 , ( char ) ( ' A ' + i ) ) ;
path + = " : " ;
2019-11-27 13:30:10 +00:00
UINT drive_type = GetDriveTypeA ( path . c_str ( ) ) ;
2019-12-13 10:52:08 +00:00
// DRIVE_REMOVABLE on W are sd cards and usb thumbnails (not usb harddrives)
2019-11-27 13:30:10 +00:00
if ( drive_type = = DRIVE_REMOVABLE )
2019-11-26 13:19:29 +00:00
{
// get name of drive
2019-12-13 17:02:25 +00:00
std : : wstring wpath = boost : : nowide : : widen ( path ) ; //std::wstring(path.begin(), path.end());
2019-11-27 13:30:10 +00:00
std : : wstring volume_name ;
volume_name . resize ( 1024 ) ;
std : : wstring file_system_name ;
file_system_name . resize ( 1024 ) ;
LPWSTR lp_volume_name_buffer = new wchar_t ;
BOOL error = GetVolumeInformationW ( wpath . c_str ( ) , & volume_name [ 0 ] , sizeof ( volume_name ) , NULL , NULL , NULL , & file_system_name [ 0 ] , sizeof ( file_system_name ) ) ;
2019-11-26 13:19:29 +00:00
if ( error ! = 0 )
{
2019-12-13 17:02:25 +00:00
volume_name . erase ( std : : find ( volume_name . begin ( ) , volume_name . end ( ) , ' \0 ' ) , volume_name . end ( ) ) ;
2019-12-13 10:52:08 +00:00
/*
2019-11-27 13:30:10 +00:00
if ( volume_name = = L " " )
2019-11-26 13:19:29 +00:00
{
2019-11-27 13:30:10 +00:00
volume_name = L " REMOVABLE DRIVE " ;
2019-11-26 13:19:29 +00:00
}
2019-12-13 10:52:08 +00:00
*/
2019-11-27 13:30:10 +00:00
if ( file_system_name ! = L " " )
2019-11-26 13:19:29 +00:00
{
2019-11-27 13:30:10 +00:00
ULARGE_INTEGER free_space ;
GetDiskFreeSpaceExA ( path . c_str ( ) , & free_space , NULL , NULL ) ;
if ( free_space . QuadPart > 0 )
2019-11-26 13:19:29 +00:00
{
2019-12-03 09:55:38 +00:00
path + = " \\ " ;
2019-11-27 13:30:10 +00:00
m_current_drives . push_back ( DriveData ( boost : : nowide : : narrow ( volume_name ) , path ) ) ;
2019-11-26 13:19:29 +00:00
}
}
}
}
}
}
}
2019-11-27 10:33:36 +00:00
void RemovableDriveManager : : eject_drive ( const std : : string & path )
2019-11-26 13:19:29 +00:00
{
2019-11-27 10:33:36 +00:00
if ( m_current_drives . empty ( ) )
2019-11-26 13:19:29 +00:00
return ;
2019-11-27 10:33:36 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
2019-11-26 13:19:29 +00:00
{
if ( ( * it ) . path = = path )
{
2019-12-13 10:52:08 +00:00
// get handle to device
2019-11-27 10:33:36 +00:00
std : : string mpath = " \\ \\ . \\ " + path ;
2019-12-03 09:55:38 +00:00
mpath = mpath . substr ( 0 , mpath . size ( ) - 1 ) ;
2019-11-27 10:33:36 +00:00
HANDLE handle = CreateFileA ( mpath . c_str ( ) , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE , nullptr , OPEN_EXISTING , 0 , nullptr ) ;
if ( handle = = INVALID_HANDLE_VALUE )
{
std : : cerr < < " Ejecting " < < mpath < < " failed " < < GetLastError ( ) < < " \n " ;
return ;
}
DWORD deviceControlRetVal ( 0 ) ;
2019-12-13 10:52:08 +00:00
//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
2019-12-11 16:02:12 +00:00
DeviceIoControl ( handle , FSCTL_LOCK_VOLUME , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr ) ;
DeviceIoControl ( handle , FSCTL_DISMOUNT_VOLUME , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr ) ;
2019-12-13 10:52:08 +00:00
// some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here but it returns error to me
2019-11-27 10:33:36 +00:00
BOOL error = DeviceIoControl ( handle , IOCTL_STORAGE_EJECT_MEDIA , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr ) ;
2019-11-27 13:30:10 +00:00
if ( error = = 0 )
{
2019-12-11 16:02:12 +00:00
CloseHandle ( handle ) ;
2019-11-27 10:33:36 +00:00
std : : cerr < < " Ejecting " < < mpath < < " failed " < < deviceControlRetVal < < " " < < GetLastError ( ) < < " \n " ;
2019-12-03 09:09:53 +00:00
return ;
2019-11-27 13:30:10 +00:00
}
2019-12-11 16:02:12 +00:00
CloseHandle ( handle ) ;
2019-12-16 12:53:12 +00:00
m_did_eject = true ;
2019-11-27 10:33:36 +00:00
m_current_drives . erase ( it ) ;
2019-11-26 13:19:29 +00:00
break ;
}
}
}
2019-11-27 13:30:10 +00:00
bool RemovableDriveManager : : is_path_on_removable_drive ( const std : : string & path )
{
if ( m_current_drives . empty ( ) )
return false ;
2019-12-19 10:47:02 +00:00
std : : size_t found = path . find_last_of ( " \\ " ) ;
std : : string new_path = path . substr ( 0 , found ) ;
int letter = PathGetDriveNumberA ( new_path . c_str ( ) ) ;
2019-11-27 13:30:10 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
{
char drive = ( * it ) . path [ 0 ] ;
if ( drive = = ( ' A ' + letter ) )
return true ;
}
return false ;
}
2019-12-05 13:07:02 +00:00
std : : string RemovableDriveManager : : get_drive_from_path ( const std : : string & path )
{
2019-12-19 10:47:02 +00:00
std : : size_t found = path . find_last_of ( " \\ " ) ;
std : : string new_path = path . substr ( 0 , found ) ;
int letter = PathGetDriveNumberA ( new_path . c_str ( ) ) ;
2019-12-05 13:07:02 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
{
char drive = ( * it ) . path [ 0 ] ;
if ( drive = = ( ' A ' + letter ) )
return ( * it ) . path ;
}
return " " ;
}
2019-11-28 12:38:08 +00:00
void RemovableDriveManager : : register_window ( )
{
2019-12-12 13:56:30 +00:00
//creates new unvisible window that is recieving callbacks from system
2019-12-13 10:52:08 +00:00
// structure to register
2019-11-28 12:38:08 +00:00
WNDCLASSEX wndClass ;
wndClass . cbSize = sizeof ( WNDCLASSEX ) ;
wndClass . style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW ;
wndClass . hInstance = reinterpret_cast < HINSTANCE > ( GetModuleHandle ( 0 ) ) ;
2019-12-13 10:52:08 +00:00
wndClass . lpfnWndProc = reinterpret_cast < WNDPROC > ( WinProcCallback ) ; //this is callback
2019-11-28 12:38:08 +00:00
wndClass . cbClsExtra = 0 ;
wndClass . cbWndExtra = 0 ;
wndClass . hIcon = LoadIcon ( 0 , IDI_APPLICATION ) ;
wndClass . hbrBackground = CreateSolidBrush ( RGB ( 192 , 192 , 192 ) ) ;
wndClass . hCursor = LoadCursor ( 0 , IDC_ARROW ) ;
2019-12-05 13:07:02 +00:00
wndClass . lpszClassName = L " PrusaSlicer_aux_class " ;
2019-11-28 12:38:08 +00:00
wndClass . lpszMenuName = NULL ;
wndClass . hIconSm = wndClass . hIcon ;
2019-12-06 15:51:04 +00:00
if ( ! RegisterClassEx ( & wndClass ) )
{
DWORD err = GetLastError ( ) ;
return ;
}
2019-12-05 13:07:02 +00:00
HWND hWnd = CreateWindowEx (
2019-12-06 15:51:04 +00:00
WS_EX_NOACTIVATE ,
2019-12-05 13:07:02 +00:00
L " PrusaSlicer_aux_class " ,
L " PrusaSlicer_aux_wnd " ,
2019-12-06 15:51:04 +00:00
WS_DISABLED , // style
2019-12-05 13:07:02 +00:00
CW_USEDEFAULT , 0 ,
640 , 480 ,
NULL , NULL ,
2019-12-06 15:51:04 +00:00
GetModuleHandle ( NULL ) ,
2019-12-05 13:07:02 +00:00
NULL ) ;
2019-12-06 15:51:04 +00:00
if ( hWnd = = NULL )
{
DWORD err = GetLastError ( ) ;
}
//ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow ( hWnd ) ;
2019-12-05 13:07:02 +00:00
}
2019-12-06 15:51:04 +00:00
2019-12-05 13:07:02 +00:00
INT_PTR WINAPI WinProcCallback ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
2019-12-13 10:52:08 +00:00
// here we need to catch messeges about device removal
// problem is that when ejecting usb (how is it implemented above) there is no messege dispached. Only after physical removal of the device.
//uncomment register_window() in init() to register and comment update() in GUI_App.cpp (only for windows!) to stop recieving periodical updates
2019-12-05 13:07:02 +00:00
LRESULT lRet = 1 ;
static HDEVNOTIFY hDeviceNotify ;
2019-12-06 15:51:04 +00:00
2019-12-05 13:07:02 +00:00
switch ( message )
{
case WM_CREATE :
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter ;
ZeroMemory ( & NotificationFilter , sizeof ( NotificationFilter ) ) ;
NotificationFilter . dbcc_size = sizeof ( DEV_BROADCAST_DEVICEINTERFACE ) ;
NotificationFilter . dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE ;
NotificationFilter . dbcc_classguid = WceusbshGUID ;
2019-12-12 13:56:30 +00:00
hDeviceNotify = RegisterDeviceNotification ( hWnd , & NotificationFilter , DEVICE_NOTIFY_WINDOW_HANDLE ) ;
2019-12-05 13:07:02 +00:00
break ;
2019-12-11 16:02:12 +00:00
2019-12-05 13:07:02 +00:00
case WM_DEVICECHANGE :
{
2019-12-13 10:52:08 +00:00
// here is the important
2019-12-06 15:51:04 +00:00
if ( wParam = = DBT_DEVICEREMOVECOMPLETE )
2019-12-05 13:07:02 +00:00
{
2019-12-11 13:53:28 +00:00
- RemovableDriveManager : : get_instance ( ) . update ( 0 , true ) ;
2019-12-05 13:07:02 +00:00
}
}
break ;
2019-12-11 16:02:12 +00:00
2019-12-05 13:07:02 +00:00
default :
// Send all other messages on to the default windows handler.
lRet = DefWindowProc ( hWnd , message , wParam , lParam ) ;
break ;
}
return lRet ;
2019-11-28 12:38:08 +00:00
}
2019-12-06 15:51:04 +00:00
2019-11-26 14:52:18 +00:00
# else
2019-11-27 10:33:36 +00:00
void RemovableDriveManager : : search_for_drives ( )
2019-11-26 14:52:18 +00:00
{
2019-12-11 16:39:34 +00:00
m_current_drives . clear ( ) ;
2019-12-09 14:33:10 +00:00
# if __APPLE__
2019-12-13 10:52:08 +00:00
// if on macos obj-c class will enumerate
2019-12-10 13:10:47 +00:00
if ( m_rdmmm )
{
m_rdmmm - > list_devices ( ) ;
}
# else
2019-12-11 16:39:34 +00:00
2019-11-26 14:52:18 +00:00
//search /media/* folder
2019-11-28 15:35:22 +00:00
search_path ( " /media/* " , " /media " ) ;
2019-11-26 14:52:18 +00:00
2019-12-10 13:41:49 +00:00
/*
2019-12-04 09:05:18 +00:00
//search /Volumes/* folder (OSX)
search_path ( " /Volumes/* " , " /Volumes " ) ;
2019-12-10 13:41:49 +00:00
*/
2019-11-28 15:35:22 +00:00
std : : string path ( std : : getenv ( " USER " ) ) ;
std : : string pp ( path ) ;
//std::cout << "user: "<< path << "\n";
2019-12-04 10:47:47 +00:00
//if program is run with sudo, we have to search for all users
// but do we want that?
/*
if ( path = = " root " ) {
2019-11-28 15:35:22 +00:00
while ( true ) {
passwd * entry = getpwent ( ) ;
if ( ! entry ) {
break ;
}
path = entry - > pw_name ;
pp = path ;
//search /media/USERNAME/* folder
pp = " /media/ " + pp ;
path = " /media/ " + path + " /* " ;
search_path ( path , pp ) ;
2019-11-26 14:52:18 +00:00
2019-11-28 15:35:22 +00:00
//search /run/media/USERNAME/* folder
path = " /run " + path ;
pp = " /run " + pp ;
search_path ( path , pp ) ;
}
endpwent ( ) ;
} else
2019-12-04 10:47:47 +00:00
*/
2019-11-28 15:35:22 +00:00
{
//search /media/USERNAME/* folder
pp = " /media/ " + pp ;
path = " /media/ " + path + " /* " ;
search_path ( path , pp ) ;
2019-11-26 14:52:18 +00:00
2019-11-28 15:35:22 +00:00
//search /run/media/USERNAME/* folder
path = " /run " + path ;
pp = " /run " + pp ;
search_path ( path , pp ) ;
2019-11-26 14:52:18 +00:00
2019-11-28 15:35:22 +00:00
}
2019-12-10 13:10:47 +00:00
# endif
2019-11-26 14:52:18 +00:00
}
2019-11-28 15:35:22 +00:00
void RemovableDriveManager : : search_path ( const std : : string & path , const std : : string & parent_path )
2019-11-26 14:52:18 +00:00
{
glob_t globbuf ;
globbuf . gl_offs = 2 ;
int error = glob ( path . c_str ( ) , GLOB_TILDE , NULL , & globbuf ) ;
2019-11-28 15:35:22 +00:00
if ( error = = 0 )
2019-11-26 14:52:18 +00:00
{
2019-11-27 13:30:10 +00:00
for ( size_t i = 0 ; i < globbuf . gl_pathc ; i + + )
2019-11-26 14:52:18 +00:00
{
2019-12-10 13:41:49 +00:00
inspect_file ( globbuf . gl_pathv [ i ] , parent_path ) ;
2019-11-26 14:52:18 +00:00
}
2019-11-28 15:35:22 +00:00
} else
{
//if error - path probably doesnt exists so function just exits
//std::cout<<"glob error "<< error<< "\n";
2019-11-26 14:52:18 +00:00
}
2019-11-27 13:30:10 +00:00
2019-11-26 14:52:18 +00:00
globfree ( & globbuf ) ;
}
2019-12-10 13:10:47 +00:00
void RemovableDriveManager : : inspect_file ( const std : : string & path , const std : : string & parent_path )
{
2019-12-13 10:52:08 +00:00
//confirms if the file is removable drive and adds it to vector
2019-12-10 13:10:47 +00:00
//if not same file system - could be removable drive
2019-12-10 13:41:49 +00:00
if ( ! compare_filesystem_id ( path , parent_path ) )
2019-12-10 13:10:47 +00:00
{
2019-12-19 15:27:48 +00:00
//free space
std : : filesystem : : space_info fs_si = std : : filesystem : : space ( path ) ;
//std::cout << "Free space: " << fs_si.free << "Available space: " << fs_si.available << " " << path << '\n';
if ( fs_si . free ! = 0 & & fs_si . available ! = 0 )
2019-12-10 13:10:47 +00:00
{
2019-12-19 15:27:48 +00:00
//user id
struct stat buf ;
stat ( path . c_str ( ) , & buf ) ;
uid_t uid = buf . st_uid ;
std : : string username ( std : : getenv ( " USER " ) ) ;
struct passwd * pw = getpwuid ( uid ) ;
if ( pw ! = 0 )
2019-12-10 13:10:47 +00:00
{
2019-12-19 15:27:48 +00:00
if ( pw - > pw_name = = username )
{
std : : string name = basename ( const_cast < char * > ( path . c_str ( ) ) ) ;
m_current_drives . push_back ( DriveData ( name , path ) ) ;
}
2019-12-10 13:10:47 +00:00
}
}
2019-12-19 15:27:48 +00:00
2019-12-10 13:10:47 +00:00
}
}
2019-11-28 15:35:22 +00:00
bool RemovableDriveManager : : compare_filesystem_id ( const std : : string & path_a , const std : : string & path_b )
{
struct stat buf ;
stat ( path_a . c_str ( ) , & buf ) ;
dev_t id_a = buf . st_dev ;
stat ( path_b . c_str ( ) , & buf ) ;
dev_t id_b = buf . st_dev ;
return id_a = = id_b ;
}
2019-11-27 10:33:36 +00:00
void RemovableDriveManager : : eject_drive ( const std : : string & path )
2019-11-26 14:52:18 +00:00
{
2019-11-27 10:33:36 +00:00
if ( m_current_drives . empty ( ) )
2019-11-26 14:52:18 +00:00
return ;
2019-11-27 10:33:36 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
2019-11-26 14:52:18 +00:00
{
if ( ( * it ) . path = = path )
{
2019-12-04 12:10:08 +00:00
std : : string correct_path ( path ) ;
for ( size_t i = 0 ; i < correct_path . size ( ) ; + + i )
{
if ( correct_path [ i ] = = ' ' )
{
2019-12-04 12:18:08 +00:00
correct_path = correct_path . insert ( i , 1 , ' \\ ' ) ;
2019-12-04 12:13:18 +00:00
i + + ;
2019-12-04 12:10:08 +00:00
}
}
2019-12-04 12:21:41 +00:00
std : : cout < < " Ejecting " < < ( * it ) . name < < " from " < < correct_path < < " \n " ;
2019-12-13 10:52:08 +00:00
// there is no usable command in c++ so terminal command is used instead
// but neither triggers "succesful safe removal messege"
2019-12-04 12:30:25 +00:00
std : : string command = " " ;
# if __APPLE__
2019-12-17 12:08:17 +00:00
//m_rdmmm->eject_device(path);
2019-12-04 12:30:25 +00:00
command = " diskutil unmount " ;
# else
command = " umount " ;
# endif
2019-12-04 12:18:08 +00:00
command + = correct_path ;
2019-12-03 09:09:53 +00:00
int err = system ( command . c_str ( ) ) ;
if ( err )
2019-11-26 14:52:18 +00:00
{
2019-12-03 09:09:53 +00:00
std : : cerr < < " Ejecting failed \n " ;
return ;
2019-11-26 14:52:18 +00:00
}
2019-12-17 12:08:17 +00:00
2019-12-16 12:53:12 +00:00
m_did_eject = true ;
2019-11-27 10:33:36 +00:00
m_current_drives . erase ( it ) ;
2019-12-03 09:09:53 +00:00
2019-11-26 14:52:18 +00:00
break ;
}
}
}
2019-11-27 13:30:10 +00:00
bool RemovableDriveManager : : is_path_on_removable_drive ( const std : : string & path )
{
if ( m_current_drives . empty ( ) )
return false ;
2019-12-18 14:40:48 +00:00
std : : size_t found = path . find_last_of ( " / " ) ;
std : : string new_path = path . substr ( 0 , found ) ;
2019-11-27 13:30:10 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
{
2019-12-18 14:40:48 +00:00
if ( compare_filesystem_id ( new_path , ( * it ) . path ) )
2019-11-27 13:30:10 +00:00
return true ;
}
return false ;
}
2019-12-05 13:07:02 +00:00
std : : string RemovableDriveManager : : get_drive_from_path ( const std : : string & path )
{
2019-12-19 10:47:02 +00:00
std : : size_t found = path . find_last_of ( " / " ) ;
std : : string new_path = path . substr ( 0 , found ) ;
2019-12-05 13:07:02 +00:00
//check if same filesystem
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
{
2019-12-19 10:47:02 +00:00
if ( compare_filesystem_id ( new_path , ( * it ) . path ) )
2019-12-05 13:07:02 +00:00
return ( * it ) . path ;
}
return " " ;
}
2019-11-26 14:52:18 +00:00
# endif
2019-12-11 10:00:47 +00:00
RemovableDriveManager : : RemovableDriveManager ( ) :
m_drives_count ( 0 ) ,
m_last_update ( 0 ) ,
2019-12-13 17:02:25 +00:00
m_last_save_path ( " " ) ,
m_last_save_name ( " " ) ,
2019-12-16 16:15:27 +00:00
m_last_save_path_verified ( false ) ,
2019-12-16 12:53:12 +00:00
m_is_writing ( false ) ,
m_did_eject ( false )
2019-12-11 10:00:47 +00:00
# if __APPLE__
2019-12-11 11:28:51 +00:00
, m_rdmmm ( new RDMMMWrapper ( ) )
2019-12-11 10:00:47 +00:00
# endif
{ }
2019-12-16 12:53:12 +00:00
RemovableDriveManager : : ~ RemovableDriveManager ( )
{
# if __APPLE__
delete m_rdmmm ;
# endif
}
2019-12-06 15:51:04 +00:00
void RemovableDriveManager : : init ( )
2019-11-26 14:52:18 +00:00
{
2019-12-11 13:53:28 +00:00
//add_callback([](void) { RemovableDriveManager::get_instance().print(); });
2019-11-28 12:38:08 +00:00
# if _WIN32
2019-12-12 09:48:33 +00:00
//register_window();
2019-12-10 10:17:12 +00:00
# elif __APPLE__
2019-12-11 10:00:47 +00:00
m_rdmmm - > register_window ( ) ;
2019-11-28 12:38:08 +00:00
# endif
2019-12-16 13:06:25 +00:00
update ( 0 , true ) ;
2019-12-06 15:51:04 +00:00
}
2019-12-12 13:56:30 +00:00
bool RemovableDriveManager : : update ( const long time , const bool check )
2019-12-06 15:51:04 +00:00
{
2019-11-27 14:47:37 +00:00
if ( time ! = 0 ) //time = 0 is forced update
{
2019-12-04 14:27:33 +00:00
long diff = m_last_update - time ;
2019-11-27 14:47:37 +00:00
if ( diff < = - 2 )
{
2019-12-04 14:27:33 +00:00
m_last_update = time ;
2019-11-27 14:47:37 +00:00
} else
{
return false ; // return value shouldnt matter if update didnt run
}
}
2019-11-27 10:33:36 +00:00
search_for_drives ( ) ;
2019-12-19 13:19:41 +00:00
if ( m_drives_count ! = m_current_drives . size ( ) )
{
if ( check ) check_and_notify ( ) ;
m_drives_count = m_current_drives . size ( ) ;
}
2019-11-27 10:33:36 +00:00
return ! m_current_drives . empty ( ) ;
2019-11-26 14:52:18 +00:00
}
2019-11-27 10:33:36 +00:00
bool RemovableDriveManager : : is_drive_mounted ( const std : : string & path )
2019-11-26 14:52:18 +00:00
{
2019-11-27 10:33:36 +00:00
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
2019-11-26 14:52:18 +00:00
{
if ( ( * it ) . path = = path )
{
return true ;
}
}
return false ;
}
2019-12-11 13:53:28 +00:00
std : : string RemovableDriveManager : : get_drive_path ( )
{
if ( m_current_drives . size ( ) = = 0 )
{
reset_last_save_path ( ) ;
return " " ;
}
2019-12-16 16:15:27 +00:00
if ( m_last_save_path_verified )
2019-12-11 13:53:28 +00:00
return m_last_save_path ;
return m_current_drives . back ( ) . path ;
}
std : : string RemovableDriveManager : : get_last_save_path ( )
2019-11-26 13:19:29 +00:00
{
2019-12-16 16:15:27 +00:00
if ( ! m_last_save_path_verified )
return " " ;
2019-12-11 11:28:51 +00:00
return m_last_save_path ;
2019-11-26 13:19:29 +00:00
}
2019-12-13 17:02:25 +00:00
std : : string RemovableDriveManager : : get_last_save_name ( )
{
return m_last_save_name ;
}
2019-11-27 10:33:36 +00:00
std : : vector < DriveData > RemovableDriveManager : : get_all_drives ( )
2019-11-26 13:19:29 +00:00
{
2019-11-27 10:33:36 +00:00
return m_current_drives ;
2019-11-26 13:19:29 +00:00
}
2019-11-28 12:38:08 +00:00
void RemovableDriveManager : : check_and_notify ( )
{
2019-12-19 13:19:41 +00:00
if ( m_callbacks . size ( ) ! = 0 & & m_drives_count > m_current_drives . size ( ) & & m_last_save_path_verified & & ! is_drive_mounted ( m_last_save_path ) )
2019-11-28 12:38:08 +00:00
{
2019-12-19 13:19:41 +00:00
for ( auto it = m_callbacks . begin ( ) ; it ! = m_callbacks . end ( ) ; + + it )
2019-11-28 12:38:08 +00:00
{
2019-12-19 13:19:41 +00:00
( * it ) ( ) ;
2019-11-28 12:38:08 +00:00
}
}
}
void RemovableDriveManager : : add_callback ( std : : function < void ( ) > callback )
{
m_callbacks . push_back ( callback ) ;
}
2019-12-06 12:21:44 +00:00
void RemovableDriveManager : : erase_callbacks ( )
{
m_callbacks . clear ( ) ;
}
2019-12-05 13:07:02 +00:00
void RemovableDriveManager : : set_last_save_path ( const std : : string & path )
{
2019-12-18 08:36:26 +00:00
m_last_save_path_verified = false ;
2019-12-16 16:15:27 +00:00
m_last_save_path = path ;
}
void RemovableDriveManager : : verify_last_save_path ( )
{
std : : string last_drive = get_drive_from_path ( m_last_save_path ) ;
if ( last_drive ! = " " )
2019-12-05 13:07:02 +00:00
{
2019-12-16 16:15:27 +00:00
m_last_save_path_verified = true ;
2019-12-05 13:07:02 +00:00
m_last_save_path = last_drive ;
2019-12-13 17:02:25 +00:00
m_last_save_name = get_drive_name ( last_drive ) ;
2019-12-19 13:19:41 +00:00
} else
{
reset_last_save_path ( ) ;
2019-12-05 13:07:02 +00:00
}
}
2019-12-13 17:02:25 +00:00
std : : string RemovableDriveManager : : get_drive_name ( const std : : string & path )
{
if ( m_current_drives . size ( ) = = 0 )
return " " ;
for ( auto it = m_current_drives . begin ( ) ; it ! = m_current_drives . end ( ) ; + + it )
{
if ( ( * it ) . path = = path )
{
return ( * it ) . name ;
}
}
return " " ;
}
2019-12-05 13:07:02 +00:00
bool RemovableDriveManager : : is_last_drive_removed ( )
{
2019-12-12 09:48:33 +00:00
//std::cout<<"is last: "<<m_last_save_path;
2019-12-16 12:53:12 +00:00
//m_drives_count = m_current_drives.size();
2019-12-16 16:15:27 +00:00
if ( ! m_last_save_path_verified )
2019-12-05 13:07:02 +00:00
{
2019-12-12 09:48:33 +00:00
//std::cout<<"\n";
2019-12-05 13:07:02 +00:00
return true ;
}
2019-12-11 11:28:51 +00:00
bool r = ! is_drive_mounted ( m_last_save_path ) ;
if ( r ) reset_last_save_path ( ) ;
2019-12-12 09:48:33 +00:00
//std::cout<<" "<< r <<"\n";
2019-12-11 11:28:51 +00:00
return r ;
2019-12-05 13:07:02 +00:00
}
2019-12-05 15:22:54 +00:00
bool RemovableDriveManager : : is_last_drive_removed_with_update ( const long time )
{
2019-12-11 11:28:51 +00:00
update ( time , false ) ;
2019-12-05 15:22:54 +00:00
return is_last_drive_removed ( ) ;
}
2019-12-05 13:07:02 +00:00
void RemovableDriveManager : : reset_last_save_path ( )
{
2019-12-16 16:15:27 +00:00
m_last_save_path_verified = false ;
2019-12-05 13:07:02 +00:00
m_last_save_path = " " ;
2019-12-13 17:02:25 +00:00
m_last_save_name = " " ;
}
void RemovableDriveManager : : set_is_writing ( const bool b )
{
m_is_writing = b ;
2019-12-16 12:53:12 +00:00
if ( b )
{
m_did_eject = false ;
}
2019-12-13 17:02:25 +00:00
}
bool RemovableDriveManager : : get_is_writing ( )
{
return m_is_writing ;
2019-12-05 13:07:02 +00:00
}
2019-12-16 12:53:12 +00:00
bool RemovableDriveManager : : get_did_eject ( )
{
return m_did_eject ;
}
2019-12-18 09:08:17 +00:00
void RemovableDriveManager : : set_did_eject ( const bool b )
{
m_did_eject = b ;
}
2019-12-12 13:56:30 +00:00
} } //namespace Slicer::Gui