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

BackgroundSlicingProcess.hpp « GUI « slic3r « src - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f87a58fd6be9fcede4af35a15b647eb30db5c75d (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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#ifndef slic3r_GUI_BackgroundSlicingProcess_hpp_
#define slic3r_GUI_BackgroundSlicingProcess_hpp_

#include <string>
#include <condition_variable>
#include <mutex>

#include <boost/thread.hpp>

#include <wx/event.h>

#include "libslic3r/PrintBase.hpp"
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "libslic3r/Format/SL1.hpp"
#include "slic3r/Utils/PrintHost.hpp"
#include "libslic3r/GCode/GCodeProcessor.hpp"


namespace boost { namespace filesystem { class path; } }

namespace Slic3r {

class DynamicPrintConfig;
class Model;
class SLAPrint;

class SlicingStatusEvent : public wxEvent
{
public:
	SlicingStatusEvent(wxEventType eventType, int winid, const PrintBase::SlicingStatus &status) :
		wxEvent(winid, eventType), status(std::move(status)) {}
	virtual wxEvent *Clone() const { return new SlicingStatusEvent(*this); }

	PrintBase::SlicingStatus status;
};

class SlicingProcessCompletedEvent : public wxEvent
{
public:
	enum StatusType {
		Finished,
		Cancelled,
		Error
	};

	SlicingProcessCompletedEvent(wxEventType eventType, int winid, StatusType status, std::exception_ptr exception) :
		wxEvent(winid, eventType), m_status(status), m_exception(exception) {}
	virtual wxEvent* Clone() const { return new SlicingProcessCompletedEvent(*this); }

	StatusType 	status()    const { return m_status; }
	bool 		finished()  const { return m_status == Finished; }
	bool 		success()   const { return m_status == Finished; }
	bool 		cancelled() const { return m_status == Cancelled; }
	bool		error() 	const { return m_status == Error; }
	// Unhandled error produced by stdlib or a Win32 structured exception, or unhandled Slic3r's own critical exception.
	bool 		critical_error() const;
	// Critical errors does invalidate plater except CopyFileError.
	bool        invalidate_plater() const;
	// Only valid if error()
	void 		rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
	// Produce a human readable message to be displayed by a notification or a message box.
	// 2nd parameter defines whether the output should be displayed with a monospace font.
	std::pair<std::string, bool> format_error_message() const;

private:
	StatusType 			m_status;
	std::exception_ptr 	m_exception;
};

wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent);

// Print step IDs for keeping track of the print state.
enum BackgroundSlicingProcessStep {
    bspsGCodeFinalize, bspsCount,
};

// Support for the GUI background processing (Slicing and G-code generation).
// As of now this class is not declared in Slic3r::GUI due to the Perl bindings limits.
class BackgroundSlicingProcess
{
public:
	BackgroundSlicingProcess();
	// Stop the background processing and finalize the bacgkround processing thread, remove temp files.
	~BackgroundSlicingProcess();

	void set_fff_print(Print *print) { m_fff_print = print; }
    void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); }
	void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
	void set_gcode_result(GCodeProcessor::Result* result) { m_gcode_result = result; }

	// The following wxCommandEvent will be sent to the UI thread / Plater window, when the slicing is finished
	// and the background processing will transition into G-code export.
	// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
	void set_slicing_completed_event(int event_id) { m_event_slicing_completed_id = event_id; }
	// The following wxCommandEvent will be sent to the UI thread / Plater window, when the G-code export is finished.
	// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
	void set_finished_event(int event_id) { m_event_finished_id = event_id; }
	// The following wxCommandEvent will be sent to the UI thread / Plater window, when the G-code is being exported to
	// specified path or uploaded.
	// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
	void set_export_began_event(int event_id) { m_event_export_began_id = event_id; }

	// Activate either m_fff_print or m_sla_print.
	// Return true if changed.
	bool select_technology(PrinterTechnology tech);

	// Get the currently active printer technology.
	PrinterTechnology   current_printer_technology() const;
	// Get the current print. It is either m_fff_print or m_sla_print.
	const PrintBase*    current_print() const { return m_print; }
	const Print* 		fff_print() const { return m_fff_print; }
	const SLAPrint* 	sla_print() const { return m_sla_print; }
    // Take the project path (if provided), extract the name of the project, run it through the macro processor and save it next to the project file.
    // If the project_path is empty, just run output_filepath().
	std::string 		output_filepath_for_project(const boost::filesystem::path &project_path);

	// Start the background processing. Returns false if the background processing was already running.
	bool start();
	// Cancel the background processing. Returns false if the background processing was not running.
	// A stopped background processing may be restarted with start().
	bool stop();
	// Cancel the background processing and reset the print. Returns false if the background processing was not running.
	// Useful when the Model or configuration is being changed drastically.
	bool reset();

	// Apply config over the print. Returns false, if the new config values caused any of the already
	// processed steps to be invalidated, therefore the task will need to be restarted.
    PrintBase::ApplyStatus apply(const Model &model, const DynamicPrintConfig &config);
	// After calling the apply() function, set_task() may be called to limit the task to be processed by process().
	// This is useful for calculating SLA supports for a single object only.
	void 		set_task(const PrintBase::TaskParams &params);
	// After calling apply, the empty() call will report whether there is anything to slice.
	bool 		empty() const;
	// Validate the print. Returns an empty string if valid, returns an error message if invalid.
	// Call validate before calling start().
    std::string validate(std::string* warning = nullptr);

	// Set the export path of the G-code.
	// Once the path is set, the G-code 
	void schedule_export(const std::string &path, bool export_path_on_removable_media);
	// Set print host upload job data to be enqueued to the PrintHostJobQueue
	// after current print slicing is complete
	void schedule_upload(Slic3r::PrintHostJob upload_job);
	// Clear m_export_path.
	void reset_export();
	// Once the G-code export is scheduled, the apply() methods will do nothing.
	bool is_export_scheduled() const { return ! m_export_path.empty(); }
	bool is_upload_scheduled() const { return ! m_upload_job.empty(); }

	enum State {
		// m_thread  is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet).
		STATE_INITIAL = 0,
		// m_thread is waiting for the task to execute.
		STATE_IDLE,
		STATE_STARTED,
		// m_thread is executing a task.
		STATE_RUNNING,
		// m_thread finished executing a task, and it is waiting until the UI thread picks up the results.
		STATE_FINISHED,
		// m_thread finished executing a task, the task has been canceled by the UI thread, therefore the UI thread will not be notified.
		STATE_CANCELED,
		// m_thread exited the loop and it is going to finish. The UI thread should join on m_thread.
		STATE_EXIT,
		STATE_EXITED,
	};
	State 	state() 	const { return m_state; }
	bool    idle() 		const { return m_state == STATE_IDLE; }
	bool    running() 	const { return m_state == STATE_STARTED || m_state == STATE_RUNNING || m_state == STATE_FINISHED || m_state == STATE_CANCELED; }
    // Returns true if the last step of the active print was finished with success.
    // The "finished" flag is reset by the apply() method, if it changes the state of the print.
    // This "finished" flag does not account for the final export of the output file (.gcode or zipped PNGs),
    // and it does not account for the OctoPrint scheduling.
    bool    finished() const { return m_print->finished(); }
    
