//Copyright (c) 2018 Ultimaker B.V. //CuraEngine is released under the terms of the AGPLv3 or higher. #ifdef _OPENMP #include // omp_get_num_threads #endif // _OPENMP #include #include "Application.h" #include "FffProcessor.h" #include "communication/ArcusCommunication.h" //To connect via Arcus to the front-end. #include "communication/CommandLine.h" //To use the command line to slice stuff. #include "progress/Progress.h" #include "utils/logoutput.h" #include "utils/string.h" //For stringcasecompare. namespace cura { Application::Application() : communication(nullptr) , current_slice(0) { } Application::~Application() { delete communication; } Application& Application::getInstance() { static Application instance; //Constructs using the default constructor. return instance; } #ifdef ARCUS void Application::connect() { std::string ip = "127.0.0.1"; int port = 49674; //Parse port number from IP address. std::string ip_port(argv[2]); std::size_t found_pos = ip_port.find(':'); if (found_pos != std::string::npos) { ip = ip_port.substr(0, found_pos); port = std::stoi(ip_port.substr(found_pos + 1).data()); } #ifdef _OPENMP int n_threads; #endif // _OPENMP for(size_t argn = 3; argn < argc; argn++) { char* str = argv[argn]; if (str[0] == '-') { for(str++; *str; str++) { switch(*str) { case 'v': increaseVerboseLevel(); break; #ifdef _OPENMP case 'm': str++; n_threads = std::strtol(str, &str, 10); str--; n_threads = std::max(1, n_threads); omp_set_num_threads(n_threads); break; #endif // _OPENMP default: logError("Unknown option: %c\n", *str); printCall(); printHelp(); break; } } } } ArcusCommunication* arcus_communication = new ArcusCommunication(); arcus_communication->connect(ip, port); communication = arcus_communication; } #endif //ARCUS void Application::printCall() const { cura::logError("Command called:\n"); for (size_t argument_index = 0; argument_index < argc; argument_index++) { cura::logError("%s ", argv[argument_index]); } cura::logError("\n"); } void Application::printHelp() const { logAlways("\n"); logAlways("usage:\n"); logAlways("CuraEngine help\n"); logAlways("\tShow this help message\n"); logAlways("\n"); #ifdef ARCUS logAlways("CuraEngine connect [:] [-j ]\n"); logAlways(" --connect [:]\n\tConnect to via a command socket, \n\tinstead of passing information via the command line\n"); logAlways(" -v\n\tIncrease the verbose level (show log messages).\n"); #ifdef _OPENMP logAlways(" -m\n\tSet the desired number of threads. Supports only a single digit.\n"); #endif // _OPENMP logAlways("\n"); #endif //ARCUS logAlways("CuraEngine slice [-v] [-p] [-j ] [-s =] [-g] [-e] [-o ] [-l ] [--next]\n"); logAlways(" -v\n\tIncrease the verbose level (show log messages).\n"); #ifdef _OPENMP logAlways(" -m\n\tSet the desired number of threads.\n"); #endif // _OPENMP logAlways(" -p\n\tLog progress information.\n"); logAlways(" -j\n\tLoad settings.def.json file to register all settings and their defaults.\n"); logAlways(" -s =\n\tSet a setting to a value for the last supplied object, \n\textruder train, or general settings.\n"); logAlways(" -l \n\tLoad an STL model. \n"); logAlways(" -g\n\tSwitch setting focus to the current mesh group only.\n\tUsed for one-at-a-time printing.\n"); logAlways(" -e\n\tSwitch setting focus to the extruder train with the given number.\n"); logAlways(" --next\n\tGenerate gcode for the previously supplied mesh group and append that to \n\tthe gcode of further models for one-at-a-time printing.\n"); logAlways(" -o \n\tSpecify a file to which to write the generated gcode.\n"); logAlways("\n"); logAlways("The settings are appended to the last supplied object:\n"); logAlways("CuraEngine slice [general settings] \n\t-g [current group settings] \n\t-e0 [extruder train 0 settings] \n\t-l obj_inheriting_from_last_extruder_train.stl [object settings] \n\t--next [next group settings]\n\t... etc.\n"); logAlways("\n"); logAlways("In order to load machine definitions from custom locations, you need to create the environment variable CURA_ENGINE_SEARCH_PATH, which should contain all search paths delimited by a (semi-)colon.\n"); logAlways("\n"); } void Application::printLicense() const { logAlways("\n"); logAlways("Cura_SteamEngine version %s\n", VERSION); logAlways("Copyright (C) 2021 Ultimaker\n"); logAlways("\n"); logAlways("This program is free software: you can redistribute it and/or modify\n"); logAlways("it under the terms of the GNU Affero General Public License as published by\n"); logAlways("the Free Software Foundation, either version 3 of the License, or\n"); logAlways("(at your option) any later version.\n"); logAlways("\n"); logAlways("This program is distributed in the hope that it will be useful,\n"); logAlways("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); logAlways("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); logAlways("GNU Affero General Public License for more details.\n"); logAlways("\n"); logAlways("You should have received a copy of the GNU Affero General Public License\n"); logAlways("along with this program. If not, see .\n"); } void Application::slice() { std::vector arguments; for (size_t argument_index = 0; argument_index < argc; argument_index++) { arguments.emplace_back(argv[argument_index]); } communication = new CommandLine(arguments); } void Application::run(const size_t argc, char** argv) { this->argc = argc; this->argv = argv; printLicense(); Progress::init(); if (argc < 2) { printHelp(); exit(1); } #pragma omp parallel { #pragma omp master { #ifdef _OPENMP log("OpenMP multithreading enabled, likely number of threads to be used: %u\n", omp_get_num_threads()); #else log("OpenMP multithreading disabled\n"); #endif } } #ifdef ARCUS if (stringcasecompare(argv[1], "connect") == 0) { connect(); } else #endif //ARCUS if (stringcasecompare(argv[1], "slice") == 0) { slice(); } else if (stringcasecompare(argv[1], "help") == 0) { printHelp(); } else { logError("Unknown command: %s\n", argv[1]); printCall(); printHelp(); exit(1); } if (!communication) { //No communication channel is open any more, so either: //- communication failed to connect, or //- the engine was called with an unknown command or a command that doesn't connect (like "help"). //In either case, we don't want to slice. exit(0); } while (communication->hasSlice()) { communication->sliceNext(); } } } //Cura namespace.