BambuSrc/slic3r/GUI/Printer/PrinterFileSystem.h

393 lines
11 KiB
C++

#ifndef slic3r_GUI_PrinterFileSystem_h_
#define slic3r_GUI_PrinterFileSystem_h_
#define BAMBU_DYNAMIC
#include "BambuTunnel.h"
#include <wx/bitmap.h>
#include <wx/event.h>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "nlohmann/json_fwd.hpp"
using nlohmann::json;
#include <functional>
#include <deque>
wxDECLARE_EVENT(EVT_STATUS_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_MODE_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
wxDECLARE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
wxDECLARE_EVENT(EVT_MEDIA_ABILITY_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPLOADING, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPLOAD_CHANGED, wxCommandEvent);
class PrinterFileSystem : public wxEvtHandler, public boost::enable_shared_from_this<PrinterFileSystem>, BambuLib
{
static const int CTRL_TYPE = 0x3001;
enum {
LIST_INFO = 0x0001,
SUB_FILE = 0x0002,
FILE_DEL = 0x0003,
FILE_DOWNLOAD = 0x0004,
FILE_UPLOAD = 0x0005,
REQUEST_MEDIA_ABILITY = 0x0007,
NOTIFY_FIRST = 0x0100,
LIST_CHANGE_NOTIFY = 0x0100,
LIST_RESYNC_NOTIFY = 0x0101,
TASK_CANCEL = 0x1000
};
public:
enum {
SUCCESS = 0,
CONTINUE = 1,
ERROR_JSON = 2,
ERROR_PIPE = 3,
ERROR_CANCEL = 4,
ERROR_RES_BUSY = 5,
ERROR_TIME_OUT = 6,
FILE_NO_EXIST = 10,
FILE_NAME_INVALID = 11,
FILE_SIZE_ERR = 12,
FILE_OPEN_ERR = 13,
FILE_READ_WRITE_ERR = 14,
FILE_CHECK_ERR = 15,
FILE_TYPE_ERR = 16,
STORAGE_UNAVAILABLE = 17,
API_VERSION_UNSUPPORT = 18,
FILE_EXIST = 19,
STORAGE_SPACE_NOT_ENOUGH = 20,
FILE_CREATE_ERR = 21,
FILE_WRITE_ERR = 22,
MD5_COMPARE_ERR = 23,
FILE_RENAME_ERR = 24,
SEND_ERR = 25,
};
public:
PrinterFileSystem();
~PrinterFileSystem();
public:
enum FileType {
F_TIMELAPSE,
F_VIDEO,
F_MODEL,
F_INVALID_TYPE,
};
enum GroupMode {
G_NONE,
G_MONTH,
G_YEAR,
};
void SetFileType(FileType type, std::string const & storage = {});
void SetGroupMode(GroupMode mode);
size_t EnterSubGroup(size_t index);
FileType GetFileType() const { return m_file_type; }
GroupMode GetGroupMode() const { return m_group_mode; }
template<typename T> using Callback = std::function<void(int, T)>;
enum Flags {
FF_SELECT = 1,
FF_THUMNAIL = 2, // Thumbnail ready
FF_DOWNLOAD = 4, // Request download
FF_DELETED = 8, // Request delete
FF_FETCH_MODEL = 16, // Request model
FF_UPLOADING = 1 << 5, // File uploading
FF_UPLOADDONE = 1 << 6, // File upload done
FF_UPLOADCANCEL = 1 << 7, // File upload cancel
FF_THUMNAIL_RETRY = 0x100, // Thumbnail need retry
};
enum UploadStatus
{
Uploading = 1 << 0,
UploadDone = 1 << 1,
UploadCancel = 1 << 2,
};
enum RequestMediaAbilityStatus
{
S_SUCCESS,
S_FAILED
};
struct Progress
{
wxInt64 size = 0;
wxInt64 total = 0;
int progress = 0;
};
struct Download;
struct Upload;
struct File
{
std::string name;
std::string path;
time_t time = 0;
boost::uint64_t size = 0;
int flags = 0;
wxBitmap thumbnail;
std::shared_ptr<Download> download;
std::string local_path;
std::map<std::string, std::string> metadata;
bool IsSelect() const { return flags & FF_SELECT; }
bool IsDownload() const { return flags & FF_DOWNLOAD; }
int DownloadProgress() const;
std::string Title() const;
std::string Metadata(std::string const &key, std::string const &dflt) const;
friend bool operator<(File const & l, File const & r) { return l.time > r.time; }
};
struct UploadFile
{
std::string name;
std::string path;
std::string select_storage;
int flags{0};
boost::uint32_t size{0};
boost::uint32_t chunk_size{0}; // KB
std::unique_ptr<Upload> upload;
bool IsUploading() const { return flags & FF_UPLOADING; }
~UploadFile();
};
struct Void {};
typedef std::vector<File> FileList;
typedef std::vector<std::string> MediaAbilityList;
void ListAllFiles();
void DeleteFiles(size_t index);
void DownloadFiles(size_t index, std::string const &path);
void DownloadCheckFiles(std::string const &path);
bool DownloadCheckFile(size_t index);
void DownloadCancel(size_t index);
void FetchModel(size_t index, std::function<void(int, std::string const &)> callback);
void FetchModelCancel();
size_t GetCount() const;
size_t GetIndexAtTime(boost::uint32_t time);
void ToggleSelect(size_t index);
void SelectAll(bool select);
size_t GetSelectCount() const;
void SetFocusRange(size_t start, size_t count);
File const &GetFile(size_t index);
File const &GetFile(size_t index, bool &select);
enum Status {
Initializing,
Connecting,
ListSyncing,
ListReady,
Failed,
};
Status GetStatus() const { return m_status; }
int GetLastError() const { return m_last_error; }
void Attached();
void Start();
void Retry();
void SetUrl(std::string const &url);
void Stop(bool quit = false);
boost::uint32_t RequestMediaAbility(int api_version);
void RequestUploadFile();
MediaAbilityList GetMediaAbilityList() const;
void SetUploadFile(const std::string& path, const std::string& name, const std::string& select_storage);
void CancelUploadTask(bool send_cancel_req = true);
private:
void BuildGroups();
void UpdateGroupSelect();
void DeleteFilesContinue();
void DownloadNextFile();
void UpdateFocusThumbnail();
static bool ParseThumbnail(File &file);
static bool ParseThumbnail(File &file, std::istream &is);
void UpdateFocusThumbnail2(std::shared_ptr<std::vector<File>> files, int type);
void FileRemoved(std::pair<FileType, std::string> type, size_t index, std::string const &name, bool by_path);
std::pair<FileList &, size_t> FindFile(std::pair<FileType, std::string> type, size_t index, std::string const &name, bool by_path);
void SendChangedEvent(wxEventType type, size_t index = (size_t)-1, std::string const &str = {}, long extra = 0);
static void DumpLog(void* context, int level, tchar const *msg);
private:
template<typename T> using Translator = std::function<int(json const &, T &, unsigned char const *)>;
typedef std::function<void(int, json const & resp)> callback_t;
typedef std::function<int(int, json const &resp, unsigned char const *data)> callback_t2;
typedef std::function<int(std::string &msg)> callback_t3;
template<typename T> boost::uint32_t SendRequest(int type, json const &req, Translator<T> const &translator, Callback<T> const &callback)
{
auto c = [translator, callback, this](int result, json const &resp, unsigned char const *data) -> int
{
T t;
if (result == 0 || result == CONTINUE || result == FILE_EXIST) {
try {
int n = (translator != nullptr) ? translator(resp, t, data) : 0;
result = n == 0 ? result : n;
}
catch (...) {
result = ERROR_JSON;
}
}
PostCallback<T>(callback, result, t);
return result;
};
return SendRequest(type, req, c);
}
template<typename T> using Applier = std::function<void(T const &)>;
template<typename T>
void InstallNotify(int type, Translator<T> const& translator, Applier<T> const& applier)
{
auto c = [translator, applier, this](int result, json const &resp, unsigned char const *data) -> int
{
T t;
if (result == 0 || result == CONTINUE) {
try {
int n = (translator != nullptr) ? translator(resp, t, data) : 0;
result = n == 0 ? result : n;
}
catch (...) {
result = ERROR_JSON;
}
}
if (result == 0 && applier) {
PostCallback<T>([applier](int, T const & t) {
applier(t);
}, 0, t);
}
return result;
};
InstallNotify(type, c);
}
boost::uint32_t SendRequest(int type, json const &req, callback_t2 const &callback);
void InstallNotify(int type, callback_t2 const &callback);
void CancelRequest(boost::uint32_t seq);
void CancelRequests(std::vector<boost::uint32_t> const &seqs);
void CancelRequests2(std::vector<boost::uint32_t> const & seqs);
void RecvMessageThread();
void HandleResponse(boost::unique_lock<boost::mutex> &l, Bambu_Sample const &sample);
void Reconnect(boost::unique_lock<boost::mutex> & l, int result);
template <typename T>
void PostCallback(Callback<T> const& callback, int result, T const& resp)
{
PostCallback([=] { callback(result, resp); });
}
void PostCallback(std::function<void(void)> const & callback);
int UploadFileTask(std::shared_ptr<UploadFile> upload_file, boost::uint64_t seq, std::string &msg);
protected:
FileType m_file_type = F_INVALID_TYPE;
std::string m_file_storage;
GroupMode m_group_mode = G_NONE;
FileList m_file_list;
std::map<std::pair<FileType, std::string>, FileList> m_file_list_cache;
std::vector<size_t> m_group_year;
std::vector<size_t> m_group_month;
std::vector<int> m_group_flags;
std::shared_ptr<UploadFile> m_upload_file;
private:
size_t m_select_count = 0;
size_t m_lock_start = 0;
size_t m_lock_end = 0;
int m_task_flags = 0;
private:
struct Session
{
Bambu_Tunnel tunnel = nullptr;
PrinterFileSystem * owner;
};
Session m_session;
boost::uint32_t m_sequence = 0;
boost::uint32_t m_download_seq = 0;
boost::uint32_t m_fetch_model_seq = 0;
boost::uint32_t m_upload_seq = 0;
std::deque<std::string> m_messages;
std::deque<callback_t2> m_callbacks;
std::deque<callback_t2> m_notifies;
bool m_stopped = true;
boost::mutex m_mutex;
boost::condition_variable m_cond;
boost::thread m_recv_thread;
Status m_status;
int m_last_error = 0;
MediaAbilityList m_media_ability_list;
std::map<boost::uint32_t, callback_t3> m_produce_message_cb_map;
};
#endif // !slic3r_GUI_PrinterFileSystem_h_