private:
	void 	thread_proc();
	// Calls thread_proc(), catches all C++ exceptions and shows them using wxApp::OnUnhandledException().
	void 	thread_proc_safe() throw();
#ifdef _WIN32
	// Wrapper for Win32 structured exceptions. Win32 structured exception blocks and C++ exception blocks cannot be mixed in the same function.
	// Catch a SEH exception and return its ID or zero if no SEH exception has been catched.
	unsigned long 	thread_proc_safe_seh() throw();
	// Calls thread_proc_safe_seh(), rethrows a Slic3r::HardCrash exception based on SEH exception
	// returned by thread_proc_safe_seh() and lets wxApp::OnUnhandledException() display it.
	void 			thread_proc_safe_seh_throw() throw();
#endif // _WIN32
	void 	join_background_thread();
	// To be called by Print::apply() through the Print::m_cancel_callback to stop the background
	// processing before changing any data of running or finalized milestones.
	// This function shall not trigger any UI update through the wxWidgets event.
	void	stop_internal();

	// Helper to wrap the FFF slicing & G-code generation.
	void	process_fff();

    // Temporary: for mimicking the fff file export behavior with the raster output
    void	process_sla();

    // Call Print::process() and catch all exceptions into ex, thus no exception could be thrown
    // by this method. This exception behavior is required to combine C++ exceptions with Win32 SEH exceptions
    // on the same thread.
	void    call_process(std::exception_ptr &ex) throw();

