OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::MediaPlayCtrl Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/MediaPlayCtrl.h>

Inheritance diagram for Slic3r::GUI::MediaPlayCtrl:
Collaboration diagram for Slic3r::GUI::MediaPlayCtrl:

Classes

struct  MediaTask

Public Member Functions

 MediaPlayCtrl (wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize)
 ~MediaPlayCtrl ()
void SetMachineObject (MachineObject *obj)
void SetWebMediaController (IMediaController *ctrl)
void StopWebStream ()
bool IsStreaming () const
void ToggleStream ()
void msw_rescale ()
void jump_to_play ()

Protected Member Functions

void onStateChanged (wxMediaEvent &event)
void Play ()
void Stop (wxString const &msg={}, wxString const &msg2={})
void TogglePlay ()
void SetStatus (wxString const &msg, bool hyperlink=true)
void on_webrtc_status (WebRtcMediaController::Status status)

Private Member Functions

void load ()
void on_show_hide (wxShowEvent &evt)
void media_proc ()
CameraStreamMode current_mode () const
void set_active_media_controller (CameraStreamMode mode)

Static Private Member Functions

static bool start_stream_service (bool *need_install=nullptr)
static bool get_stream_url (std::string *url=nullptr)

Private Attributes

std::shared_ptr< int > m_token = std::make_shared<int>(0)
wxMediaCtrl3 * m_media_ctrl
IMediaController * m_active_media_controller = nullptr
IMediaController * m_web_ctrl = nullptr
std::unique_ptr< WebRtcMediaController > m_webrtc_ctrl
CameraStreamMode m_last_mode = CameraStreamMode::none
std::uint64_t m_webrtc_epoch = 0
std::string m_agent_camera_url
bool m_web_user_stopped = false
wxMediaState m_last_state = MEDIASTATE_IDLE
std::string m_machine
int m_lan_proto = 0
std::string m_lan_ip
std::string m_lan_user
std::string m_lan_passwd
std::string m_dev_ver
std::string m_tutk_state
bool m_camera_exists = false
bool m_lan_mode = false
int m_remote_proto = 0
bool m_device_busy = false
bool m_disable_lan = false
wxString m_url
std::deque< MediaTask > m_tasks
boost::mutex m_mutex
boost::condition_variable m_cond
boost::thread m_thread
bool m_streaming = false
bool m_user_triggered = false
int m_failed_retry = 0
int m_failed_code = 0
std::vector< double > m_stat
std::set< int > m_last_failed_codes
wxDateTime m_last_user_play
wxDateTime m_next_retry
::Button * m_button_play
::Label * m_label_stat
::Label * m_label_status

Static Private Attributes

static const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3)
static const wxMediaState MEDIASTATE_INITIALIZING = static_cast<wxMediaState>(4)
static const wxMediaState MEDIASTATE_LOADING = static_cast<wxMediaState>(5)
static const wxMediaState MEDIASTATE_BUFFERING = static_cast<wxMediaState>(6)

Detailed Description


Class Documentation

◆ Slic3r::GUI::MediaPlayCtrl::MediaTask

struct Slic3r::GUI::MediaPlayCtrl::MediaTask
Collaboration diagram for Slic3r::GUI::MediaPlayCtrl::MediaTask:
Class Members
wxString command
IMediaController * controller = nullptr

Constructor & Destructor Documentation

◆ MediaPlayCtrl()

Slic3r::GUI::MediaPlayCtrl::MediaPlayCtrl ( wxWindow * parent,
wxMediaCtrl3 * media_ctrl,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize )
88 : wxPanel(parent, wxID_ANY, pos, size)
89 , m_media_ctrl(media_ctrl)
90 , m_active_media_controller(media_ctrl)
91{
92 SetLabel("MediaPlayCtrl");
93 SetBackgroundColour(*wxWHITE);
94 m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
95 m_media_ctrl->SetIdleImage(from_u8(resources_dir() + "/images/live_stream_default.png"));
96
97 m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
98 m_button_play->SetCanFocus(false);
99
100 m_label_status = new Label(this, "");
101 m_label_status->SetForegroundColour(wxColour("#323A3C"));
102
103 m_label_stat = new Label(this, "");
104 m_label_stat->SetForegroundColour(wxColour("#323A3C"));
105 m_media_ctrl->Bind(EVT_MEDIA_CTRL_STAT, [this](auto & e) {
106#if !BBL_RELEASE_TO_PUBLIC
107 wxSize size = m_media_ctrl->GetVideoSize();
108 m_label_stat->SetLabel(e.GetString() + wxString::Format(" VS:%ix%i", size.x, size.y));
109#endif
110 wxString str = e.GetString();
111 m_stat.clear();
112 for (auto k : {"FPS:", "BPS:", "T:", "B:"}) {
113 auto ik = str.Find(k);
114 double value = 0;
115 if (ik != wxString::npos) {
116 ik += strlen(k);
117 auto ip = str.find(' ', ik);
118 if (ip == wxString::npos) ip = str.Length();
119 auto v = str.Mid(ik, ip - ik);
120 if (strcmp(k, "T:") == 0 && v.Length() == 8) {
121 long h = 0,m = 0,s = 0;
122 v.Left(2).ToLong(&h);
123 v.Mid(3, 2).ToLong(&m);
124 v.Mid(6, 2).ToLong(&s);
125 value = h * 3600. + m * 60 + s;
126 } else {
127 v.ToDouble(&value);
128 if (v.Right(1) == "K") value *= 1024;
129 else if (v.Right(1) == "%") value *= 0.01;
130 }
131 }
132 m_stat.push_back(value);
133 }
134 });
135
136 m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
137 m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) {
140 });
141 // Orca: live-view FAQ link binding removed (vendor URL)
142
143 Bind(wxEVT_RIGHT_UP, [this](auto & e) {
144 wxClipboard & c = *wxTheClipboard;
145 if (c.Open()) {
146 if (wxGetKeyState(WXK_SHIFT)) {
147 if (c.IsSupported(wxDF_TEXT)) {
148 wxTextDataObject data;
149 c.GetData(data);
150 Stop();
151 m_url = data.GetText();
152 load();
153 }
154 } else {
155 c.SetData(new wxTextDataObject(m_url));
156 }
157 c.Close();
158 }
159 });
160
161 wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
162 sizer->Add(m_button_play, 0, wxEXPAND | wxALL, 0);
163 sizer->Add(m_label_stat, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(25));
164 sizer->AddStretchSpacer(1);
165 sizer->Add(m_label_status, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(25));
166 SetSizer(sizer);
167
168 m_thread = boost::thread([this] {
169 media_proc();
170 });
171
172//#if BBL_RELEASE_TO_PUBLIC
173// m_next_retry = wxDateTime::Now();
174//#endif
175
176 parent->Bind(wxEVT_SHOW, &MediaPlayCtrl::on_show_hide, this);
177 parent->GetParent()->GetParent()->Bind(wxEVT_SHOW, &MediaPlayCtrl::on_show_hide, this);
178
179 m_lan_user = "bblp";
180 m_lan_passwd = "bblp";
181}
void media_proc()
Definition MediaPlayCtrl.cpp:970
wxMediaCtrl3 * m_media_ctrl
Definition MediaPlayCtrl.h:101
std::vector< double > m_stat
Definition MediaPlayCtrl.h:137
IMediaController * m_active_media_controller
Definition MediaPlayCtrl.h:102
::Label * m_label_stat
Definition MediaPlayCtrl.h:143
boost::thread m_thread
Definition MediaPlayCtrl.h:131
void onStateChanged(wxMediaEvent &event)
Definition MediaPlayCtrl.cpp:868
void load()
Definition MediaPlayCtrl.cpp:941
void TogglePlay()
Definition MediaPlayCtrl.cpp:729
wxString m_url
Definition MediaPlayCtrl.h:122
::Button * m_button_play
Definition MediaPlayCtrl.h:142
std::string m_lan_passwd
Definition MediaPlayCtrl.h:114
void on_show_hide(wxShowEvent &evt)
Definition MediaPlayCtrl.cpp:961
::Label * m_label_status
Definition MediaPlayCtrl.h:144
std::string m_lan_user
Definition MediaPlayCtrl.h:113
void Stop(wxString const &msg={}, wxString const &msg2={})
Definition MediaPlayCtrl.cpp:583
wxString from_u8(const std::string &str)
Definition GUI.cpp:544
const std::string & resources_dir()
Definition utils.cpp:296

