forked from viewit/OrcaSlicer-KX
1. first formal version of macos 2. add the bambu networking plugin install logic 3. auto compute the wipe volume when filament change 4. add the logic of wiping into support 5. refine the GUI layout and icons, improve the gui apperance in lots of small places 6. serveral improve to support 7. support AMS auto-mapping 8. disable lots of unstable features: such as params table, media file download, HMS 9. fix serveral kinds of bugs 10. update the document of building 11. ...
242 lines
7.5 KiB
C++
242 lines
7.5 KiB
C++
#include "MediaPlayCtrl.h"
|
|
#include "Widgets/Button.hpp"
|
|
#include "Widgets/CheckBox.hpp"
|
|
#include "Widgets/Label.hpp"
|
|
#include "GUI_App.hpp"
|
|
#include "libslic3r/AppConfig.hpp"
|
|
#include "I18N.hpp"
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
|
: wxPanel(parent, wxID_ANY, pos, size)
|
|
, m_media_ctrl(media_ctrl)
|
|
{
|
|
SetBackgroundColour(*wxWHITE);
|
|
m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
|
|
|
|
m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
|
|
|
|
m_label_status = new Label(Label::Body_14, this);
|
|
|
|
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto & e) { TogglePlay(); });
|
|
|
|
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) { m_media_ctrl->Play(); });
|
|
|
|
Bind(wxEVT_RIGHT_UP, [this](auto & e) { wxClipboard & c = *wxTheClipboard; if (c.Open()) { c.SetData(new wxTextDataObject(m_url)); c.Close(); } });
|
|
|
|
wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
sizer->Add(m_button_play, 0, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 0);
|
|
sizer->AddStretchSpacer(1);
|
|
sizer->Add(m_label_status, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(25));
|
|
SetSizer(sizer);
|
|
|
|
m_thread = boost::thread([this] {
|
|
media_proc();
|
|
});
|
|
}
|
|
|
|
MediaPlayCtrl::~MediaPlayCtrl()
|
|
{
|
|
{
|
|
boost::unique_lock lock(m_mutex);
|
|
m_tasks.push_back("<exit>");
|
|
m_cond.notify_all();
|
|
}
|
|
m_thread.join();
|
|
}
|
|
|
|
void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
|
{
|
|
std::string machine = obj ? obj->dev_id : "";
|
|
if (machine == m_machine) {
|
|
if (m_last_state == MEDIASTATE_IDLE && m_next_retry.IsValid() && wxDateTime::Now() >= m_next_retry)
|
|
Play();
|
|
return;
|
|
}
|
|
m_machine = machine;
|
|
m_failed_retry = 0;
|
|
if (m_last_state != MEDIASTATE_IDLE)
|
|
Stop();
|
|
//Play();
|
|
SetStatus("");
|
|
}
|
|
|
|
void MediaPlayCtrl::Play()
|
|
{
|
|
if (m_machine.empty()) {
|
|
SetStatus(_L("Initialize failed (No Device)!"));
|
|
return;
|
|
}
|
|
if (m_last_state != MEDIASTATE_IDLE) {
|
|
return;
|
|
}
|
|
m_last_state = MEDIASTATE_INITIALIZING;
|
|
m_button_play->SetIcon("media_stop");
|
|
SetStatus(_L("Initializing..."));
|
|
|
|
|
|
NetworkAgent* agent = wxGetApp().getAgent();
|
|
if (agent) {
|
|
agent->get_camera_url(m_machine, [this](std::string url) {
|
|
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
|
|
CallAfter([this, url] {
|
|
m_url = url;
|
|
if (m_last_state == MEDIASTATE_INITIALIZING) {
|
|
if (url.empty()) {
|
|
Stop();
|
|
m_failed_code = 1;
|
|
SetStatus(_L("Initialize failed [%d]!"));
|
|
} else {
|
|
m_last_state = MEDIASTATE_LOADING;
|
|
SetStatus(_L("Loading..."));
|
|
if (wxGetApp().app_config->get("dump_video") == "true") {
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << boost::filesystem::current_path();
|
|
m_url = m_url + "&dump=video.h264";
|
|
}
|
|
boost::unique_lock lock(m_mutex);
|
|
m_tasks.push_back(m_url);
|
|
m_cond.notify_all();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
void MediaPlayCtrl::Stop()
|
|
{
|
|
if (m_last_state != MEDIASTATE_IDLE) {
|
|
m_media_ctrl->InvalidateBestSize();
|
|
m_button_play->SetIcon("media_play");
|
|
boost::unique_lock lock(m_mutex);
|
|
m_tasks.push_back("<stop>");
|
|
m_cond.notify_all();
|
|
}
|
|
m_last_state = MEDIASTATE_IDLE;
|
|
SetStatus(_L("Stopped."));
|
|
++m_failed_retry;
|
|
//m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(5 * m_failed_retry);
|
|
}
|
|
|
|
void MediaPlayCtrl::TogglePlay()
|
|
{
|
|
if (m_last_state != MEDIASTATE_IDLE)
|
|
Stop();
|
|
else
|
|
Play();
|
|
}
|
|
|
|
void MediaPlayCtrl::SetStatus(wxString const& msg2)
|
|
{
|
|
auto msg = wxString::Format(msg2, m_failed_code);
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data();
|
|
#ifdef __WXMSW__
|
|
OutputDebugStringA("MediaPlayCtrl::SetStatus: ");
|
|
OutputDebugStringA(msg.ToUTF8().data());
|
|
OutputDebugStringA("\n");
|
|
#endif // __WXMSW__
|
|
m_label_status->SetLabel(msg);
|
|
//m_label_status->SetForegroundColour(!msg.EndsWith("!") ? 0x42AE00 : 0x3B65E9);
|
|
Layout();
|
|
}
|
|
|
|
void MediaPlayCtrl::media_proc()
|
|
{
|
|
boost::unique_lock lock(m_mutex);
|
|
while (true) {
|
|
while (m_tasks.empty()) {
|
|
m_cond.wait(lock);
|
|
}
|
|
wxString url = m_tasks.front();
|
|
lock.unlock();
|
|
if (url.IsEmpty()) {
|
|
break;
|
|
}
|
|
else if (url == "<stop>") {
|
|
m_media_ctrl->Stop();
|
|
}
|
|
else if (url == "<exit>") {
|
|
break;
|
|
}
|
|
else if (url == "<play>") {
|
|
m_media_ctrl->Play();
|
|
}
|
|
else {
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
|
m_media_ctrl->Load(wxURI(url));
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
|
|
}
|
|
lock.lock();
|
|
m_tasks.pop_front();
|
|
wxMediaEvent theEvent(wxEVT_MEDIA_STATECHANGED, m_media_ctrl->GetId());
|
|
theEvent.SetId(0);
|
|
m_media_ctrl->GetEventHandler()->AddPendingEvent(theEvent);
|
|
}
|
|
}
|
|
|
|
void MediaPlayCtrl::onStateChanged(wxMediaEvent& event)
|
|
{
|
|
auto last_state = m_last_state;
|
|
auto state = m_media_ctrl->GetState();
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
|
|
if ((int) state < 0)
|
|
return;
|
|
{
|
|
boost::unique_lock lock(m_mutex);
|
|
if (!m_tasks.empty()) {
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: skip when task not finished";
|
|
return;
|
|
}
|
|
}
|
|
if (last_state == MEDIASTATE_IDLE && state == wxMEDIASTATE_STOPPED) {
|
|
return;
|
|
}
|
|
m_last_state = state;
|
|
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) &&
|
|
state == wxMEDIASTATE_STOPPED) {
|
|
Stop();
|
|
return;
|
|
}
|
|
if (last_state == MEDIASTATE_LOADING && state == wxMEDIASTATE_STOPPED) {
|
|
wxSize size = m_media_ctrl->GetVideoSize();
|
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
|
m_failed_code = m_media_ctrl->GetLastError();
|
|
if (size.GetWidth() > 1000) {
|
|
SetStatus(_L("Playing..."));
|
|
m_failed_retry = 0;
|
|
boost::unique_lock lock(m_mutex);
|
|
m_tasks.push_back("<play>");
|
|
m_cond.notify_all();
|
|
}
|
|
else if (event.GetId()) {
|
|
Stop();
|
|
SetStatus(_L("Load failed [%d]!"));
|
|
} else {
|
|
m_last_state = last_state;
|
|
}
|
|
}
|
|
}
|
|
|
|
}}
|
|
|
|
void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
|
{
|
|
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
|
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
|
wxSize size = GetVideoSize();
|
|
if (size.GetWidth() <= 0)
|
|
size = wxSize{16, 9};
|
|
int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
|
|
if (maxHeight != GetMaxHeight()) {
|
|
BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
|
|
SetMaxSize({-1, maxHeight});
|
|
Slic3r::GUI::wxGetApp().CallAfter([this] {
|
|
GetParent()->Layout();
|
|
GetParent()->Refresh();
|
|
});
|
|
}
|
|
}
|
|
|