#ifdef _WIN32
	// Wrapper for Win32 structured exceptions. Win32 structured exception blocks and C++ exception blocks cannot be mixed in the same function.
	// Catch a SEH exception and return its ID or zero if no SEH exception has been catched.
	unsigned long call_process_seh(std::exception_ptr &ex) throw();
	// Calls call_process_seh(), rethrows a Slic3r::HardCrash exception based on SEH exception
	// returned by call_process_seh().
	void    	  call_process_seh_throw(std::exception_ptr &ex) throw();
#endif // _WIN32

	// Currently active print. It is one of m_fff_print and m_sla_print.
	PrintBase				   *m_print 			 = nullptr;
	// Non-owned pointers to Print instances.
	Print 					   *m_fff_print 		 = nullptr;
	SLAPrint 				   *m_sla_print			 = nullptr;
	// Data structure, to which the G-code export writes its annotations.
	GCodeProcessor::Result     *m_gcode_result 		 = nullptr;
	// Callback function, used to write thumbnails into gcode.
	ThumbnailsGeneratorCallback m_thumbnail_cb 	     = nullptr;
	SL1Archive                  m_sla_archive;
		// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
	std::string 				m_temp_output_path;
	// Output path provided by the user. The output path may be set even if the slicing is running,
	// but once set, it cannot be re-set.
	std::string 				m_export_path;
	bool 						m_export_path_on_removable_media = false;
	// Print host upload job to schedule after slicing is complete, used by schedule_upload(),
	// empty by default (ie. no upload to schedule)
	PrintHostJob                m_upload_job;
	// Thread, on which the background processing is executed. The thread will always be present
	// and ready to execute the slicing process.
	boost::thread		 		m_thread;
	// Mutex and condition variable to synchronize m_thread with the UI thread.
	std::mutex 		 			m_mutex;
	std::condition_variable		m_condition;
	State 						m_state = STATE_INITIAL;

	// For executing tasks from the background thread on UI thread synchronously (waiting for result) using wxWidgets CallAfter().
	// When the background proces is canceled, the UITask has to be invalidated as well, so that it will not be
	// executed on the UI thread referencing invalid data.
    struct UITask {
        enum State {
            Planned,
            Finished,
            Canceled,
        };
        State  					state = Planned;
        std::mutex 				mutex;
    	std::condition_variable	condition;
    };
    // Only one UI task may be planned by the background thread to be executed on the UI thread, as the background
    // thread is blocking until the UI thread calculation finishes.
    std::shared_ptr<UITask> 	m_ui_task;

    PrintState<BackgroundSlicingProcessStep, bspsCount>   	m_step_state;
	bool                set_step_started(BackgroundSlicingProcessStep step);
	void                set_step_done(BackgroundSlicingProcessStep step);
	bool 				is_step_done(BackgroundSlicingProcessStep step) const;
	bool                invalidate_step(BackgroundSlicingProcessStep step);
    bool                invalidate_all_steps();
    // If the background processing stop was requested, throw CanceledException.
    void                throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); }
	void				finalize_gcode();
    void                prepare_upload();
    // To be executed at the background thread.
	ThumbnailsList		render_thumbnails(const ThumbnailsParams &params);
	// Execute task from background thread on the UI thread synchronously. Returns true if processed, false if cancelled before executing the task.
	bool 				execute_ui_task(std::function<void()> task);
	// To be called from inside m_mutex to cancel a planned UI task.
	static void			cancel_ui_task(std::shared_ptr<BackgroundSlicingProcess::UITask> task);

	// wxWidgets command ID to be sent to the plater to inform that the slicing is finished, and the G-code export will continue.
	int 						m_event_slicing_completed_id 	= 0;
	// wxWidgets command ID to be sent to the plater to inform that the task finished.
	int 						m_event_finished_id  			= 0;
	// wxWidgets command ID to be sent to the plater to inform that the G-code is being exported.
	int                         m_event_export_began_id         = 0;

};

}; // namespace Slic3r

#endif /* slic3r_GUI_BackgroundSlicingProcess_hpp_ */