References Slic3r::GUI::from_u8(), load(), m_active_media_controller, m_button_play, m_label_stat, m_label_status, m_lan_passwd, m_lan_user, m_media_ctrl, m_stat, m_thread, m_url, media_proc(), on_show_hide(), onStateChanged(), Slic3r::resources_dir(), Stop(), and TogglePlay().

Referenced by ToggleStream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~MediaPlayCtrl()

Slic3r::GUI::MediaPlayCtrl::~MediaPlayCtrl ( )
184{
185 if (m_webrtc_ctrl)
186 m_webrtc_ctrl->Stop();
187 m_media_ctrl->EndExternalStream();
188 {
189 boost::unique_lock lock(m_mutex);
190 m_tasks.push_back({"<exit>", nullptr});
191 m_cond.notify_all();
192 }
193 while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
194 wxEventLoopBase::GetActive()->Yield();
195 }
196
197 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << this;
198}
boost::condition_variable m_cond
Definition MediaPlayCtrl.h:130
boost::mutex m_mutex
Definition MediaPlayCtrl.h:129
std::unique_ptr< WebRtcMediaController > m_webrtc_ctrl
Definition MediaPlayCtrl.h:104
std::deque< MediaTask > m_tasks
Definition MediaPlayCtrl.h:128
@ lock
Definition GLGizmoEmboss.cpp:209

References m_cond, m_media_ctrl, m_mutex, m_tasks, m_thread, and m_webrtc_ctrl.

Member Function Documentation

◆ current_mode()

CameraStreamMode Slic3r::GUI::MediaPlayCtrl::current_mode ( ) const
private
233{
234 auto agent = wxGetApp().getAgent();
235 return agent ? agent->get_camera_stream_mode() : CameraStreamMode::none;
236}
@ none
Definition IPrinterAgent.hpp:63

References Slic3r::none.

Referenced by load(), Play(), SetMachineObject(), and SetWebMediaController().

Here is the caller graph for this function:

◆ get_stream_url()

bool Slic3r::GUI::MediaPlayCtrl::get_stream_url ( std::string * url = nullptr)
staticprivate
1078{
1079#ifdef __WIN32__
1080 HANDLE shm = ::OpenFileMapping(FILE_MAP_READ, FALSE, L"bambu_stream_url");
1081 if (shm == NULL) return false;
1082 if (url) {
1083 char *addr = (char *) MapViewOfFile(shm, FILE_MAP_READ, 0, 0, 0);
1084 if (addr) {
1085 *url = addr;
1086 UnmapViewOfFile(addr);
1087 url = nullptr;
1088 }
1089 }
1090 CloseHandle(shm);
1091#else
1092 std::string file_url = data_dir() + "/cameratools/url.txt";
1093 key_t key = ::ftok(file_url.c_str(), 1000);
1094 int shm = ::shmget(key, 1024, 0);
1095 if (shm == -1) return false;
1096 struct shmid_ds ds;
1097 ::shmctl(shm, IPC_STAT, &ds);
1098 if (ds.shm_nattch == 0) {
1099 return false;
1100 }
1101 if (url) {
1102 char *addr = (char *) ::shmat(shm, nullptr, 0);
1103 if (addr != (void*) -1) {
1104 *url = addr;
1105 ::shmdt(addr);
1106 url = nullptr;
1107 }
1108 }
1109#endif
1110 return url == nullptr;
1111}
#define L(s)
Definition ExtrusionEntity.cpp:25
const std::string & data_dir()
Definition utils.cpp:365

References Slic3r::data_dir(), get_stream_url(), and L.

Referenced by get_stream_url(), SetMachineObject(), and ToggleStream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsStreaming()

bool Slic3r::GUI::MediaPlayCtrl::IsStreaming ( ) const
939{ return m_streaming; }
bool m_streaming
Definition MediaPlayCtrl.h:133

References IsStreaming(), and m_streaming.

Referenced by IsStreaming().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ jump_to_play()

void Slic3r::GUI::MediaPlayCtrl::jump_to_play ( )
862{
864 return;
865 TogglePlay();
866}
wxMediaState m_last_state
Definition MediaPlayCtrl.h:109
static const wxMediaState MEDIASTATE_IDLE
Definition MediaPlayCtrl.h:93

References jump_to_play(), m_last_state, MEDIASTATE_IDLE, and TogglePlay().

Referenced by Slic3r::GUI::MultiMachineItem::MultiMachineItem(), and jump_to_play().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load()

void Slic3r::GUI::MediaPlayCtrl::load ( )
private
942{
944 SetStatus(_L("Loading..."));
945 const auto mode = current_mode();
946 if (mode == CameraStreamMode::none && wxGetApp().app_config->get("internal_developer_mode") == "true") {
947 std::string file_h264 = data_dir() + "/video.h264";
948 std::string file_info = data_dir() + "/video.info";
949 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
950 // closed by BambuSource
951 FILE *dump_h264_file = boost::nowide::fopen(file_h264.c_str(), "wb");
952 FILE *dump_info_file = boost::nowide::fopen(file_info.c_str(), "wb");
953 m_url = m_url + "&dump_h264=" + boost::lexical_cast<std::string>(dump_h264_file);
954 m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
955 }
956 boost::unique_lock lock(m_mutex);
958 m_cond.notify_all();
959}
#define _L(s)
Definition OBJ.cpp:34
void SetStatus(wxString const &msg, bool hyperlink=true)
Definition MediaPlayCtrl.cpp:914
static const wxMediaState MEDIASTATE_LOADING
Definition MediaPlayCtrl.h:95
CameraStreamMode current_mode() const
Definition MediaPlayCtrl.cpp:232

References _L, current_mode(), Slic3r::data_dir(), load(), m_active_media_controller, m_cond, m_last_state, m_mutex, m_tasks, m_url, MEDIASTATE_LOADING, Slic3r::none, and SetStatus().

Referenced by MediaPlayCtrl(), load(), and Play().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ media_proc()

void Slic3r::GUI::MediaPlayCtrl::media_proc ( )
private
971{
972 boost::unique_lock lock(m_mutex);
973 while (true) {
974 while (m_tasks.empty()) {
975 m_cond.wait(lock);
976 }
977 MediaTask task = m_tasks.front();
978 if (m_tasks.size() >= 2 && !task.command.IsEmpty() && task.command[0] != '<' &&
979 m_tasks[1].command == "<stop>" && task.controller == m_tasks[1].controller) {
980 BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << task.command;
981 m_tasks.pop_front();
982 m_tasks.pop_front();
983 continue;
984 }
985 lock.unlock();
986 if (task.command == "<stop>") {
987 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
988 if (task.controller)
989 task.controller->Stop();
990 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
991 }
992 else if (task.command == "<exit>") {
993 break;
994 }
995 else if (task.command == "<play>") {
996 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
997 if (task.controller)
998 task.controller->Play();
999 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
1000 }
1001 else {
1002 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
1003 if (task.controller)
1004 task.controller->Load(wxURI(task.command));
1005 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
1006 }
1007 lock.lock();
1008 m_tasks.pop_front();
1009 wxMediaEvent theEvent(wxEVT_MEDIA_STATECHANGED, m_media_ctrl->GetId());
1010 theEvent.SetId(0);
1011 m_media_ctrl->GetEventHandler()->AddPendingEvent(theEvent);
1012 }
1013}
Definition MediaPlayCtrl.h:124
void trace(unsigned int level, const char *message)
Definition utils.cpp:247

