Welcome to mirror list, hosted at ThFree Co, Russian Federation.

RemovableDriveManager.hpp « GUI « slic3r « src - github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e1a8d6faf181bbdf9fdacb9a83faf23a8709c76b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#ifndef slic3r_GUI_RemovableDriveManager_hpp_
#define slic3r_GUI_RemovableDriveManager_hpp_

#include <vector>
#include <string>

#include <boost/thread.hpp>
#include <tbb/mutex.h>
#include <condition_variable>

// Custom wxWidget events
#include "Event.hpp"

namespace Slic3r {
namespace GUI {

struct DriveData
{
	std::string name;
	std::string path;

	void clear() {
		name.clear();
		path.clear();
	}
	bool empty() const {
		return path.empty();
	}
};

inline bool operator< (const DriveData &lhs, const DriveData &rhs) { return lhs.path < rhs.path; }
inline bool operator> (const DriveData &lhs, const DriveData &rhs) { return lhs.path > rhs.path; }
inline bool operator==(const DriveData &lhs, const DriveData &rhs) { return lhs.path == rhs.path; }

using RemovableDriveEjectEvent = Event<std::pair<DriveData, bool>>;
wxDECLARE_EVENT(EVT_REMOVABLE_DRIVE_EJECTED, RemovableDriveEjectEvent);

using RemovableDrivesChangedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_REMOVABLE_DRIVES_CHANGED, RemovableDrivesChangedEvent);

#if __APPLE__
	// Callbacks on device plug / unplug work reliably on OSX.
	#define REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
#endif // __APPLE__

class RemovableDriveManager
{
public:
	RemovableDriveManager() = default;
	RemovableDriveManager(RemovableDriveManager const&) = delete;
	void operator=(RemovableDriveManager const&) = delete;
	~RemovableDriveManager() { assert(! m_initialized); }

	// Start the background thread and register this window as a target for update events.
	// Register for OSX notifications.
	void 		init(wxEvtHandler *callback_evt_handler);
	// Stop the background thread of the removable drive manager, so that no new updates will be sent out.
	// Deregister OSX notifications.
	void 		shutdown();

	// Returns path to a removable media if it exists, prefering the input path.
	std::string get_removable_drive_path(const std::string &path);
	bool        is_path_on_removable_drive(const std::string &path) { return this->get_removable_drive_path(path) == path; }

	// Verify whether the path provided is on removable media. If so, save the path for further eject and return true, otherwise return false.
	bool 		set_and_verify_last_save_path(const std::string &path);
	// Eject drive of a file set by set_and_verify_last_save_path().
	// On Unix / OSX, the function blocks and sends out the EVT_REMOVABLE_DRIVE_EJECTED event on success.
	// On Windows, the function does not block, and the eject is detected in the background thread.
	void 		eject_drive();

	// Status is used to retrieve info for showing UI buttons.
	// Status is called every time when change of UI buttons is possible therefore should not perform update.
	struct RemovableDrivesStatus {
		bool 	has_removable_drives { false };
		bool 	has_eject { false };
	};
	RemovableDrivesStatus status();

	// Enumerates current drives and sends out wxWidget events on change or eject.
	// Called by each public method, by the background thread and from RemovableDriveManagerMM::on_device_unmount OSX notification handler.
	// Not to be called manually.
	// Public to be accessible from RemovableDriveManagerMM::on_device_unmount OSX notification handler.
	// It would be better to make this method private and friend to RemovableDriveManagerMM, but RemovableDriveManagerMM is an ObjectiveC class.
	void 		update();

#ifdef _WIN32
    // Called by Win32 Volume arrived / detached callback.
	void 		volumes_changed();
#endif // _WIN32

private:
	bool 			 		m_initialized { false };
	wxEvtHandler*			m_callback_evt_handler { nullptr };

#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
	// Worker thread, worker thread synchronization and callbacks to the UI thread.
	void 					thread_proc();
	boost::thread 			m_thread;
	std::condition_variable m_thread_stop_condition;
	mutable std::mutex 		m_thread_stop_mutex;
	bool 					m_stop { false };
#ifdef _WIN32
    std::atomic<bool>		m_wakeup { false };
#endif /* _WIN32 */
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS

	// Called from update() to enumerate removable drives.
	std::vector<DriveData> 	search_for_removable_drives() const;

	// m_current_drives is guarded by m_drives_mutex
	// sorted ascending by path
	std::vector<DriveData> 	m_current_drives;
	mutable tbb::mutex 		m_drives_mutex;
	// Locking the update() function to avoid that the function is executed multiple times.
	mutable tbb::mutex 		m_inside_update_mutex;

	// Returns drive path (same as path in DriveData) if exists otherwise empty string.
	std::string 			get_removable_drive_from_path(const std::string& path);
	// Returns iterator to a drive in m_current_drives with path equal to m_last_save_path or end().
	std::vector<DriveData>::const_iterator find_last_save_path_drive_data() const;
	// Set with set_and_verify_last_save_path() to a removable drive path to be ejected.
	std::string 			m_last_save_path;

#if __APPLE__
    void register_window_osx();
    void unregister_window_osx();
    void list_devices(std::vector<DriveData> &out) const;
    // not used as of now
    void eject_device(const std::string &path);
    // Opaque pointer to RemovableDriveManagerMM
    void *m_impl_osx;
#endif
};

}}

#endif // slic3r_GUI_RemovableDriveManager_hpp_