2018-03-23 10:41:20 +00:00
# include "BackgroundSlicingProcess.hpp"
2018-10-02 11:23:38 +00:00
# include "GUI_App.hpp"
2020-03-04 08:24:13 +00:00
# include "GUI.hpp"
2018-03-23 10:41:20 +00:00
2018-11-06 10:54:36 +00:00
# include <wx/app.h>
2018-03-23 10:41:20 +00:00
# include <wx/panel.h>
2018-09-14 07:28:00 +00:00
# include <wx/stdpaths.h>
2018-03-23 10:41:20 +00:00
2018-11-13 16:33:03 +00:00
// For zipped archive creation
# include <wx/stdstream.h>
# include <wx/wfstream.h>
# include <wx/zipstrm.h>
2019-10-24 06:46:39 +00:00
# include <miniz.h>
2018-09-12 09:59:02 +00:00
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
2018-11-08 19:18:40 +00:00
# include "libslic3r/Print.hpp"
# include "libslic3r/SLAPrint.hpp"
# include "libslic3r/Utils.hpp"
# include "libslic3r/GCode/PostProcessor.hpp"
2018-12-19 13:47:16 +00:00
# include "libslic3r/GCode/PreviewData.hpp"
2020-04-13 10:31:37 +00:00
# include "libslic3r/Format/SL1.hpp"
2019-04-15 14:14:19 +00:00
# include "libslic3r/libslic3r.h"
2018-09-12 09:59:02 +00:00
2018-03-23 10:41:20 +00:00
# include <cassert>
# include <stdexcept>
2018-12-11 09:33:11 +00:00
# include <cctype>
2018-03-23 10:41:20 +00:00
2020-02-28 10:13:14 +00:00
# include <boost/format/format_fwd.hpp>
# include <boost/filesystem/operations.hpp>
2018-12-12 11:00:45 +00:00
# include <boost/log/trivial.hpp>
2018-09-14 07:28:00 +00:00
# include <boost/nowide/cstdio.hpp>
2019-05-04 00:07:07 +00:00
# include "I18N.hpp"
2019-12-18 13:09:16 +00:00
# include "RemovableDriveManager.hpp"
2018-09-14 07:28:00 +00:00
2020-02-28 10:13:14 +00:00
# include "slic3r/Utils/Thread.hpp"
2018-03-23 10:41:20 +00:00
namespace Slic3r {
2018-09-14 07:28:00 +00:00
BackgroundSlicingProcess : : BackgroundSlicingProcess ( )
{
2018-10-24 19:03:12 +00:00
boost : : filesystem : : path temp_path ( wxStandardPaths : : Get ( ) . GetTempDir ( ) . utf8_str ( ) . data ( ) ) ;
temp_path / = ( boost : : format ( " .%1%.gcode " ) % get_current_pid ( ) ) . str ( ) ;
m_temp_output_path = temp_path . string ( ) ;
2018-09-14 07:28:00 +00:00
}
BackgroundSlicingProcess : : ~ BackgroundSlicingProcess ( )
{
this - > stop ( ) ;
this - > join_background_thread ( ) ;
boost : : nowide : : remove ( m_temp_output_path . c_str ( ) ) ;
}
2018-12-03 12:14:28 +00:00
bool BackgroundSlicingProcess : : select_technology ( PrinterTechnology tech )
2018-11-08 19:18:40 +00:00
{
2018-12-03 12:14:28 +00:00
bool changed = false ;
2018-11-08 19:18:40 +00:00
if ( m_print = = nullptr | | m_print - > technology ( ) ! = tech ) {
if ( m_print ! = nullptr )
this - > reset ( ) ;
switch ( tech ) {
case ptFFF : m_print = m_fff_print ; break ;
case ptSLA : m_print = m_sla_print ; break ;
2019-10-29 09:40:34 +00:00
default : assert ( false ) ; break ;
2018-11-08 19:18:40 +00:00
}
2018-12-03 12:14:28 +00:00
changed = true ;
2018-11-08 19:18:40 +00:00
}
assert ( m_print ! = nullptr ) ;
2018-12-03 12:14:28 +00:00
return changed ;
2018-11-08 19:18:40 +00:00
}
2018-11-22 14:29:59 +00:00
PrinterTechnology BackgroundSlicingProcess : : current_printer_technology ( ) const
{
return m_print - > technology ( ) ;
}
2019-05-17 14:27:00 +00:00
std : : string BackgroundSlicingProcess : : output_filepath_for_project ( const boost : : filesystem : : path & project_path )
{
assert ( m_print ! = nullptr ) ;
if ( project_path . empty ( ) )
return m_print - > output_filepath ( " " ) ;
return m_print - > output_filepath ( project_path . parent_path ( ) . string ( ) , project_path . stem ( ) . string ( ) ) ;
}
2018-11-08 19:18:40 +00:00
// This function may one day be merged into the Print, but historically the print was separated
// from the G-code generator.
void BackgroundSlicingProcess : : process_fff ( )
{
assert ( m_print = = m_fff_print ) ;
m_print - > process ( ) ;
2018-11-20 12:22:26 +00:00
wxQueueEvent ( GUI : : wxGetApp ( ) . mainframe - > m_plater , new wxCommandEvent ( m_event_slicing_completed_id ) ) ;
2019-11-22 11:39:03 +00:00
m_fff_print - > export_gcode ( m_temp_output_path , m_gcode_preview_data , m_thumbnail_cb ) ;
2019-11-15 15:36:29 +00:00
2018-11-16 17:28:50 +00:00
if ( this - > set_step_started ( bspsGCodeFinalize ) ) {
if ( ! m_export_path . empty ( ) ) {
//FIXME localize the messages
2018-12-12 11:00:45 +00:00
// Perform the final post-processing of the export path by applying the print statistics over the file name.
2018-12-12 14:09:20 +00:00
std : : string export_path = m_fff_print - > print_statistics ( ) . finalize_output_path ( m_export_path ) ;
2020-03-12 11:43:01 +00:00
int copy_ret_val = copy_file ( m_temp_output_path , export_path , m_export_path_on_removable_media ) ;
2020-03-06 14:10:58 +00:00
switch ( copy_ret_val ) {
2020-02-27 09:44:25 +00:00
case SUCCESS : break ; // no error
case FAIL_COPY_FILE :
throw std : : runtime_error ( _utf8 ( L ( " Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked? " ) ) ) ;
break ;
case FAIL_FILES_DIFFERENT :
2020-02-21 10:17:48 +00:00
throw std : : runtime_error ( ( boost : : format ( _utf8 ( L ( " Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp. " ) ) ) % export_path ) . str ( ) ) ;
break ;
2020-02-27 09:44:25 +00:00
case FAIL_RENAMING :
2020-02-21 10:17:48 +00:00
throw std : : runtime_error ( ( boost : : format ( _utf8 ( L ( " Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again. " ) ) ) % export_path ) . str ( ) ) ;
break ;
2020-02-27 09:44:25 +00:00
case FAIL_CHECK_ORIGIN_NOT_OPENED :
2020-02-21 10:17:48 +00:00
throw std : : runtime_error ( ( boost : : format ( _utf8 ( L ( " Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp. " ) ) ) % m_temp_output_path % export_path ) . str ( ) ) ;
break ;
2020-02-27 09:44:25 +00:00
case FAIL_CHECK_TARGET_NOT_OPENED :
2020-02-21 10:17:48 +00:00
throw std : : runtime_error ( ( boost : : format ( _utf8 ( L ( " Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp. " ) ) ) % export_path ) . str ( ) ) ;
break ;
default :
2020-02-27 09:44:25 +00:00
BOOST_LOG_TRIVIAL ( warning ) < < " Unexpected fail code( " < < ( int ) copy_ret_val < < " ) durring copy_file() to " < < export_path < < " . " ;
2020-02-21 10:17:48 +00:00
break ;
2020-01-02 10:28:37 +00:00
}
2020-02-21 10:17:48 +00:00
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 95 , _utf8 ( L ( " Running post-processing scripts " ) ) ) ;
2018-12-12 11:00:45 +00:00
run_post_process_scripts ( export_path , m_fff_print - > config ( ) ) ;
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 100 , ( boost : : format ( _utf8 ( L ( " G-code file exported to %1% " ) ) ) % export_path ) . str ( ) ) ;
2018-12-14 14:27:34 +00:00
} else if ( ! m_upload_job . empty ( ) ) {
2018-12-20 15:35:54 +00:00
prepare_upload ( ) ;
2018-11-16 17:28:50 +00:00
} else {
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 100 , _utf8 ( L ( " Slicing complete " ) ) ) ;
2018-11-08 19:18:40 +00:00
}
2018-11-16 17:28:50 +00:00
this - > set_step_done ( bspsGCodeFinalize ) ;
}
2018-11-08 19:18:40 +00:00
}
2019-10-24 06:46:39 +00:00
static void write_thumbnail ( Zipper & zipper , const ThumbnailData & data )
2019-10-23 15:10:14 +00:00
{
2019-10-24 06:46:39 +00:00
size_t png_size = 0 ;
void * png_data = tdefl_write_image_to_png_file_in_memory_ex ( ( const void * ) data . pixels . data ( ) , data . width , data . height , 4 , & png_size , MZ_DEFAULT_LEVEL , 1 ) ;
if ( png_data ! = nullptr )
{
2019-10-25 11:59:13 +00:00
zipper . add_entry ( " thumbnail/thumbnail " + std : : to_string ( data . width ) + " x " + std : : to_string ( data . height ) + " .png " , ( const std : : uint8_t * ) png_data , png_size ) ;
2019-10-24 06:46:39 +00:00
mz_free ( png_data ) ;
}
2018-11-08 19:18:40 +00:00
}
2018-11-16 17:28:50 +00:00
void BackgroundSlicingProcess : : process_sla ( )
{
2018-11-13 10:53:54 +00:00
assert ( m_print = = m_sla_print ) ;
m_print - > process ( ) ;
2018-11-16 17:28:50 +00:00
if ( this - > set_step_started ( bspsGCodeFinalize ) ) {
2018-11-13 10:53:54 +00:00
if ( ! m_export_path . empty ( ) ) {
2019-10-23 15:10:14 +00:00
const std : : string export_path = m_sla_print - > print_statistics ( ) . finalize_output_path ( m_export_path ) ;
Zipper zipper ( export_path ) ;
2020-04-13 10:31:37 +00:00
m_sla_archive . export_print ( zipper , * m_sla_print ) ;
2019-10-24 06:46:39 +00:00
2019-11-22 11:39:03 +00:00
if ( m_thumbnail_cb ! = nullptr )
2019-10-25 11:59:13 +00:00
{
2019-11-22 11:39:03 +00:00
ThumbnailsList thumbnails ;
2019-11-28 13:18:24 +00:00
m_thumbnail_cb ( thumbnails , current_print ( ) - > full_print_config ( ) . option < ConfigOptionPoints > ( " thumbnails " ) - > values , true , true , true , true ) ;
// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, false, true, true); // renders also supports and pad
2019-11-22 11:39:03 +00:00
for ( const ThumbnailData & data : thumbnails )
2019-10-25 11:59:13 +00:00
{
if ( data . is_valid ( ) )
write_thumbnail ( zipper , data ) ;
}
}
2019-10-23 15:10:14 +00:00
zipper . finalize ( ) ;
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 100 , ( boost : : format ( _utf8 ( L ( " Masked SLA file exported to %1% " ) ) ) % export_path ) . str ( ) ) ;
2018-12-20 15:35:54 +00:00
} else if ( ! m_upload_job . empty ( ) ) {
prepare_upload ( ) ;
} else {
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 100 , _utf8 ( L ( " Slicing complete " ) ) ) ;
2018-11-13 10:53:54 +00:00
}
this - > set_step_done ( bspsGCodeFinalize ) ;
}
}
2018-03-23 10:41:20 +00:00
void BackgroundSlicingProcess : : thread_proc ( )
{
2018-11-08 19:18:40 +00:00
assert ( m_print ! = nullptr ) ;
assert ( m_print = = m_fff_print | | m_print = = m_sla_print ) ;
2018-03-23 10:41:20 +00:00
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
// Let the caller know we are ready to run the background processing task.
m_state = STATE_IDLE ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
for ( ; ; ) {
2018-03-28 15:05:31 +00:00
assert ( m_state = = STATE_IDLE | | m_state = = STATE_CANCELED | | m_state = = STATE_FINISHED ) ;
2018-03-23 10:41:20 +00:00
// Wait until a new task is ready to be executed, or this thread should be finished.
lck . lock ( ) ;
m_condition . wait ( lck , [ this ] ( ) { return m_state = = STATE_STARTED | | m_state = = STATE_EXIT ; } ) ;
if ( m_state = = STATE_EXIT )
// Exiting this thread.
break ;
// Process the background slicing task.
m_state = STATE_RUNNING ;
lck . unlock ( ) ;
std : : string error ;
try {
assert ( m_print ! = nullptr ) ;
2018-11-08 19:18:40 +00:00
switch ( m_print - > technology ( ) ) {
case ptFFF : this - > process_fff ( ) ; break ;
2018-11-13 10:53:54 +00:00
case ptSLA : this - > process_sla ( ) ; break ;
2018-11-08 19:18:40 +00:00
default : m_print - > process ( ) ; break ;
}
2018-10-31 15:22:36 +00:00
} catch ( CanceledException & /* ex */ ) {
2018-03-28 15:05:31 +00:00
// Canceled, this is all right.
assert ( m_print - > canceled ( ) ) ;
2019-08-08 13:17:17 +00:00
} catch ( const std : : bad_alloc & ex ) {
2020-03-04 08:24:13 +00:00
wxString errmsg = GUI : : from_u8 ( ( boost : : format ( _utf8 ( L ( " %s has encountered an error. It was likely caused by running out of memory. "
2019-08-08 13:17:17 +00:00
" If you are sure you have enough RAM on your system, this may also be a bug and we would "
2020-03-02 08:41:54 +00:00
" be glad if you reported it. " ) ) ) % SLIC3R_APP_NAME ) . str ( ) ) ;
2020-02-21 10:58:18 +00:00
error = std : : string ( errmsg . ToUTF8 ( ) ) + " \n \n " + std : : string ( ex . what ( ) ) ;
2019-08-08 13:17:17 +00:00
} catch ( std : : exception & ex ) {
2018-03-23 10:41:20 +00:00
error = ex . what ( ) ;
} catch ( . . . ) {
error = " Unknown C++ exception. " ;
}
2019-02-21 10:40:56 +00:00
m_print - > finalize ( ) ;
2018-03-23 10:41:20 +00:00
lck . lock ( ) ;
m_state = m_print - > canceled ( ) ? STATE_CANCELED : STATE_FINISHED ;
2018-10-30 08:27:31 +00:00
if ( m_print - > cancel_status ( ) ! = Print : : CANCELED_INTERNAL ) {
// Only post the canceled event, if canceled by user.
// Don't post the canceled event, if canceled from Print::apply().
wxCommandEvent evt ( m_event_finished_id ) ;
2020-03-06 13:09:31 +00:00
evt . SetString ( GUI : : from_u8 ( error ) ) ;
2018-10-30 08:27:31 +00:00
evt . SetInt ( m_print - > canceled ( ) ? - 1 : ( error . empty ( ) ? 1 : 0 ) ) ;
wxQueueEvent ( GUI : : wxGetApp ( ) . mainframe - > m_plater , evt . Clone ( ) ) ;
}
2018-03-28 15:05:31 +00:00
m_print - > restart ( ) ;
2018-03-23 10:41:20 +00:00
lck . unlock ( ) ;
// Let the UI thread wake up if it is waiting for the background task to finish.
m_condition . notify_one ( ) ;
// Let the UI thread see the result.
}
m_state = STATE_EXITED ;
lck . unlock ( ) ;
// End of the background processing thread. The UI thread should join m_thread now.
}
2018-11-06 10:54:36 +00:00
void BackgroundSlicingProcess : : thread_proc_safe ( )
{
try {
this - > thread_proc ( ) ;
} catch ( . . . ) {
wxTheApp - > OnUnhandledException ( ) ;
}
}
2018-03-23 10:41:20 +00:00
void BackgroundSlicingProcess : : join_background_thread ( )
{
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
if ( m_state = = STATE_INITIAL ) {
// Worker thread has not been started yet.
assert ( ! m_thread . joinable ( ) ) ;
} else {
assert ( m_state = = STATE_IDLE ) ;
assert ( m_thread . joinable ( ) ) ;
// Notify the worker thread to exit.
m_state = STATE_EXIT ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
// Wait until the worker thread exits.
m_thread . join ( ) ;
}
}
bool BackgroundSlicingProcess : : start ( )
{
2018-11-08 19:18:40 +00:00
if ( m_print - > empty ( ) )
// The print is empty (no object in Model, or all objects are out of the print bed).
return false ;
2018-03-23 10:41:20 +00:00
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
if ( m_state = = STATE_INITIAL ) {
// The worker thread is not running yet. Start it.
assert ( ! m_thread . joinable ( ) ) ;
2019-11-07 11:57:40 +00:00
m_thread = create_thread ( [ this ] { this - > thread_proc_safe ( ) ; } ) ;
2018-03-23 10:41:20 +00:00
// Wait until the worker thread is ready to execute the background processing task.
m_condition . wait ( lck , [ this ] ( ) { return m_state = = STATE_IDLE ; } ) ;
}
assert ( m_state = = STATE_IDLE | | this - > running ( ) ) ;
if ( this - > running ( ) )
// The background processing thread is already running.
return false ;
if ( ! this - > idle ( ) )
throw std : : runtime_error ( " Cannot start a background task, the worker thread is not idle. " ) ;
m_state = STATE_STARTED ;
2018-10-30 08:27:31 +00:00
m_print - > set_cancel_callback ( [ this ] ( ) { this - > stop_internal ( ) ; } ) ;
2018-03-23 10:41:20 +00:00
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
return true ;
}
bool BackgroundSlicingProcess : : stop ( )
{
2018-11-16 17:28:50 +00:00
// m_print->state_mutex() shall NOT be held. Unfortunately there is no interface to test for it.
2018-03-23 10:41:20 +00:00
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
2018-09-14 07:28:00 +00:00
if ( m_state = = STATE_INITIAL ) {
2018-10-23 13:27:31 +00:00
// this->m_export_path.clear();
2018-03-23 10:41:20 +00:00
return false ;
2018-09-14 07:28:00 +00:00
}
2018-10-18 16:06:40 +00:00
// assert(this->running());
2018-03-23 10:41:20 +00:00
if ( m_state = = STATE_STARTED | | m_state = = STATE_RUNNING ) {
m_print - > cancel ( ) ;
// Wait until the background processing stops by being canceled.
m_condition . wait ( lck , [ this ] ( ) { return m_state = = STATE_CANCELED ; } ) ;
2018-03-28 15:05:31 +00:00
// In the "Canceled" state. Reset the state to "Idle".
m_state = STATE_IDLE ;
2018-10-23 20:53:43 +00:00
m_print - > set_cancel_callback ( [ ] ( ) { } ) ;
2018-03-28 15:05:31 +00:00
} else if ( m_state = = STATE_FINISHED | | m_state = = STATE_CANCELED ) {
// In the "Finished" or "Canceled" state. Reset the state to "Idle".
m_state = STATE_IDLE ;
2018-10-23 20:53:43 +00:00
m_print - > set_cancel_callback ( [ ] ( ) { } ) ;
2018-03-23 10:41:20 +00:00
}
2018-10-23 13:27:31 +00:00
// this->m_export_path.clear();
2018-03-23 10:41:20 +00:00
return true ;
}
2018-11-08 13:23:17 +00:00
bool BackgroundSlicingProcess : : reset ( )
{
bool stopped = this - > stop ( ) ;
this - > reset_export ( ) ;
m_print - > clear ( ) ;
2018-11-08 19:18:40 +00:00
this - > invalidate_all_steps ( ) ;
2018-11-08 13:23:17 +00:00
return stopped ;
}
2018-10-30 08:27:31 +00:00
// 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 BackgroundSlicingProcess : : stop_internal ( )
{
2018-11-16 17:28:50 +00:00
// m_print->state_mutex() shall be held. Unfortunately there is no interface to test for it.
if ( m_state = = STATE_IDLE )
// The worker thread is waiting on m_mutex/m_condition for wake up. The following lock of the mutex would block.
return ;
2018-10-30 08:27:31 +00:00
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
assert ( m_state = = STATE_STARTED | | m_state = = STATE_RUNNING | | m_state = = STATE_FINISHED | | m_state = = STATE_CANCELED ) ;
if ( m_state = = STATE_STARTED | | m_state = = STATE_RUNNING ) {
2018-11-16 17:28:50 +00:00
// At this point of time the worker thread may be blocking on m_print->state_mutex().
// Set the print state to canceled before unlocking the state_mutex(), so when the worker thread wakes up,
// it throws the CanceledException().
2018-10-30 08:27:31 +00:00
m_print - > cancel_internal ( ) ;
2018-11-16 17:28:50 +00:00
// Allow the worker thread to wake up if blocking on a milestone.
m_print - > state_mutex ( ) . unlock ( ) ;
2018-10-30 08:27:31 +00:00
// Wait until the background processing stops by being canceled.
m_condition . wait ( lck , [ this ] ( ) { return m_state = = STATE_CANCELED ; } ) ;
2018-11-16 17:28:50 +00:00
// Lock it back to be in a consistent state.
m_print - > state_mutex ( ) . lock ( ) ;
2018-10-30 08:27:31 +00:00
}
// In the "Canceled" state. Reset the state to "Idle".
m_state = STATE_IDLE ;
m_print - > set_cancel_callback ( [ ] ( ) { } ) ;
2018-11-13 16:45:44 +00:00
}
bool BackgroundSlicingProcess : : empty ( ) const
{
assert ( m_print ! = nullptr ) ;
return m_print - > empty ( ) ;
2018-10-30 08:27:31 +00:00
}
2018-11-08 19:18:40 +00:00
std : : string BackgroundSlicingProcess : : validate ( )
2018-03-23 10:41:20 +00:00
{
2018-11-08 19:18:40 +00:00
assert ( m_print ! = nullptr ) ;
return m_print - > validate ( ) ;
2018-03-23 10:41:20 +00:00
}
2018-10-18 16:06:40 +00:00
// 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.
2018-10-23 20:53:43 +00:00
Print : : ApplyStatus BackgroundSlicingProcess : : apply ( const Model & model , const DynamicPrintConfig & config )
2018-10-18 16:06:40 +00:00
{
2018-11-08 19:18:40 +00:00
assert ( m_print ! = nullptr ) ;
assert ( config . opt_enum < PrinterTechnology > ( " printer_technology " ) = = m_print - > technology ( ) ) ;
2018-10-23 20:53:43 +00:00
Print : : ApplyStatus invalidated = m_print - > apply ( model , config ) ;
2018-12-19 13:47:16 +00:00
if ( ( invalidated & PrintBase : : APPLY_STATUS_INVALIDATED ) ! = 0 & & m_print - > technology ( ) = = ptFFF & &
m_gcode_preview_data ! = nullptr & & ! this - > m_fff_print - > is_step_done ( psGCodeExport ) ) {
// Some FFF status was invalidated, and the G-code was not exported yet.
// Let the G-code preview UI know that the final G-code preview is not valid.
// In addition, this early memory deallocation reduces memory footprint.
m_gcode_preview_data - > reset ( ) ;
}
2018-10-18 16:06:40 +00:00
return invalidated ;
}
2019-02-21 10:40:56 +00:00
void BackgroundSlicingProcess : : set_task ( const PrintBase : : TaskParams & params )
{
assert ( m_print ! = nullptr ) ;
m_print - > set_task ( params ) ;
}
2018-10-23 13:27:31 +00:00
// Set the output path of the G-code.
2020-03-12 11:43:01 +00:00
void BackgroundSlicingProcess : : schedule_export ( const std : : string & path , bool export_path_on_removable_media )
2018-10-23 13:27:31 +00:00
{
assert ( m_export_path . empty ( ) ) ;
if ( ! m_export_path . empty ( ) )
return ;
// Guard against entering the export step before changing the export path.
2018-11-16 17:28:50 +00:00
tbb : : mutex : : scoped_lock lock ( m_print - > state_mutex ( ) ) ;
2018-10-23 13:27:31 +00:00
this - > invalidate_step ( bspsGCodeFinalize ) ;
m_export_path = path ;
2020-03-12 11:43:01 +00:00
m_export_path_on_removable_media = export_path_on_removable_media ;
2018-10-23 13:27:31 +00:00
}
2018-12-11 09:33:11 +00:00
void BackgroundSlicingProcess : : schedule_upload ( Slic3r : : PrintHostJob upload_job )
{
assert ( m_export_path . empty ( ) ) ;
if ( ! m_export_path . empty ( ) )
return ;
// Guard against entering the export step before changing the export path.
tbb : : mutex : : scoped_lock lock ( m_print - > state_mutex ( ) ) ;
this - > invalidate_step ( bspsGCodeFinalize ) ;
2018-12-19 13:47:16 +00:00
m_export_path . clear ( ) ;
2018-12-11 09:33:11 +00:00
m_upload_job = std : : move ( upload_job ) ;
}
2018-10-23 13:27:31 +00:00
void BackgroundSlicingProcess : : reset_export ( )
{
assert ( ! this - > running ( ) ) ;
if ( ! this - > running ( ) ) {
m_export_path . clear ( ) ;
2020-03-12 11:43:01 +00:00
m_export_path_on_removable_media = false ;
2018-10-23 13:27:31 +00:00
// invalidate_step expects the mutex to be locked.
2018-11-16 17:28:50 +00:00
tbb : : mutex : : scoped_lock lock ( m_print - > state_mutex ( ) ) ;
2018-10-23 13:27:31 +00:00
this - > invalidate_step ( bspsGCodeFinalize ) ;
}
}
2018-11-16 17:28:50 +00:00
bool BackgroundSlicingProcess : : set_step_started ( BackgroundSlicingProcessStep step )
2018-10-23 13:27:31 +00:00
{
2018-11-16 17:28:50 +00:00
return m_step_state . set_started ( step , m_print - > state_mutex ( ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ;
2018-10-23 13:27:31 +00:00
}
void BackgroundSlicingProcess : : set_step_done ( BackgroundSlicingProcessStep step )
{
2018-11-16 17:28:50 +00:00
m_step_state . set_done ( step , m_print - > state_mutex ( ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ;
}
bool BackgroundSlicingProcess : : is_step_done ( BackgroundSlicingProcessStep step ) const
{
return m_step_state . is_done ( step , m_print - > state_mutex ( ) ) ;
2018-10-23 13:27:31 +00:00
}
bool BackgroundSlicingProcess : : invalidate_step ( BackgroundSlicingProcessStep step )
{
2018-11-16 17:28:50 +00:00
bool invalidated = m_step_state . invalidate ( step , [ this ] ( ) { this - > stop_internal ( ) ; } ) ;
2018-10-23 13:27:31 +00:00
return invalidated ;
}
bool BackgroundSlicingProcess : : invalidate_all_steps ( )
{
2018-11-16 17:28:50 +00:00
return m_step_state . invalidate_all ( [ this ] ( ) { this - > stop_internal ( ) ; } ) ;
2018-10-23 13:27:31 +00:00
}
2018-12-20 15:35:54 +00:00
void BackgroundSlicingProcess : : prepare_upload ( )
{
// A print host upload job has been scheduled, enqueue it to the printhost job queue
// XXX: is fs::path::string() right?
// Generate a unique temp path to which the gcode/zip file is copied/exported
boost : : filesystem : : path source_path = boost : : filesystem : : temp_directory_path ( )
2019-04-15 14:14:19 +00:00
/ boost : : filesystem : : unique_path ( " . " SLIC3R_APP_KEY " .upload.%%%%-%%%%-%%%%-%%%% " ) ;
2018-12-20 15:35:54 +00:00
if ( m_print = = m_fff_print ) {
2019-05-09 17:58:16 +00:00
m_print - > set_status ( 95 , _utf8 ( L ( " Running post-processing scripts " ) ) ) ;
2020-02-27 09:44:25 +00:00
if ( copy_file ( m_temp_output_path , source_path . string ( ) ) ! = SUCCESS ) {
2019-05-09 17:58:16 +00:00
throw std : : runtime_error ( _utf8 ( L ( " Copying of the temporary G-code to the output G-code failed " ) ) ) ;
2018-12-20 15:35:54 +00:00
}
2019-01-29 07:57:00 +00:00
run_post_process_scripts ( source_path . string ( ) , m_fff_print - > config ( ) ) ;
2019-10-23 15:10:14 +00:00
m_upload_job . upload_data . upload_path = m_fff_print - > print_statistics ( ) . finalize_output_path ( m_upload_job . upload_data . upload_path . string ( ) ) ;
2019-03-15 11:34:58 +00:00
} else {
2019-10-23 15:10:14 +00:00
m_upload_job . upload_data . upload_path = m_sla_print - > print_statistics ( ) . finalize_output_path ( m_upload_job . upload_data . upload_path . string ( ) ) ;
2020-04-13 10:31:37 +00:00
2019-10-23 15:10:14 +00:00
Zipper zipper { source_path . string ( ) } ;
2020-04-13 10:31:37 +00:00
m_sla_archive . export_print ( zipper , * m_sla_print , m_upload_job . upload_data . upload_path . string ( ) ) ;
2019-11-22 11:39:03 +00:00
if ( m_thumbnail_cb ! = nullptr )
2019-10-25 11:59:13 +00:00
{
2019-11-22 11:39:03 +00:00
ThumbnailsList thumbnails ;
2019-11-28 13:18:24 +00:00
m_thumbnail_cb ( thumbnails , current_print ( ) - > full_print_config ( ) . option < ConfigOptionPoints > ( " thumbnails " ) - > values , true , true , true , true ) ;
// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, false, true, true); // renders also supports and pad
2019-11-22 11:39:03 +00:00
for ( const ThumbnailData & data : thumbnails )
2019-10-25 11:59:13 +00:00
{
if ( data . is_valid ( ) )
write_thumbnail ( zipper , data ) ;
}
}
2019-10-23 15:10:14 +00:00
zipper . finalize ( ) ;
2019-10-23 14:01:23 +00:00
}
2018-12-20 15:35:54 +00:00
2019-10-23 15:10:14 +00:00
m_print - > set_status ( 100 , ( boost : : format ( _utf8 ( L ( " Scheduling upload to `%1%`. See Window -> Print Host Upload Queue " ) ) ) % m_upload_job . printhost - > get_host ( ) ) . str ( ) ) ;
2018-12-20 15:35:54 +00:00
m_upload_job . upload_data . source_path = std : : move ( source_path ) ;
GUI : : wxGetApp ( ) . printhost_job_queue ( ) . enqueue ( std : : move ( m_upload_job ) ) ;
}
2018-03-23 10:41:20 +00:00
} ; // namespace Slic3r