References Slic3r::GUI::MediaPlayCtrl::MediaTask::command, Slic3r::GUI::MediaPlayCtrl::MediaTask::controller, Slic3r::GUI::IMediaController::Load(), m_cond, m_media_ctrl, m_mutex, m_tasks, media_proc(), Slic3r::GUI::IMediaController::Play(), Slic3r::GUI::IMediaController::Stop(), and Slic3r::trace().

Referenced by MediaPlayCtrl(), and media_proc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ msw_rescale()

void Slic3r::GUI::MediaPlayCtrl::msw_rescale ( )
857 {
858 m_button_play->Rescale();
859}

References m_button_play, and msw_rescale().

Referenced by msw_rescale().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_show_hide()

void Slic3r::GUI::MediaPlayCtrl::on_show_hide ( wxShowEvent & evt)
private
962{
963 evt.Skip();
964 if (m_isBeingDeleted) return;
965 m_failed_retry = 0;
966 if (!IsShownOnScreen())
967 Stop();
968}
int m_failed_retry
Definition MediaPlayCtrl.h:135

References m_failed_retry, on_show_hide(), and Stop().

Referenced by MediaPlayCtrl(), and on_show_hide().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_webrtc_status()

void Slic3r::GUI::MediaPlayCtrl::on_webrtc_status ( WebRtcMediaController::Status status)
protected
709{
710 // Drop CallAfter-queued events from a superseded Play attempt.
711 if (status.epoch != m_webrtc_epoch)
712 return;
715 SetStatus(_L("Initializing..."), false);
716 } else if (status.kind == WebRtcMediaController::Status::Playing) {
717 m_last_state = wxMEDIASTATE_PLAYING;
718 m_failed_code = 0;
719 m_failed_retry = 0;
720 SetStatus(_L("Playing..."), false);
721 } else if (status.kind == WebRtcMediaController::Status::Failed) {
722 m_failed_code = static_cast<int>(status.code) + 1;
723 Stop();
724 }
725 // Status::Stopped needs no action: a genuine failure arrives as Failed, and
726 // a stop we initiated is already handled by Stop() itself.
727}
int m_failed_code
Definition MediaPlayCtrl.h:136
static const wxMediaState MEDIASTATE_INITIALIZING
Definition MediaPlayCtrl.h:94
std::uint64_t m_webrtc_epoch
Definition MediaPlayCtrl.h:106
@ Connecting
Definition WebRtcMediaController.hpp:39
@ Playing
Definition WebRtcMediaController.hpp:39
@ Failed
Definition WebRtcMediaController.hpp:39

References _L, Slic3r::GUI::WebRtcMediaController::Status::code, Slic3r::GUI::WebRtcMediaController::Status::Connecting, Slic3r::GUI::WebRtcMediaController::Status::epoch, Slic3r::GUI::WebRtcMediaController::Status::Failed, Slic3r::GUI::WebRtcMediaController::Status::kind, m_failed_code, m_failed_retry, m_last_state, m_webrtc_epoch, MEDIASTATE_INITIALIZING, Slic3r::GUI::WebRtcMediaController::Status::Playing, SetStatus(), and Stop().

Referenced by set_active_media_controller().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ onStateChanged()

void Slic3r::GUI::MediaPlayCtrl::onStateChanged ( wxMediaEvent & event)
protected
869{
870 auto last_state = m_last_state;
872 return;
873 auto state = m_active_media_controller->GetState();
874 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
875 if ((int) state < 0) return;
876 {
877 boost::unique_lock lock(m_mutex);
878 if (!m_tasks.empty()) {
879 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: skip when task not finished";
880 return;
881 }
882 }
883 if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
884 if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
886 Stop();
887 return;
888 }
889 if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
890 wxSize size = m_active_media_controller->GetVideoSize();
891 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
893 if (size.GetWidth() >= 320) {
894 m_last_state = state;
895 m_failed_code = 0;
896 SetStatus(_L("Playing..."), false);
897
898
899 m_failed_retry = 0;
900 m_disable_lan = false;
901 boost::unique_lock lock(m_mutex);
902 m_tasks.push_back({"<play>", m_active_media_controller});
903 m_cond.notify_all();
904 } else if (event.GetId()) {
905 if (m_failed_code == 0)
906 m_failed_code = 2;
907 Stop();
908 }
909 } else {
910 m_last_state = state;
911 }
912}
bool m_disable_lan
Definition MediaPlayCtrl.h:121

References _L, m_active_media_controller, m_cond, m_disable_lan, m_failed_code, m_failed_retry, m_last_state, m_media_ctrl, m_mutex, m_tasks, MEDIASTATE_IDLE, MEDIASTATE_INITIALIZING, MEDIASTATE_LOADING, onStateChanged(), SetStatus(), and Stop().

Referenced by MediaPlayCtrl(), and onStateChanged().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Play()

