#ifndef slic3r_GUI_PrinterFileSystem_h_ #define slic3r_GUI_PrinterFileSystem_h_ #define BAMBU_DYNAMIC #include "BambuTunnel.h" #include #include #include #include "nlohmann/json_fwd.hpp" using nlohmann::json; #include #include wxDECLARE_EVENT(EVT_STATUS_CHANGED, wxCommandEvent); wxDECLARE_EVENT(EVT_MODE_CHANGED, wxCommandEvent); wxDECLARE_EVENT(EVT_FILE_CHANGED, wxCommandEvent); wxDECLARE_EVENT(EVT_THUMBNAIL, wxCommandEvent); wxDECLARE_EVENT(EVT_DOWNLOAD, wxCommandEvent); class PrinterFileSystem : public wxEvtHandler, public boost::enable_shared_from_this, BambuLib { static const int CTRL_TYPE = 0x3001; enum { LIST_INFO = 0x0001, THUMBNAIL = 0x0002, FILE_DEL = 0x0003, FILE_DOWNLOAD = 0X0004, NOTIFY_FIRST = 0x0100, LIST_CHANGE_NOTIFY = 0x0100, LIST_RESYNC_NOTIFY = 0x0101, TASK_CANCEL = 0x1000 }; enum { SUCCESS = 0, CONTINUE = 1, ERROR_JSON = 2, ERROR_PIPE = 3, ERROR_CANCEL = 4, FILE_NO_EXIST = 10, FILE_NAME_INVALID = 11, FILE_SIZE_ERR = 12, FILE_OPEN_ERR = 13, FILE_READ_ERR = 14, FILE_CHECK_ERR = 15, }; public: PrinterFileSystem(); ~PrinterFileSystem(); public: enum FileType { F_TIMELAPSE, F_VIDEO, }; enum GroupMode { G_NONE, G_MONTH, G_YEAR, }; void SetFileType(FileType type); void SetGroupMode(GroupMode mode); size_t EnterSubGroup(size_t index); GroupMode GetFileType() const { return m_group_mode; } GroupMode GetGroupMode() const { return m_group_mode; } template using Callback = std::function; enum Flags { FF_SELECT = 1, FF_THUMNAIL = 2, // Thumbnail ready FF_DOWNLOAD = 4, // Request download FF_DELETED = 8, // Request delete }; struct File { std::string name; time_t time = 0; boost::uint64_t size = 0; wxBitmap thumbnail; int flags = 0; int progress = -1; // -1: waiting std::string path; bool IsSelect() const { return flags & FF_SELECT; } bool IsDownload() const { return flags & FF_DOWNLOAD; } friend bool operator<(File const & l, File const & r) { return l.time > r.time; } }; struct Void {}; typedef std::vector FileList; struct Thumbnail { std::string name; wxBitmap thumbnail; }; struct Progress { wxInt64 size; wxInt64 total; }; void ListAllFiles(); void DeleteFiles(size_t index); void DownloadFiles(size_t index, std::string const &path); void DownloadCheckFiles(std::string const &path); void DownloadCancel(size_t index); size_t GetCount() const; size_t GetIndexAtTime(boost::uint32_t time); void ToggleSelect(size_t index); void SelectAll(bool select); void SetFocusRange(size_t start, size_t count); File const &GetFile(size_t index); 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); private: void BuildGroups(); void DeleteFilesContinue(); void DownloadNextFile(); void UpdateFocusThumbnail(); void FileRemoved(size_t index, std::string const &name); size_t FindFile(size_t index, std::string const &name); 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 using Translator = std::function; typedef std::function callback_t; typedef std::function callback_t2; template boost::uint32_t SendRequest(int type, json const& req, Translator const& translator, Callback const& callback) { auto c = [translator, callback, this](int result, json const &resp, unsigned char const *data) { 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; } } PostCallback(callback, result, t); }; return SendRequest(type, req, c); } template using Applier = std::function; template void InstallNotify(int type, Translator const& translator, Applier const& applier) { auto c = [translator, applier, this](int result, json const &resp, unsigned char const *data) { 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([applier](int, T const & t) { applier(t); }, 0, t); } }; 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 RecvMessageThread(); void HandleResponse(boost::unique_lock &l, Bambu_Sample const &sample); void Reconnect(boost::unique_lock & l, int result); int RecvData(std::function const & callback); template void PostCallback(Callback const& callback, int result, T const& resp) { PostCallback([=] { callback(result, resp); }); } void PostCallback(std::function const & callback); protected: FileType m_file_type = F_TIMELAPSE; GroupMode m_group_mode = G_NONE; FileList m_file_list; FileList m_file_list2; std::vector m_group_year; std::vector m_group_month; private: 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; std::deque m_messages; std::deque m_callbacks; std::deque 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; }; #endif // !slic3r_GUI_PrinterFileSystem_h_