void Slic3r::GUI::MediaPlayCtrl::Play ( )
protected
387{
388 if ((m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry) || !IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
389 return;
390
391 const CameraStreamMode mode = current_mode();
393 m_last_mode = mode;
394 auto agent = wxGetApp().getAgent();
395
396 auto printer_agent = agent ? agent->get_printer_agent() : nullptr;
397 const bool is_bbl = (printer_agent ? printer_agent->get_agent_info().id : "") == BBL_PRINTER_AGENT_ID;
398
399 if (!is_bbl) {
400 const bool is_webrtc = mode == CameraStreamMode::webrtc;
401 const bool is_snapshot = mode == CameraStreamMode::http_snapshot;
402 const bool is_http_stream = mode == CameraStreamMode::http || mode == CameraStreamMode::https || mode == CameraStreamMode::rtsp;
403 if (!is_webrtc && !is_snapshot && !is_http_stream)
404 return;
405
406 auto *webrtc_ctrl = is_webrtc ? dynamic_cast<WebRtcMediaController *>(m_active_media_controller) : nullptr;
407 if (is_webrtc && (!webrtc_ctrl || !m_media_ctrl)) {
408 Stop(_L("Please confirm if the printer is connected."));
409 return;
410 }
411 if (webrtc_ctrl && webrtc_ctrl->is_active())
412 return;
413
414 m_failed_code = 0;
416 (!is_webrtc && m_url.IsEmpty())) {
417 Stop(_L("Please confirm if the printer is connected."));
418 return;
419 }
420
421 if (is_webrtc) {
422 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state << " failed_retry=" << m_failed_retry
423 << " shown=" << IsShownOnScreen();
424 auto channel = agent ? agent->create_camera_signaling_channel(m_machine, wxGetApp().get_printer_cloud_provider()) : nullptr;
425 if (!channel) {
426 Stop(_L("Sign in to OrcaCloud to view the camera."));
427 return;
428 }
429 webrtc_ctrl->set_signalling_channel(std::move(channel));
430 m_media_ctrl->BeginExternalStream();
432 SetStatus(_L("Initializing..."), false);
433 } else if (is_snapshot) {
434 m_last_state = wxMEDIASTATE_PLAYING;
435 SetStatus(_L("Playing..."), false);
436 }
437
438 m_button_play->SetIcon("media_stop");
440 // wxMediaCtrl3 reports when it has a decoded frame; load() waits for
441 // that event before queuing Play so the stream is not marked stopped.
442 load();
443 } else {
444 m_active_media_controller->Load(wxURI(m_url));
446 }
447 if (webrtc_ctrl) {
448 m_webrtc_epoch = webrtc_ctrl->epoch();
449 }
450 return;
451 }
452
453 m_failed_code = 0;
454 if (m_machine.empty()) {
455 Stop(_L("Please confirm if the printer is connected."));
456 return;
457 }
458 if (!IsEnabled()) {
459 Stop(_L("Please confirm if the printer is connected."));
460 return;
461 }
462 if (m_device_busy) {
463 Stop(_L("The printer is currently busy downloading. Please try again after it finishes."));
464 m_failed_retry = 0;
465 return;
466 }
467 if (!m_camera_exists) {
468 Stop(_L("Printer camera is malfunctioning."));
469 return;
470 }
471
472 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
473 std::string agent_version = agent ? agent->get_version() : "";
475 m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
476 std::string url;
478 url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
480 url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
482 url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
483 url += "&device=" + m_machine;
484 url += "&net_ver=" + agent_version;
485 url += "&dev_ver=" + m_dev_ver;
486 url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
487 url += "&cli_ver=" + std::string(SLIC3R_VERSION);
488 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd});
489 m_url = url;
490 load();
491 m_button_play->SetIcon("media_stop");
492 return;
493 }
494
495 // m_lan_mode && m_lan_proto > LVL_Disable (use local tunnel)
496 // m_lan_mode && m_lan_proto == LVL_Disable (*)
497 // m_lan_mode && m_lan_proto == LVL_None (x)
498 // !m_lan_mode && m_remote_proto (go on)
499 // !m_lan_mode && !m_remote_proto && m_lan_proto > LVL_None (use local tunnel)
500 // !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_Disable (*)
501 // !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_None (x)
502
505 ? _L("A problem occurred. Please update the printer firmware and try again.")
506 : _L("LAN Only Liveview is off. Please turn on the liveview on printer screen."));
507 return;
508 }
509
510 m_disable_lan = false;
511 m_failed_code = 0;
513 m_button_play->SetIcon("media_stop");
514
515 if (!m_remote_proto) { // not support tutk
516 m_failed_code = -1;
517 m_url = "bambu:///local/";
518 Stop(_L("Please enter the IP of the printer to connect."));
519 return;
520 }
521
522 m_label_stat->SetLabel({});
523 SetStatus(_L("Initializing..."));
524
525 if (agent) {
526 std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
527 agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
528 [this, m = m_machine, v = agent_version, dv = m_dev_ver, token = std::weak_ptr(m_token)](std::string url) {
529 if (token.expired()) {
530 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": token has been expired";
531 return;
532 }
533
534 if (boost::algorithm::starts_with(url, "bambu:///")) {
535 url += "&device=" + into_u8(m);
536 url += "&net_ver=" + v;
537 url += "&dev_ver=" + dv;
538 url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
539 url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
540 url += "&cli_ver=" + std::string(SLIC3R_VERSION);
541 }
542 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url,
543 {"?uid=", "authkey=", "passwd=", "license=", "token="});
544 CallAfter([this, m, url] {
545 if (m != m_machine) {
546 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
547 return;
548 }
550 if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
551 m_failed_code = 3;
552 if (boost::ends_with(url, "]")) {
553 size_t n = url.find_last_of('[');
554 if (n != std::string::npos)
555 m_failed_code = std::atoi(url.substr(n + 1, url.length() - n - 2).c_str());
556 }
557 Stop(_L("Connection Failed. Please check the network and try again"), from_u8(url));
558 } else {
559 m_url = url;
560 load();
561 }
562 } else {
563 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for state: " << m_last_state;
564 }
565 });
566 }, wxGetApp().get_printer_cloud_provider());
567 }
568}
bool m_camera_exists
Definition MediaPlayCtrl.h:117
int m_lan_proto
Definition MediaPlayCtrl.h:111
int m_remote_proto
Definition MediaPlayCtrl.h:119
wxDateTime m_next_retry
Definition MediaPlayCtrl.h:140
CameraStreamMode m_last_mode
Definition MediaPlayCtrl.h:105
void set_active_media_controller(CameraStreamMode mode)
Definition MediaPlayCtrl.cpp:206
bool m_lan_mode
Definition MediaPlayCtrl.h:118
std::string m_lan_ip
Definition MediaPlayCtrl.h:112
bool m_device_busy
Definition MediaPlayCtrl.h:120
std::string m_dev_ver
Definition MediaPlayCtrl.h:115
std::shared_ptr< int > m_token
Definition MediaPlayCtrl.h:99
std::string m_machine
Definition MediaPlayCtrl.h:110
bool IsEnabled()
Definition dark_mode.cpp:32
void refresh_agora_url(char const *device, char const *dev_ver, char const *channel, void *context, void(*callback)(void *context, char const *url))
Definition MediaPlayCtrl.cpp:374
wxString hide_id_middle_string(wxString const &str, size_t offset=0, size_t length=-1)
Definition MediaPlayCtrl.cpp:340
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
wxString hide_passwd(wxString url, std::vector< wxString > const &passwords)
Definition MediaPlayCtrl.cpp:351
CameraStreamMode
Definition IPrinterAgent.hpp:62
@ webrtc
Definition IPrinterAgent.hpp:67
@ https
Definition IPrinterAgent.hpp:65
@ http
Definition IPrinterAgent.hpp:64
@ http_snapshot
Definition IPrinterAgent.hpp:68
@ rtsp
Definition IPrinterAgent.hpp:66
@ LVL_Disable
Definition PrinterNetworkTypes.hpp:9
@ LVL_Rtsps
Definition PrinterNetworkTypes.hpp:11
@ LVL_Local
Definition PrinterNetworkTypes.hpp:10
@ LVL_None
Definition PrinterNetworkTypes.hpp:8
@ LVL_Rtsp
Definition PrinterNetworkTypes.hpp:12
static constexpr char BBL_PRINTER_AGENT_ID[]
Definition NetworkAgentFactory.hpp:20

References _L, Slic3r::BBL_PRINTER_AGENT_ID, current_mode(), Slic3r::GUI::from_u8(), Slic3r::GUI::hide_id_middle_string(), Slic3r::GUI::hide_passwd(), Slic3r::http, Slic3r::http_snapshot, Slic3r::https, Slic3r::GUI::into_u8(), load(), Slic3r::LVL_Disable, Slic3r::LVL_Local, Slic3r::LVL_None, Slic3r::LVL_Rtsp, Slic3r::LVL_Rtsps, m_active_media_controller, m_button_play, m_camera_exists, m_dev_ver, m_device_busy, m_disable_lan, m_failed_code, m_failed_retry, m_label_stat, m_lan_ip, m_lan_mode, m_lan_passwd, m_lan_proto, m_lan_user, m_last_mode, m_last_state, m_machine, m_media_ctrl, m_next_retry, m_remote_proto, m_token, m_url, m_webrtc_epoch, MEDIASTATE_IDLE, MEDIASTATE_INITIALIZING, Slic3r::GUI::refresh_agora_url(), Slic3r::rtsp, set_active_media_controller(), SetStatus(), Stop(), and Slic3r::webrtc.

Referenced by TogglePlay().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_active_media_controller()

void Slic3r::GUI::MediaPlayCtrl::set_active_media_controller ( CameraStreamMode mode)
private
207{
208 switch (mode) {
210 if (auto *web_ctrl = dynamic_cast<WebMediaController *>(m_web_ctrl))
211 web_ctrl->set_mode(mode);
213 break;
215 if (!m_webrtc_ctrl) {
216 m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
217 [this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
218 [this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
219 if (token.expired())
220 return;
221 CallAfter([this, status] { on_webrtc_status(status); });
222 });
223 }
225 break;
226 default:
228 break;
229 }
230}
IMediaController * m_web_ctrl
Definition MediaPlayCtrl.h:103
void on_webrtc_status(WebRtcMediaController::Status status)
Definition MediaPlayCtrl.cpp:708

References Slic3r::http_snapshot, m_active_media_controller, m_media_ctrl, m_token, m_web_ctrl, m_webrtc_ctrl, on_webrtc_status(), and Slic3r::webrtc.

Referenced by Play(), SetMachineObject(), and SetWebMediaController().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMachineObject()

void Slic3r::GUI::MediaPlayCtrl::SetMachineObject ( MachineObject * obj)
239{
240 const CameraStreamMode mode = current_mode();
241 if (mode != m_last_mode) {
243 m_failed_code = 0; // a mode switch is not a stream failure - don't arm back-off
244 Stop(" ");
245 }
246 m_last_mode = mode;
247 }
249
250 const bool uses_local_camera_url = mode == CameraStreamMode::http || mode == CameraStreamMode::https ||
252 const bool uses_webrtc = mode == CameraStreamMode::webrtc;
253 const std::string machine = obj ? obj->get_dev_id() : "";
254 bool changed = false;
255
256 if (uses_local_camera_url) {
257 auto agent = wxGetApp().getAgent();
258 std::string url = agent ? agent->get_local_camera_stream_url() : "";
259 m_camera_exists = !url.empty();
260 Enable(obj && m_camera_exists);
261 changed = machine != m_machine || url != m_agent_camera_url;
262 m_agent_camera_url = url;
263 m_url = from_u8(url);
264 } else if (uses_webrtc) {
265 m_camera_exists = obj != nullptr;
266 Enable(obj != nullptr);
267 changed = machine != m_machine;
268 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed
269 << " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped;
270 m_url.clear();
271 m_agent_camera_url.clear();
272 } else {
273 if (obj) {
274 m_camera_exists = obj->has_ipcam;
275 m_dev_ver = obj->get_ota_version();
276 m_lan_mode = obj->is_lan_mode_printer();
277 m_lan_proto = obj->liveview_local;
278 m_remote_proto = obj->get_liveview_remote();
279 m_lan_ip = obj->get_dev_ip();
280 m_lan_passwd = obj->get_access_code();
281 m_device_busy = obj->is_camera_busy_off();
282 m_tutk_state = obj->tutk_state;
283
285 // Legacy plugin cannot support remote play for H2D, force using local mode
287 }
288 } else {
289 m_camera_exists = false;
290 m_lan_mode = false;
292 m_lan_ip.clear();
293 m_lan_passwd.clear();
294 m_dev_ver.clear();
295 m_tutk_state.clear();
296 m_remote_proto = 0;
297 m_device_busy = false;
298 }
299 Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
300 if (machine == m_machine)
301 return;
302
303 m_machine = machine;
304 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
305 m_disable_lan = false;
306 m_failed_retry = 0;
307 m_last_failed_codes.clear();
308 m_last_user_play = wxDateTime::Now();
309 std::string stream_url;
310 if (get_stream_url(&stream_url)) {
311 m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
312 } else {
313 m_streaming = false;
314 }
316 Stop(" ");
317 if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
318 m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
319 else
320 SetStatus("", false);
321 return;
322 }
323
324 m_machine = machine;
325 if (!changed)
326 return;
327
328 // A genuine target switch is not a stream failure and should clear the
329 // manual-stop state before the new target is allowed to play.
330 m_web_user_stopped = false;
331 if (uses_local_camera_url) {
332 m_failed_code = 0;
333 m_failed_retry = 0;
334 m_next_retry = wxDateTime();
335 }
337 Stop(" ");
338}
bool use_legacy_network() const
Definition BBLNetworkPlugin.hpp:304
static BBLNetworkPlugin & instance()
Definition BBLNetworkPlugin.cpp:56
static std::string get_printer_series_str(std::string type_str)
Definition DevConfigUtil.h:72
wxDateTime m_last_user_play
Definition MediaPlayCtrl.h:139
std::string m_tutk_state
Definition MediaPlayCtrl.h:116
std::set< int > m_last_failed_codes
Definition MediaPlayCtrl.h:138
static bool get_stream_url(std::string *url=nullptr)
Definition MediaPlayCtrl.cpp:1077
bool m_web_user_stopped
Definition MediaPlayCtrl.h:108
std::string m_agent_camera_url
Definition MediaPlayCtrl.h:107
@ Enable
Definition Config.hpp:245
@ LVR_None
Definition PrinterNetworkTypes.hpp:16

References current_mode(), Slic3r::Enable, Slic3r::GUI::from_u8(), Slic3r::MachineObject::get_access_code(), Slic3r::MachineObject::get_dev_id(), Slic3r::MachineObject::get_dev_ip(), Slic3r::MachineObject::get_liveview_remote(), Slic3r::MachineObject::get_ota_version(), Slic3r::DevPrinterConfigUtil::get_printer_series_str(), get_stream_url(), Slic3r::MachineObject::has_ipcam, Slic3r::http, Slic3r::http_snapshot, Slic3r::https, Slic3r::BBLNetworkPlugin::instance(), Slic3r::MachineObject::is_camera_busy_off(), Slic3r::MachineObject::is_info_ready(), Slic3r::MachineObject::is_lan_mode_printer(), Slic3r::MachineObject::liveview_local, Slic3r::LVL_None, Slic3r::LVR_None, m_agent_camera_url, m_camera_exists, m_dev_ver, m_device_busy, m_disable_lan, m_failed_code, m_failed_retry, m_lan_ip, m_lan_mode, m_lan_passwd, m_lan_proto, m_last_failed_codes, m_last_mode, m_last_state, m_last_user_play, m_machine, m_next_retry, Slic3r::MachineObject::m_push_count, m_remote_proto, m_streaming, m_tutk_state, m_url, m_web_user_stopped, MEDIASTATE_IDLE, Slic3r::MachineObject::printer_type, Slic3r::rtsp, set_active_media_controller(), SetStatus(), Stop(), Slic3r::MachineObject::tutk_state, and Slic3r::webrtc.

Here is the call graph for this function:

◆ SetStatus()

void Slic3r::GUI::MediaPlayCtrl::SetStatus ( wxString const & msg,
bool hyperlink = true )
protected
915{
916 auto msg = msg2;
917 if (m_failed_code != 0) {
920 msg += wxString::Format(" [%d:%d]", state2, m_failed_code);
921 }
922 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data() << " tutk_state: " << m_tutk_state;
923#ifdef __WXMSW__
924 OutputDebugStringA("MediaPlayCtrl::SetStatus: ");
925 OutputDebugStringA(msg.ToUTF8().data());
926 OutputDebugStringA("\n");
927#endif // __WXMSW__
928 m_label_status->SetLabel(msg);
929 m_label_status->Wrap(GetSize().GetWidth() - 120 - m_label_stat->GetSize().GetWidth());
930 long style = m_label_status->GetWindowStyle() & ~LB_HYPERLINK;
931 if (hyperlink) {
933 }
934 m_label_status->SetWindowStyle(style);
935 m_label_status->InvalidateBestSize();
936 Layout();
937}
#define LB_HYPERLINK
Definition Label.hpp:10
#define style
Definition WipeTowerDialog.cpp:101
static const wxMediaState MEDIASTATE_BUFFERING
Definition MediaPlayCtrl.h:96

References LB_HYPERLINK, m_failed_code, m_label_stat, m_label_status, m_last_state, m_tutk_state, MEDIASTATE_BUFFERING, MEDIASTATE_IDLE, SetStatus(), and style.

Referenced by load(), on_webrtc_status(), onStateChanged(), Play(), SetMachineObject(), SetStatus(), Stop(), and StopWebStream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetWebMediaController()

void Slic3r::GUI::MediaPlayCtrl::SetWebMediaController ( IMediaController * ctrl)
201{
202 m_web_ctrl = ctrl;
204}

References current_mode(), m_web_ctrl, and set_active_media_controller().

Here is the call graph for this function:

◆ start_stream_service()

bool Slic3r::GUI::MediaPlayCtrl::start_stream_service ( bool * need_install = nullptr)
staticprivate
1016{
1017#ifdef __WIN32__
1018 auto tools_dir = boost::nowide::widen(data_dir()) + L"\\cameratools\\";
1019 auto file_source = tools_dir + L"bambu_source.exe";
1020 auto file_ffmpeg = tools_dir + L"ffmpeg.exe";
1021 auto file_ff_cfg = tools_dir + L"ffmpeg.cfg";
1022#else
1023 auto tools_dir = data_dir() + "/cameratools/";
1024 auto file_source = tools_dir + "bambu_source";
1025 auto file_ffmpeg = tools_dir + "ffmpeg";
1026 auto file_ff_cfg = tools_dir + "ffmpeg.cfg";
1027#endif
1028 if (!boost::filesystem::exists(file_source) || !boost::filesystem::exists(file_ffmpeg) || !boost::filesystem::exists(file_ff_cfg)) {
1029 if (need_install) *need_install = true;
1030 return false;
1031 }
1032 std::string file_url = data_dir() + "/cameratools/url.txt";
1033 if (!boost::filesystem::exists(file_url)) {
1034 boost::nowide::ofstream file(file_url);
1035 file.close();
1036 }
1037 wxString file_url2 = L"bambu:///camera/" + from_u8(file_url);
1038 file_url2.Replace("\\", "/");
1039 file_url2 = wxURI(file_url2).BuildURI();
1040 try {
1041 std::string configs;
1042 load_string_file(file_ff_cfg, configs);
1043 std::vector<std::string> configss;
1044 boost::algorithm::split(configss, configs, boost::algorithm::is_any_of("\r\n"));
1045 configss.erase(std::remove(configss.begin(), configss.end(), std::string()), configss.end());
1046 boost::process::pipe intermediate;
1047 boost::filesystem::path start_dir(boost::filesystem::path(data_dir()) / "plugins");
1048#ifdef __WXMSW__
1049 auto plugins_dir = boost::nowide::widen(data_dir()) + L"\\plugins\\";
1050 for (auto dll : {L"BambuSource.dll", L"live555.dll"}) {
1051 auto file_dll = tools_dir + dll;
1052 auto file_dll2 = plugins_dir + dll;
1053 if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2))
1054 boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_options::overwrite_existing);
1055 }
1056 boost::process::child process_source(file_source, file_url2.ToStdWstring(), boost::process::start_dir(tools_dir),
1057 boost::process::windows::create_no_window,
1058 boost::process::std_out > intermediate, boost::process::limit_handles);
1059 boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window,
1060 boost::process::std_in < intermediate, boost::process::limit_handles);
1061#else
1062 boost::filesystem::permissions(file_source, boost::filesystem::owner_exe | boost::filesystem::add_perms);
1063 boost::filesystem::permissions(file_ffmpeg, boost::filesystem::owner_exe | boost::filesystem::add_perms);
1064 boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir),
1065 boost::process::std_out > intermediate, boost::process::limit_handles);
1066 boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::std_in < intermediate, boost::process::limit_handles);
1067#endif
1068 process_source.detach();
1069 process_ffmpeg.detach();
1070 } catch (std::exception &e) {
1071 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl failed to start camera stream: " << decode_path(e.what());
1072 return false;
1073 }
1074 return true;
1075}
std::string decode_path(const char *src)
Definition utils.cpp:1401
void load_string_file(const boost::filesystem::path &p, std::string &str)
Definition utils.cpp:2164

References Slic3r::data_dir(), Slic3r::decode_path(), Slic3r::from_u8(), L, Slic3r::load_string_file(), and start_stream_service().

Referenced by start_stream_service(), and ToggleStream().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Stop()

void Slic3r::GUI::MediaPlayCtrl::Stop ( wxString const & msg = {},
wxString const & msg2 = {} )
protected
584{
585 const bool webrtc_active = m_last_mode == CameraStreamMode::webrtc &&
586 dynamic_cast<WebRtcMediaController *>(m_active_media_controller) != nullptr;
587 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state
588 << " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code
589 << " msg='" << msg.ToUTF8().data() << "'";
590 if (webrtc_active) {
592 m_media_ctrl->EndExternalStream();
593 }
594 switch (m_last_mode) {
598 const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot;
600 if (snapshot) {
603 } else {
604 // http/https mode plays through the ffmpeg backend (m_media_ctrl), not
605 // the webview - tear its read thread down too, otherwise it keeps
606 // pulling and painting frames after the UI says "Video Stopped".
607 boost::unique_lock lock(m_mutex);
608 m_tasks.push_back({"<stop>", m_active_media_controller});
609 m_cond.notify_all();
610 }
611 m_button_play->SetIcon("media_play");
613 if (!msg.IsEmpty())
614 SetStatus(msg);
615 else
616 SetStatus(_L("Video Stopped."), false);
617 // Keep retries bounded for an explicit or retry-driven playback attempt.
618 // m_failed_retry is cleared on success (onStateChanged) and on a deliberate
619 // machine switch (SetMachineObject); manual playback via TogglePlay resets it.
620 if (m_failed_code != 0) {
621 const bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false";
623 m_next_retry = auto_retry
624 ? wxDateTime::Now() + wxTimeSpan::Seconds(std::min(5 * m_failed_retry, 30))
625 : wxDateTime::Now() + wxTimeSpan::Days(1); // "off": wait for a manual retry
626 }
627 } else if (!msg.IsEmpty()) {
628 SetStatus(msg, false);
629 }
630 return;
631 }
632 default:
633 break;
634 }
635
636 int last_state = m_last_state;
637
639 m_media_ctrl->InvalidateBestSize();
640 m_button_play->SetIcon("media_play");
641 boost::unique_lock lock(m_mutex);
642 if (!webrtc_active)
643 m_tasks.push_back({"<stop>", m_active_media_controller});
644 m_cond.notify_all();
645 if (!msg.IsEmpty())
646 SetStatus(msg);
647 else if (m_failed_code) {
648 auto iter = error_messages.find(m_failed_code);
649 auto msg2 = iter == error_messages.end()
650 ? _L("Please check the network and try again. You can restart or update the printer if the issue persists.")
651 : _L(iter->second.c_str());
652 if (m_failed_code == 1) {
653 if (m_last_state == wxMEDIASTATE_PLAYING)
654 msg2 = _L("The printer has been logged out and cannot connect.");
655 }
656#if !BBL_RELEASE_TO_PUBLIC && defined(__WINDOWS__)
657 if (m_failed_code < 0)
658 boost::thread ping_thread = Slic3r::create_thread([] {
660 });
661#endif
662 SetStatus(msg2);
663 } else
664 SetStatus(_L("Video Stopped."), false);
666 bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false";
667 if (!auto_retry || m_failed_code >= 100 || m_failed_code == 1) // not keep retry on local error or EOS
668 m_next_retry = wxDateTime();
669 } else if (!msg.IsEmpty()) {
670 SetStatus(msg, false);
671 return;
672 } else {
673 m_failed_code = 0;
674 return;
675 }
676
677 auto tunnel = m_url.empty() ? "" : into_u8(wxURI(m_url).GetPath()).substr(1);
678 if (auto n = tunnel.find_first_of("/_"); n != std::string::npos)
679 tunnel = tunnel.substr(0, n);
680 if (last_state != wxMEDIASTATE_PLAYING && m_failed_code != 0
682 && (m_user_triggered || m_failed_retry > 3)) {
684 }
685
686 m_url.clear();
688 bool local = tunnel == "local" || tunnel == "rtsp" ||
689 tunnel == "rtsps";
690 if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && local && (m_failed_retry > 1 || m_user_triggered)) {
691 m_next_retry = wxDateTime(); // stop retry
692 if (wxGetApp().show_modal_ip_address_enter_dialog(false, _L("LAN Connection Failed (Failed to start liveview)"))) {
693 m_failed_retry = 0;
694 m_user_triggered = true;
695 if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
696 m_last_failed_codes.clear();
697 m_last_user_play = wxDateTime::Now();
698 }
699 m_next_retry = wxDateTime::Now();
700 return;
701 }
702 }
703 m_user_triggered = false;
704 if (m_next_retry.IsValid())
705 m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(5 * m_failed_retry);
706}
bool m_user_triggered
Definition MediaPlayCtrl.h:134
void start_ping_test()
Definition GUI_App.cpp:360
static const std::map< int, std::string > error_messages
Definition SendToPrinter.cpp:101
@ local
Definition Time.hpp:13
boost::thread create_thread(boost::thread::attributes &attrs, Fn &&fn)
Definition Thread.hpp:48

References _L, Slic3r::create_thread(), Slic3r::GUI::error_messages, Slic3r::http, Slic3r::http_snapshot, Slic3r::https, Slic3r::GUI::into_u8(), m_active_media_controller, m_button_play, m_cond, m_failed_code, m_failed_retry, m_last_failed_codes, m_last_mode, m_last_state, m_last_user_play, m_media_ctrl, m_mutex, m_next_retry, m_tasks, m_url, m_user_triggered, MEDIASTATE_IDLE, SetStatus(), Slic3r::GUI::start_ping_test(), and Slic3r::webrtc.

Referenced by MediaPlayCtrl(), on_show_hide(), on_webrtc_status(), onStateChanged(), Play(), SetMachineObject(), and TogglePlay().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StopWebStream()

void Slic3r::GUI::MediaPlayCtrl::StopWebStream ( )
573{
575 return;
578 m_button_play->SetIcon("media_play");
580 SetStatus(_L("Video Stopped."), false);
581}

References _L, m_active_media_controller, m_button_play, m_last_state, m_web_ctrl, MEDIASTATE_IDLE, and SetStatus().

Here is the call graph for this function:

◆ TogglePlay()

void Slic3r::GUI::MediaPlayCtrl::TogglePlay ( )
protected
730{
731 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::TogglePlay";
733 m_next_retry = wxDateTime();
734 m_web_user_stopped = true;
735 Stop();
736 } else {
737 m_failed_retry = 0;
738 m_user_triggered = true;
739 m_web_user_stopped = false;
740 if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
741 m_last_failed_codes.clear();
742 m_last_user_play = wxDateTime::Now();
743 }
744 m_next_retry = wxDateTime::Now();
745 Play();
746 }
747}
void Play()
Definition MediaPlayCtrl.cpp:386

References m_failed_retry, m_last_failed_codes, m_last_state, m_last_user_play, m_next_retry, m_user_triggered, m_web_user_stopped, MEDIASTATE_IDLE, Play(), and Stop().

Referenced by MediaPlayCtrl(), and jump_to_play().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ToggleStream()

void Slic3r::GUI::MediaPlayCtrl::ToggleStream ( )
750{
751 std::string file_url = data_dir() + "/cameratools/url.txt";
752 if (m_streaming) {
753 boost::nowide::ofstream file(file_url);
754 file.close();
755 m_streaming = false;
756 return;
757 } else if (!boost::filesystem::exists(file_url)) {
758 boost::nowide::ofstream file(file_url);
759 file.close();
760 }
761 std::string url;
762 if (!get_stream_url(&url)) {
763 // create stream pipeline
764 bool need_install = false;
765 if (!start_stream_service(&need_install)) {
766 if (!need_install) return;
767 auto res = MessageDialog(this->GetParent(), _L("Virtual Camera Tools is required for this task!\nDo you want to install them?"), _L("Info"),
768 wxOK | wxCANCEL).ShowModal();
769 if (res == wxID_OK) {
770 // download tools
771 struct DownloadProgressDialog2 : DownloadProgressDialog
772 {
773 MediaPlayCtrl *ctrl;
774 DownloadProgressDialog2(MediaPlayCtrl *ctrl) : DownloadProgressDialog(_L("Downloading Virtual Camera Tools")), ctrl(ctrl) {}
775 struct UpgradeNetworkJob2 : UpgradeNetworkJob
776 {
777 UpgradeNetworkJob2() {
778 name = "cameratools";
779 package_name = "camera_tools.zip";
780 }
781 };
782 std::unique_ptr<UpgradeNetworkJob> make_job() override
783 { return std::make_unique<UpgradeNetworkJob2>(); }
784 void on_finish() override
785 {
786 ctrl->CallAfter([ctrl = this->ctrl] { ctrl->ToggleStream(); });
787 EndModal(wxID_CLOSE);
788 }
789 };
790 DownloadProgressDialog2 dlg(this);
791 dlg.ShowModal();
792 }
793 return;
794 }
795 }
796 if (!url.empty() && wxGetApp().app_config->get("not_show_vcamera_stop_prev") != "1") {
797 MessageDialog dlg(this->GetParent(), _L("Another virtual camera is running.\nOrca Slicer supports only a single virtual camera.\nDo you want to stop this virtual camera?"), _L("Warning"),
798 wxYES | wxCANCEL | wxICON_INFORMATION);
799 dlg.show_dsa_button();
800 auto res = dlg.ShowModal();
801 if (dlg.get_checkbox_state())
802 wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1");
803 if (res == wxID_CANCEL) return;
804 }
806 std::string url;
808 url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
810 url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
812 url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
813 url += "&device=" + into_u8(m_machine);
814 url += "&dev_ver=" + m_dev_ver;
815 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd});
816 std::string file_url = data_dir() + "/cameratools/url.txt";
817 boost::nowide::ofstream file(file_url);
818 auto url2 = encode_path(url.c_str());
819 file.write(url2.c_str(), url2.size());
820 file.close();
821 m_streaming = true;
822 return;
823 }
824 NetworkAgent *agent = wxGetApp().getAgent();
825 if (!agent) return;
826 std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
827 agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
828 [this, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) {
829 if (boost::algorithm::starts_with(url, "bambu:///")) {
830 url += "&device=" + m;
831 url += "&net_ver=" + v;
832 url += "&dev_ver=" + dv;
833 url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
834 url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
835 url += "&cli_ver=" + std::string(SLIC3R_VERSION);
836 }
837 BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url,
838 {"?uid=", "authkey=", "passwd=", "license=", "token="});
839 CallAfter([this, m, url] {
840 if (m != m_machine) return;
841 if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
842 MessageDialog(this->GetParent(), wxString::Format(_L("Virtual camera initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)), _L("Information"),
843 wxICON_INFORMATION)
844 .ShowModal();
845 return;
846 }
847 std::string file_url = data_dir() + "/cameratools/url.txt";
848 boost::nowide::ofstream file(file_url);
849 auto url2 = encode_path(url.c_str());
850 file.write(url2.c_str(), url2.size());
851 file.close();
852 m_streaming = true;
853 });
854 }, wxGetApp().get_printer_cloud_provider());
855}
static bool start_stream_service(bool *need_install=nullptr)
Definition MediaPlayCtrl.cpp:1015
std::string encode_path(const char *src)
Definition utils.cpp:1382

References MediaPlayCtrl(), _L, Slic3r::data_dir(), Slic3r::encode_path(), Slic3r::GUI::from_u8(), Slic3r::NetworkAgent::get_camera_url(), Slic3r::GUI::MsgDialog::get_checkbox_state(), get_stream_url(), Slic3r::NetworkAgent::get_version(), Slic3r::GUI::hide_id_middle_string(), Slic3r::GUI::hide_passwd(), Slic3r::GUI::into_u8(), Slic3r::LVL_Disable, Slic3r::LVL_Local, Slic3r::LVL_Rtsp, Slic3r::LVL_Rtsps, m_dev_ver, m_disable_lan, m_lan_ip, m_lan_mode, m_lan_passwd, m_lan_proto, m_lan_user, m_machine, m_remote_proto, m_streaming, Slic3r::GUI::MsgDialog::show_dsa_button(), Slic3r::GUI::DPIAware< P >::ShowModal(), start_stream_service(), and ToggleStream().

Referenced by ToggleStream().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_active_media_controller

IMediaController* Slic3r::GUI::MediaPlayCtrl::m_active_media_controller = nullptr
private

◆ m_agent_camera_url

std::string Slic3r::GUI::MediaPlayCtrl::m_agent_camera_url
private

Referenced by SetMachineObject().

◆ m_button_play

::Button* Slic3r::GUI::MediaPlayCtrl::m_button_play
private

◆ m_camera_exists

bool Slic3r::GUI::MediaPlayCtrl::m_camera_exists = false
private

Referenced by Play(), and SetMachineObject().

◆ m_cond

boost::condition_variable Slic3r::GUI::MediaPlayCtrl::m_cond
private

◆ m_dev_ver

std::string Slic3r::GUI::MediaPlayCtrl::m_dev_ver
private

◆ m_device_busy

bool Slic3r::GUI::MediaPlayCtrl::m_device_busy = false
private

Referenced by Play(), and SetMachineObject().

◆ m_disable_lan

bool Slic3r::GUI::MediaPlayCtrl::m_disable_lan = false
private

◆ m_failed_code

int Slic3r::GUI::MediaPlayCtrl::m_failed_code = 0
private

◆ m_failed_retry

int Slic3r::GUI::MediaPlayCtrl::m_failed_retry = 0
private

◆ m_label_stat

::Label* Slic3r::GUI::MediaPlayCtrl::m_label_stat
private

Referenced by MediaPlayCtrl(), Play(), and SetStatus().

◆ m_label_status

::Label* Slic3r::GUI::MediaPlayCtrl::m_label_status
private

Referenced by MediaPlayCtrl(), and SetStatus().

◆ m_lan_ip

std::string Slic3r::GUI::MediaPlayCtrl::m_lan_ip
private

◆ m_lan_mode

bool Slic3r::GUI::MediaPlayCtrl::m_lan_mode = false
private

◆ m_lan_passwd

std::string Slic3r::GUI::MediaPlayCtrl::m_lan_passwd
private

◆ m_lan_proto

int Slic3r::GUI::MediaPlayCtrl::m_lan_proto = 0
private

◆ m_lan_user

std::string Slic3r::GUI::MediaPlayCtrl::m_lan_user
private

Referenced by MediaPlayCtrl(), Play(), and ToggleStream().

◆ m_last_failed_codes

std::set<int> Slic3r::GUI::MediaPlayCtrl::m_last_failed_codes
private

Referenced by SetMachineObject(), Stop(), and TogglePlay().

◆ m_last_mode

CameraStreamMode Slic3r::GUI::MediaPlayCtrl::m_last_mode = CameraStreamMode::none
private

Referenced by Play(), SetMachineObject(), and Stop().

◆ m_last_state

wxMediaState Slic3r::GUI::MediaPlayCtrl::m_last_state = MEDIASTATE_IDLE
private

◆ m_last_user_play

wxDateTime Slic3r::GUI::MediaPlayCtrl::m_last_user_play
private

Referenced by SetMachineObject(), Stop(), and TogglePlay().

◆ m_machine

std::string Slic3r::GUI::MediaPlayCtrl::m_machine
private

◆ m_media_ctrl

wxMediaCtrl3* Slic3r::GUI::MediaPlayCtrl::m_media_ctrl
private

◆ m_mutex

boost::mutex Slic3r::GUI::MediaPlayCtrl::m_mutex
private

◆ m_next_retry

wxDateTime Slic3r::GUI::MediaPlayCtrl::m_next_retry
private

◆ m_remote_proto

int Slic3r::GUI::MediaPlayCtrl::m_remote_proto = 0
private

◆ m_stat

std::vector<double> Slic3r::GUI::MediaPlayCtrl::m_stat
private

Referenced by MediaPlayCtrl().

◆ m_streaming

bool Slic3r::GUI::MediaPlayCtrl::m_streaming = false
private

◆ m_tasks

std::deque<MediaTask> Slic3r::GUI::MediaPlayCtrl::m_tasks
private

◆ m_thread

boost::thread Slic3r::GUI::MediaPlayCtrl::m_thread
private

Referenced by MediaPlayCtrl(), and ~MediaPlayCtrl().

◆ m_token

std::shared_ptr<int> Slic3r::GUI::MediaPlayCtrl::m_token = std::make_shared<int>(0)
private

◆ m_tutk_state

std::string Slic3r::GUI::MediaPlayCtrl::m_tutk_state
private

Referenced by SetMachineObject(), and SetStatus().

◆ m_url

wxString Slic3r::GUI::MediaPlayCtrl::m_url
private

◆ m_user_triggered

bool Slic3r::GUI::MediaPlayCtrl::m_user_triggered = false
private

Referenced by Stop(), and TogglePlay().

◆ m_web_ctrl

IMediaController* Slic3r::GUI::MediaPlayCtrl::m_web_ctrl = nullptr
private

◆ m_web_user_stopped

bool Slic3r::GUI::MediaPlayCtrl::m_web_user_stopped = false
private

Referenced by SetMachineObject(), and TogglePlay().

◆ m_webrtc_ctrl

std::unique_ptr<WebRtcMediaController> Slic3r::GUI::MediaPlayCtrl::m_webrtc_ctrl
private

◆ m_webrtc_epoch

std::uint64_t Slic3r::GUI::MediaPlayCtrl::m_webrtc_epoch = 0
private

Referenced by on_webrtc_status(), and Play().

◆ MEDIASTATE_BUFFERING

const wxMediaState Slic3r::GUI::MediaPlayCtrl::MEDIASTATE_BUFFERING = static_cast<wxMediaState>(6)
inlinestaticprivate

Referenced by SetStatus().

◆ MEDIASTATE_IDLE

const wxMediaState Slic3r::GUI::MediaPlayCtrl::MEDIASTATE_IDLE = static_cast<wxMediaState>(3)
inlinestaticprivate

◆ MEDIASTATE_INITIALIZING

const wxMediaState Slic3r::GUI::MediaPlayCtrl::MEDIASTATE_INITIALIZING = static_cast<wxMediaState>(4)
inlinestaticprivate

◆ MEDIASTATE_LOADING

const wxMediaState Slic3r::GUI::MediaPlayCtrl::MEDIASTATE_LOADING = static_cast<wxMediaState>(5)
inlinestaticprivate

Referenced by load(), and onStateChanged().


The documentation for this class was generated from the following files: