mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 19:01:02 +00:00
refactor: media controller playback routing and ownership
This commit is contained in:
@@ -3,10 +3,6 @@
|
|||||||
#include <wx/mediactrl.h>
|
#include <wx/mediactrl.h>
|
||||||
#include <wx/uri.h>
|
#include <wx/uri.h>
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <slic3r/Utils/IPrinterAgent.hpp>
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
class IMediaController
|
class IMediaController
|
||||||
@@ -16,13 +12,6 @@ public:
|
|||||||
|
|
||||||
virtual void Load(wxURI url) = 0;
|
virtual void Load(wxURI url) = 0;
|
||||||
|
|
||||||
// The default keeps existing media controllers unaware of camera-specific modes.
|
|
||||||
virtual void Load(wxURI url, CameraStreamMode mode)
|
|
||||||
{
|
|
||||||
(void) mode;
|
|
||||||
Load(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Play() = 0;
|
virtual void Play() = 0;
|
||||||
|
|
||||||
virtual void Stop() = 0;
|
virtual void Stop() = 0;
|
||||||
@@ -32,15 +21,6 @@ public:
|
|||||||
virtual int GetLastError() const { return {}; };
|
virtual int GetLastError() const { return {}; };
|
||||||
|
|
||||||
virtual wxSize GetVideoSize() const { return {}; };
|
virtual wxSize GetVideoSize() const { return {}; };
|
||||||
|
|
||||||
virtual void StartSession(std::unique_ptr<ICameraSignalingChannel> channel)
|
|
||||||
{
|
|
||||||
(void) channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void StopSession() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
|||||||
+188
-185
@@ -1,4 +1,6 @@
|
|||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
|
#include "WebMediaController.hpp"
|
||||||
|
#include "IPrinterAgent.hpp"
|
||||||
#include "Widgets/Button.hpp"
|
#include "Widgets/Button.hpp"
|
||||||
#include "Widgets/CheckBox.hpp"
|
#include "Widgets/CheckBox.hpp"
|
||||||
#include "Widgets/Label.hpp"
|
#include "Widgets/Label.hpp"
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
#include <boost/nowide/fstream.hpp>
|
#include <boost/nowide/fstream.hpp>
|
||||||
#include <boost/nowide/utf8_codecvt.hpp>
|
#include <boost/nowide/utf8_codecvt.hpp>
|
||||||
#include <slic3r/GUI/DeviceManager.hpp>
|
#include <slic3r/GUI/DeviceManager.hpp>
|
||||||
|
#include <wx/mediactrl.h>
|
||||||
#undef pid_t
|
#undef pid_t
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
@@ -52,6 +55,7 @@ namespace GUI {
|
|||||||
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
||||||
: wxPanel(parent, wxID_ANY, pos, size)
|
: wxPanel(parent, wxID_ANY, pos, size)
|
||||||
, m_media_ctrl(media_ctrl)
|
, m_media_ctrl(media_ctrl)
|
||||||
|
, m_active_media_controller(media_ctrl)
|
||||||
{
|
{
|
||||||
SetLabel("MediaPlayCtrl");
|
SetLabel("MediaPlayCtrl");
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
@@ -98,7 +102,10 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
|
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(); });
|
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
||||||
|
if (m_active_media_controller)
|
||||||
|
m_active_media_controller->Play();
|
||||||
|
});
|
||||||
// Orca: live-view FAQ link binding removed (vendor URL)
|
// Orca: live-view FAQ link binding removed (vendor URL)
|
||||||
|
|
||||||
Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
||||||
@@ -143,14 +150,12 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
|
|||||||
|
|
||||||
MediaPlayCtrl::~MediaPlayCtrl()
|
MediaPlayCtrl::~MediaPlayCtrl()
|
||||||
{
|
{
|
||||||
m_webrtc_stopping = true;
|
|
||||||
if (m_webrtc_ctrl)
|
if (m_webrtc_ctrl)
|
||||||
m_webrtc_ctrl->StopSession();
|
m_webrtc_ctrl->Stop();
|
||||||
m_media_ctrl->EndExternalStream();
|
m_media_ctrl->EndExternalStream();
|
||||||
m_webrtc_stopping = false;
|
|
||||||
{
|
{
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<exit>");
|
m_tasks.push_back({"<exit>", nullptr});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
}
|
}
|
||||||
while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
|
while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
|
||||||
@@ -163,6 +168,33 @@ MediaPlayCtrl::~MediaPlayCtrl()
|
|||||||
void MediaPlayCtrl::SetWebMediaController(IMediaController *ctrl)
|
void MediaPlayCtrl::SetWebMediaController(IMediaController *ctrl)
|
||||||
{
|
{
|
||||||
m_web_ctrl = ctrl;
|
m_web_ctrl = ctrl;
|
||||||
|
set_active_media_controller(current_mode());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaPlayCtrl::set_active_media_controller(CameraStreamMode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case CameraStreamMode::http_snapshot:
|
||||||
|
if (auto *web_ctrl = dynamic_cast<WebMediaController *>(m_web_ctrl))
|
||||||
|
web_ctrl->set_mode(mode);
|
||||||
|
m_active_media_controller = m_web_ctrl;
|
||||||
|
break;
|
||||||
|
case CameraStreamMode::webrtc:
|
||||||
|
if (!m_webrtc_ctrl) {
|
||||||
|
m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
|
||||||
|
[this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
|
||||||
|
[this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
|
||||||
|
if (token.expired())
|
||||||
|
return;
|
||||||
|
CallAfter([this, status] { on_webrtc_status(status); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
m_active_media_controller = m_webrtc_ctrl.get();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_active_media_controller = m_media_ctrl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraStreamMode MediaPlayCtrl::current_mode() const
|
CameraStreamMode MediaPlayCtrl::current_mode() const
|
||||||
@@ -181,105 +213,96 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
|||||||
}
|
}
|
||||||
m_last_mode = mode;
|
m_last_mode = mode;
|
||||||
}
|
}
|
||||||
|
set_active_media_controller(mode);
|
||||||
|
|
||||||
switch (mode) {
|
const bool uses_local_camera_url = mode == CameraStreamMode::http || mode == CameraStreamMode::https ||
|
||||||
case CameraStreamMode::http:
|
mode == CameraStreamMode::http_snapshot || mode == CameraStreamMode::rtsp;
|
||||||
case CameraStreamMode::https:
|
const bool uses_webrtc = mode == CameraStreamMode::webrtc;
|
||||||
case CameraStreamMode::http_snapshot:
|
const std::string machine = obj ? obj->get_dev_id() : "";
|
||||||
case CameraStreamMode::rtsp: {
|
bool changed = false;
|
||||||
std::string machine = obj ? obj->get_dev_id() : "";
|
|
||||||
|
if (uses_local_camera_url) {
|
||||||
auto agent = wxGetApp().getAgent();
|
auto agent = wxGetApp().getAgent();
|
||||||
std::string url = agent ? agent->get_local_camera_stream_url() : "";
|
std::string url = agent ? agent->get_local_camera_stream_url() : "";
|
||||||
m_camera_exists = !url.empty();
|
m_camera_exists = !url.empty();
|
||||||
Enable(obj && m_camera_exists);
|
Enable(obj && m_camera_exists);
|
||||||
bool changed = machine != m_machine || url != m_agent_camera_url;
|
changed = machine != m_machine || url != m_agent_camera_url;
|
||||||
m_machine = machine;
|
|
||||||
m_agent_camera_url = url;
|
m_agent_camera_url = url;
|
||||||
m_url = from_u8(url);
|
m_url = from_u8(url);
|
||||||
if (!changed) {
|
} else if (uses_webrtc) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
// A genuine machine/URL switch: not a failure, so drop any pending
|
|
||||||
// failure back-off before (re)starting on the new target.
|
|
||||||
m_web_user_stopped = false;
|
|
||||||
m_failed_code = 0;
|
|
||||||
m_failed_retry = 0;
|
|
||||||
m_next_retry = wxDateTime();
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE)
|
|
||||||
Stop(" ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case CameraStreamMode::webrtc: {
|
|
||||||
std::string machine = obj ? obj->get_dev_id() : "";
|
|
||||||
m_camera_exists = obj != nullptr;
|
m_camera_exists = obj != nullptr;
|
||||||
Enable(obj != nullptr);
|
Enable(obj != nullptr);
|
||||||
const bool changed = machine != m_machine;
|
changed = machine != m_machine;
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed
|
||||||
<< " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped;
|
<< " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped;
|
||||||
m_machine = machine;
|
|
||||||
m_url.clear();
|
m_url.clear();
|
||||||
m_agent_camera_url.clear();
|
m_agent_camera_url.clear();
|
||||||
if (!changed) {
|
} else {
|
||||||
|
if (obj) {
|
||||||
|
m_camera_exists = obj->has_ipcam;
|
||||||
|
m_dev_ver = obj->get_ota_version();
|
||||||
|
m_lan_mode = obj->is_lan_mode_printer();
|
||||||
|
m_lan_proto = obj->liveview_local;
|
||||||
|
m_remote_proto = obj->get_liveview_remote();
|
||||||
|
m_lan_ip = obj->get_dev_ip();
|
||||||
|
m_lan_passwd = obj->get_access_code();
|
||||||
|
m_device_busy = obj->is_camera_busy_off();
|
||||||
|
m_tutk_state = obj->tutk_state;
|
||||||
|
|
||||||
|
if (DevPrinterConfigUtil::get_printer_series_str(obj->printer_type) == "series_o" && BBLNetworkPlugin::instance().use_legacy_network()) {
|
||||||
|
// Legacy plugin cannot support remote play for H2D, force using local mode
|
||||||
|
m_remote_proto = LiveviewRemote::LVR_None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_camera_exists = false;
|
||||||
|
m_lan_mode = false;
|
||||||
|
m_lan_proto = LiveviewLocal::LVL_None;
|
||||||
|
m_lan_ip.clear();
|
||||||
|
m_lan_passwd.clear();
|
||||||
|
m_dev_ver.clear();
|
||||||
|
m_tutk_state.clear();
|
||||||
|
m_remote_proto = 0;
|
||||||
|
m_device_busy = false;
|
||||||
|
}
|
||||||
|
Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
|
||||||
|
if (machine == m_machine)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_machine = machine;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
|
||||||
|
m_disable_lan = false;
|
||||||
|
m_failed_retry = 0;
|
||||||
|
m_last_failed_codes.clear();
|
||||||
|
m_last_user_play = wxDateTime::Now();
|
||||||
|
std::string stream_url;
|
||||||
|
if (get_stream_url(&stream_url)) {
|
||||||
|
m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
|
||||||
|
} else {
|
||||||
|
m_streaming = false;
|
||||||
}
|
}
|
||||||
m_web_user_stopped = false;
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE)
|
if (m_last_state != MEDIASTATE_IDLE)
|
||||||
Stop(" ");
|
Stop(" ");
|
||||||
|
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
|
||||||
|
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
|
||||||
|
else
|
||||||
|
SetStatus("", false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string machine = obj ? obj->get_dev_id() : "";
|
|
||||||
if (obj) {
|
|
||||||
m_camera_exists = obj->has_ipcam;
|
|
||||||
m_dev_ver = obj->get_ota_version();
|
|
||||||
m_lan_mode = obj->is_lan_mode_printer();
|
|
||||||
m_lan_proto = obj->liveview_local;
|
|
||||||
m_remote_proto = obj->get_liveview_remote();
|
|
||||||
m_lan_ip = obj->get_dev_ip();
|
|
||||||
m_lan_passwd = obj->get_access_code();
|
|
||||||
m_device_busy = obj->is_camera_busy_off();
|
|
||||||
m_tutk_state = obj->tutk_state;
|
|
||||||
|
|
||||||
if (DevPrinterConfigUtil::get_printer_series_str(obj->printer_type) == "series_o" && BBLNetworkPlugin::instance().use_legacy_network()) {
|
|
||||||
// Legacy plugin cannot support remote play for H2D, force using local mode
|
|
||||||
m_remote_proto = LiveviewRemote::LVR_None;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_camera_exists = false;
|
|
||||||
m_lan_mode = false;
|
|
||||||
m_lan_proto = LiveviewLocal::LVL_None;
|
|
||||||
m_lan_ip.clear();
|
|
||||||
m_lan_passwd.clear();
|
|
||||||
m_dev_ver.clear();
|
|
||||||
m_tutk_state.clear();
|
|
||||||
m_remote_proto = 0;
|
|
||||||
m_device_busy = false;
|
|
||||||
}
|
|
||||||
Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
|
|
||||||
if (machine == m_machine) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_machine = machine;
|
m_machine = machine;
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
|
if (!changed)
|
||||||
m_disable_lan = false;
|
return;
|
||||||
m_failed_retry = 0;
|
|
||||||
m_last_failed_codes.clear();
|
// A genuine target switch is not a stream failure and should clear the
|
||||||
m_last_user_play = wxDateTime::Now();
|
// manual-stop state before the new target is allowed to play.
|
||||||
std::string stream_url;
|
m_web_user_stopped = false;
|
||||||
if (get_stream_url(&stream_url)) {
|
if (uses_local_camera_url) {
|
||||||
m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
|
m_failed_code = 0;
|
||||||
} else {
|
m_failed_retry = 0;
|
||||||
m_streaming = false;
|
m_next_retry = wxDateTime();
|
||||||
}
|
}
|
||||||
if (m_last_state != MEDIASTATE_IDLE)
|
if (m_last_state != MEDIASTATE_IDLE)
|
||||||
Stop(" ");
|
Stop(" ");
|
||||||
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
|
|
||||||
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
|
|
||||||
else
|
|
||||||
SetStatus("", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1)
|
wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1)
|
||||||
@@ -330,97 +353,71 @@ void refresh_agora_url(char const* device, char const* dev_ver, char const* chan
|
|||||||
|
|
||||||
void MediaPlayCtrl::Play()
|
void MediaPlayCtrl::Play()
|
||||||
{
|
{
|
||||||
switch (current_mode()) {
|
if ((m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry) || !IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
|
||||||
case CameraStreamMode::http_snapshot:
|
return;
|
||||||
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
|
|
||||||
|
const CameraStreamMode mode = current_mode();
|
||||||
|
set_active_media_controller(mode);
|
||||||
|
m_last_mode = mode;
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
|
||||||
|
auto printer_agent = agent ? agent->get_printer_agent() : nullptr;
|
||||||
|
const bool is_bbl = (printer_agent ? printer_agent->get_agent_info().id : "") == BBL_PRINTER_AGENT_ID;
|
||||||
|
|
||||||
|
if (!is_bbl) {
|
||||||
|
const bool is_webrtc = mode == CameraStreamMode::webrtc;
|
||||||
|
const bool is_snapshot = mode == CameraStreamMode::http_snapshot;
|
||||||
|
const bool is_http_stream = mode == CameraStreamMode::http || mode == CameraStreamMode::https || mode == CameraStreamMode::rtsp;
|
||||||
|
if (!is_webrtc && !is_snapshot && !is_http_stream)
|
||||||
return;
|
return;
|
||||||
if (!IsShownOnScreen()) return;
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE) return;
|
auto *webrtc_ctrl = is_webrtc ? dynamic_cast<WebRtcMediaController *>(m_active_media_controller) : nullptr;
|
||||||
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty() || !m_web_ctrl) {
|
if (is_webrtc && (!webrtc_ctrl || !m_media_ctrl)) {
|
||||||
Stop(_L("Please confirm if the printer is connected."));
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_button_play->SetIcon("media_stop");
|
if (webrtc_ctrl && webrtc_ctrl->is_active())
|
||||||
m_web_ctrl->Load(wxURI(m_url), current_mode());
|
|
||||||
m_web_ctrl->Play();
|
|
||||||
m_last_state = wxMEDIASTATE_PLAYING;
|
|
||||||
SetStatus(_L("Playing..."), false);
|
|
||||||
return;
|
|
||||||
case CameraStreamMode::http:
|
|
||||||
case CameraStreamMode::https:
|
|
||||||
case CameraStreamMode::rtsp:
|
|
||||||
if (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
|
|
||||||
return;
|
return;
|
||||||
if (!IsShownOnScreen()) return;
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE) return;
|
|
||||||
m_failed_code = 0;
|
m_failed_code = 0;
|
||||||
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty()) {
|
if (!m_active_media_controller || m_machine.empty() || !IsEnabled() || !m_camera_exists ||
|
||||||
|
(!is_webrtc && m_url.IsEmpty())) {
|
||||||
Stop(_L("Please confirm if the printer is connected."));
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_button_play->SetIcon("media_stop");
|
|
||||||
load();
|
if (is_webrtc) {
|
||||||
return;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state << " failed_retry=" << m_failed_retry
|
||||||
case CameraStreamMode::webrtc: {
|
<< " shown=" << IsShownOnScreen();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state
|
auto channel = agent ? agent->create_camera_signaling_channel(m_machine) : nullptr;
|
||||||
<< " next_retry_valid=" << m_next_retry.IsValid()
|
if (!channel) {
|
||||||
<< " next_retry_future=" << (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
|
Stop(_L("Sign in to OrcaCloud to view the camera."));
|
||||||
<< " failed_retry=" << m_failed_retry << " shown=" << IsShownOnScreen();
|
return;
|
||||||
if (m_webrtc_ctrl && m_webrtc_ctrl->is_active()) {
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: session already active, ignoring";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
|
|
||||||
return;
|
|
||||||
if (!IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
|
|
||||||
return;
|
|
||||||
m_failed_code = 0;
|
|
||||||
if (m_machine.empty() || !IsEnabled() || !m_camera_exists) {
|
|
||||||
Stop(_L("Please confirm if the printer is connected."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto agent = wxGetApp().getAgent();
|
|
||||||
auto channel = agent ? agent->create_camera_signaling_channel(m_machine) : nullptr;
|
|
||||||
if (!channel) {
|
|
||||||
Stop(_L("Sign in to OrcaCloud to view the camera."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!m_webrtc_ctrl) {
|
|
||||||
m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
|
|
||||||
[this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
|
|
||||||
[this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
|
|
||||||
if (token.expired())
|
|
||||||
return;
|
|
||||||
CallAfter([this, status] { on_webrtc_status(status); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
m_button_play->SetIcon("media_stop");
|
|
||||||
m_media_ctrl->BeginExternalStream();
|
|
||||||
m_last_state = MEDIASTATE_INITIALIZING;
|
|
||||||
SetStatus(_L("Initializing..."), false);
|
|
||||||
m_webrtc_stopping = false;
|
|
||||||
m_webrtc_ctrl->StartSession(std::move(channel));
|
|
||||||
m_webrtc_epoch = m_webrtc_ctrl->epoch();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default: // assumed to be CameraStreamMode::none
|
|
||||||
if (NetworkAgent* agent = wxGetApp().getAgent()) {
|
|
||||||
if (auto printer_agent = agent->get_printer_agent()) {
|
|
||||||
if (printer_agent->get_agent_info().id != BBL_PRINTER_AGENT_ID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
webrtc_ctrl->set_signalling_channel(std::move(channel));
|
||||||
|
m_media_ctrl->BeginExternalStream();
|
||||||
|
m_last_state = MEDIASTATE_INITIALIZING;
|
||||||
|
SetStatus(_L("Initializing..."), false);
|
||||||
|
} else if (is_snapshot) {
|
||||||
|
m_last_state = wxMEDIASTATE_PLAYING;
|
||||||
|
SetStatus(_L("Playing..."), false);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
m_button_play->SetIcon("media_stop");
|
||||||
|
if (m_active_media_controller == m_media_ctrl) {
|
||||||
|
// wxMediaCtrl3 reports when it has a decoded frame; load() waits for
|
||||||
|
// that event before queuing Play so the stream is not marked stopped.
|
||||||
|
load();
|
||||||
|
} else {
|
||||||
|
m_active_media_controller->Load(wxURI(m_url));
|
||||||
|
m_active_media_controller->Play();
|
||||||
|
}
|
||||||
|
if (webrtc_ctrl) {
|
||||||
|
m_webrtc_epoch = webrtc_ctrl->epoch();
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
|
|
||||||
return;
|
|
||||||
if (!IsShownOnScreen())
|
|
||||||
return;
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_failed_code = 0;
|
m_failed_code = 0;
|
||||||
if (m_machine.empty()) {
|
if (m_machine.empty()) {
|
||||||
Stop(_L("Please confirm if the printer is connected."));
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
@@ -441,7 +438,6 @@ void MediaPlayCtrl::Play()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
|
||||||
NetworkAgent *agent = wxGetApp().getAgent();
|
|
||||||
std::string agent_version = agent ? agent->get_version() : "";
|
std::string agent_version = agent ? agent->get_version() : "";
|
||||||
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||||
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
|
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
|
||||||
@@ -545,8 +541,8 @@ void MediaPlayCtrl::StopWebStream()
|
|||||||
{
|
{
|
||||||
if (m_last_state == MEDIASTATE_IDLE)
|
if (m_last_state == MEDIASTATE_IDLE)
|
||||||
return;
|
return;
|
||||||
if (m_web_ctrl)
|
if (m_active_media_controller && m_active_media_controller == m_web_ctrl)
|
||||||
m_web_ctrl->Stop();
|
m_active_media_controller->Stop();
|
||||||
m_button_play->SetIcon("media_play");
|
m_button_play->SetIcon("media_play");
|
||||||
m_last_state = MEDIASTATE_IDLE;
|
m_last_state = MEDIASTATE_IDLE;
|
||||||
SetStatus(_L("Video Stopped."), false);
|
SetStatus(_L("Video Stopped."), false);
|
||||||
@@ -554,15 +550,14 @@ void MediaPlayCtrl::StopWebStream()
|
|||||||
|
|
||||||
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
||||||
{
|
{
|
||||||
const bool webrtc_active = m_webrtc_ctrl && m_last_mode == CameraStreamMode::webrtc;
|
const bool webrtc_active = m_last_mode == CameraStreamMode::webrtc &&
|
||||||
|
dynamic_cast<WebRtcMediaController *>(m_active_media_controller) != nullptr;
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state
|
||||||
<< " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code
|
<< " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code
|
||||||
<< " msg='" << msg.ToUTF8().data() << "'";
|
<< " msg='" << msg.ToUTF8().data() << "'";
|
||||||
if (webrtc_active) {
|
if (webrtc_active) {
|
||||||
m_webrtc_stopping = true;
|
m_active_media_controller->Stop();
|
||||||
m_webrtc_ctrl->StopSession();
|
|
||||||
m_media_ctrl->EndExternalStream();
|
m_media_ctrl->EndExternalStream();
|
||||||
m_webrtc_stopping = false;
|
|
||||||
}
|
}
|
||||||
switch (m_last_mode) {
|
switch (m_last_mode) {
|
||||||
case CameraStreamMode::http:
|
case CameraStreamMode::http:
|
||||||
@@ -571,13 +566,14 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
|||||||
const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot;
|
const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot;
|
||||||
if (m_last_state != MEDIASTATE_IDLE) {
|
if (m_last_state != MEDIASTATE_IDLE) {
|
||||||
if (snapshot) {
|
if (snapshot) {
|
||||||
if (m_web_ctrl) m_web_ctrl->Stop();
|
if (m_active_media_controller)
|
||||||
|
m_active_media_controller->Stop();
|
||||||
} else {
|
} else {
|
||||||
// http/https mode plays through the ffmpeg backend (m_media_ctrl), not
|
// http/https mode plays through the ffmpeg backend (m_media_ctrl), not
|
||||||
// the webview - tear its read thread down too, otherwise it keeps
|
// the webview - tear its read thread down too, otherwise it keeps
|
||||||
// pulling and painting frames after the UI says "Video Stopped".
|
// pulling and painting frames after the UI says "Video Stopped".
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<stop>");
|
m_tasks.push_back({"<stop>", m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
}
|
}
|
||||||
m_button_play->SetIcon("media_play");
|
m_button_play->SetIcon("media_play");
|
||||||
@@ -611,7 +607,8 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
|||||||
m_media_ctrl->InvalidateBestSize();
|
m_media_ctrl->InvalidateBestSize();
|
||||||
m_button_play->SetIcon("media_play");
|
m_button_play->SetIcon("media_play");
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<stop>");
|
if (!webrtc_active)
|
||||||
|
m_tasks.push_back({"<stop>", m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
if (!msg.IsEmpty())
|
if (!msg.IsEmpty())
|
||||||
SetStatus(msg);
|
SetStatus(msg);
|
||||||
@@ -678,7 +675,7 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
|||||||
|
|
||||||
void MediaPlayCtrl::on_webrtc_status(WebRtcMediaController::Status status)
|
void MediaPlayCtrl::on_webrtc_status(WebRtcMediaController::Status status)
|
||||||
{
|
{
|
||||||
// Drop CallAfter-queued events from a superseded StartSession attempt.
|
// Drop CallAfter-queued events from a superseded Play attempt.
|
||||||
if (status.epoch != m_webrtc_epoch)
|
if (status.epoch != m_webrtc_epoch)
|
||||||
return;
|
return;
|
||||||
if (status.kind == WebRtcMediaController::Status::Connecting) {
|
if (status.kind == WebRtcMediaController::Status::Connecting) {
|
||||||
@@ -839,7 +836,9 @@ void MediaPlayCtrl::jump_to_play()
|
|||||||
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
||||||
{
|
{
|
||||||
auto last_state = m_last_state;
|
auto last_state = m_last_state;
|
||||||
auto state = m_media_ctrl->GetState();
|
if (m_active_media_controller != m_media_ctrl)
|
||||||
|
return;
|
||||||
|
auto state = m_active_media_controller->GetState();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
|
||||||
if ((int) state < 0) return;
|
if ((int) state < 0) return;
|
||||||
{
|
{
|
||||||
@@ -851,14 +850,14 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
|||||||
}
|
}
|
||||||
if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
|
if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
|
||||||
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
|
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
|
||||||
m_failed_code = m_media_ctrl->GetLastError();
|
m_failed_code = m_active_media_controller->GetLastError();
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
|
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
|
||||||
wxSize size = m_media_ctrl->GetVideoSize();
|
wxSize size = m_active_media_controller->GetVideoSize();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
||||||
m_failed_code = m_media_ctrl->GetLastError();
|
m_failed_code = m_active_media_controller->GetLastError();
|
||||||
if (size.GetWidth() >= 320) {
|
if (size.GetWidth() >= 320) {
|
||||||
m_last_state = state;
|
m_last_state = state;
|
||||||
m_failed_code = 0;
|
m_failed_code = 0;
|
||||||
@@ -868,7 +867,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
|||||||
m_failed_retry = 0;
|
m_failed_retry = 0;
|
||||||
m_disable_lan = false;
|
m_disable_lan = false;
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<play>");
|
m_tasks.push_back({"<play>", m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
} else if (event.GetId()) {
|
} else if (event.GetId()) {
|
||||||
if (m_failed_code == 0)
|
if (m_failed_code == 0)
|
||||||
@@ -923,7 +922,7 @@ void MediaPlayCtrl::load()
|
|||||||
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
|
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
|
||||||
}
|
}
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back(m_url);
|
m_tasks.push_back({m_url, m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,30 +942,34 @@ void MediaPlayCtrl::media_proc()
|
|||||||
while (m_tasks.empty()) {
|
while (m_tasks.empty()) {
|
||||||
m_cond.wait(lock);
|
m_cond.wait(lock);
|
||||||
}
|
}
|
||||||
wxString url = m_tasks.front();
|
MediaTask task = m_tasks.front();
|
||||||
if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "<stop>") {
|
if (m_tasks.size() >= 2 && !task.command.IsEmpty() && task.command[0] != '<' &&
|
||||||
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << url;
|
m_tasks[1].command == "<stop>" && task.controller == m_tasks[1].controller) {
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << task.command;
|
||||||
m_tasks.pop_front();
|
m_tasks.pop_front();
|
||||||
m_tasks.pop_front();
|
m_tasks.pop_front();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (url == "<stop>") {
|
if (task.command == "<stop>") {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
|
||||||
m_media_ctrl->Stop();
|
if (task.controller)
|
||||||
|
task.controller->Stop();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
|
||||||
}
|
}
|
||||||
else if (url == "<exit>") {
|
else if (task.command == "<exit>") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (url == "<play>") {
|
else if (task.command == "<play>") {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
|
||||||
m_media_ctrl->Play();
|
if (task.controller)
|
||||||
|
task.controller->Play();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
||||||
m_media_ctrl->Load(wxURI(url));
|
if (task.controller)
|
||||||
|
task.controller->Load(wxURI(task.command));
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
|
||||||
}
|
}
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ private:
|
|||||||
static bool get_stream_url(std::string *url = nullptr);
|
static bool get_stream_url(std::string *url = nullptr);
|
||||||
|
|
||||||
CameraStreamMode current_mode() const;
|
CameraStreamMode current_mode() const;
|
||||||
|
void set_active_media_controller(CameraStreamMode mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
|
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
|
||||||
@@ -86,10 +87,10 @@ private:
|
|||||||
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
||||||
|
|
||||||
wxMediaCtrl3 * m_media_ctrl;
|
wxMediaCtrl3 * m_media_ctrl;
|
||||||
|
IMediaController * m_active_media_controller = nullptr;
|
||||||
IMediaController * m_web_ctrl = nullptr;
|
IMediaController * m_web_ctrl = nullptr;
|
||||||
std::unique_ptr<WebRtcMediaController> m_webrtc_ctrl;
|
std::unique_ptr<WebRtcMediaController> m_webrtc_ctrl;
|
||||||
CameraStreamMode m_last_mode = CameraStreamMode::none;
|
CameraStreamMode m_last_mode = CameraStreamMode::none;
|
||||||
bool m_webrtc_stopping = false;
|
|
||||||
std::uint64_t m_webrtc_epoch = 0;
|
std::uint64_t m_webrtc_epoch = 0;
|
||||||
std::string m_agent_camera_url;
|
std::string m_agent_camera_url;
|
||||||
bool m_web_user_stopped = false;
|
bool m_web_user_stopped = false;
|
||||||
@@ -108,7 +109,11 @@ private:
|
|||||||
bool m_disable_lan = false;
|
bool m_disable_lan = false;
|
||||||
wxString m_url;
|
wxString m_url;
|
||||||
|
|
||||||
std::deque<wxString> m_tasks;
|
struct MediaTask {
|
||||||
|
wxString command;
|
||||||
|
IMediaController *controller = nullptr;
|
||||||
|
};
|
||||||
|
std::deque<MediaTask> m_tasks;
|
||||||
boost::mutex m_mutex;
|
boost::mutex m_mutex;
|
||||||
boost::condition_variable m_cond;
|
boost::condition_variable m_cond;
|
||||||
boost::thread m_thread;
|
boost::thread m_thread;
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ WebMediaController::WebMediaController(wxWebView* webview) : m_webview(webview)
|
|||||||
m_webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", "");
|
m_webview->SetPage("<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMediaController::Load(wxURI url) { Load(url, CameraStreamMode::http); }
|
void WebMediaController::Load(wxURI url)
|
||||||
|
{
|
||||||
|
m_url = url.BuildURI().ToStdString();
|
||||||
|
}
|
||||||
|
|
||||||
void WebMediaController::Load(wxURI url, CameraStreamMode mode)
|
void WebMediaController::set_mode(CameraStreamMode mode)
|
||||||
{
|
{
|
||||||
m_url = url.BuildURI().ToStdString();
|
|
||||||
m_stream_mode = mode;
|
m_stream_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <slic3r/GUI/IMediaController.hpp>
|
#include <slic3r/GUI/IMediaController.hpp>
|
||||||
|
#include <slic3r/Utils/IPrinterAgent.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ public:
|
|||||||
|
|
||||||
void Load(wxURI url) override;
|
void Load(wxURI url) override;
|
||||||
|
|
||||||
void Load(wxURI url, CameraStreamMode mode) override;
|
void set_mode(CameraStreamMode mode);
|
||||||
|
|
||||||
void Play() override;
|
void Play() override;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ WebRtcMediaController::WebRtcMediaController(std::function<void(const wxImage&,
|
|||||||
|
|
||||||
WebRtcMediaController::~WebRtcMediaController()
|
WebRtcMediaController::~WebRtcMediaController()
|
||||||
{
|
{
|
||||||
StopSession();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcMediaController::report(Status status)
|
void WebRtcMediaController::report(Status status)
|
||||||
@@ -52,8 +52,14 @@ void WebRtcMediaController::report(Status status)
|
|||||||
m_on_status(status);
|
m_on_status(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcMediaController::StartSession(std::unique_ptr<ICameraSignalingChannel> channel)
|
void WebRtcMediaController::set_signalling_channel(std::unique_ptr<ICameraSignalingChannel> channel)
|
||||||
{
|
{
|
||||||
|
m_pending_signaling = std::move(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRtcMediaController::Play()
|
||||||
|
{
|
||||||
|
std::unique_ptr<ICameraSignalingChannel> channel = std::move(m_pending_signaling);
|
||||||
// Tear down any previous attempt WITHOUT notifying: the Stopped that would
|
// Tear down any previous attempt WITHOUT notifying: the Stopped that would
|
||||||
// otherwise be delivered (async, via CallAfter) races the new attempt's
|
// otherwise be delivered (async, via CallAfter) races the new attempt's
|
||||||
// Connecting and makes the consumer cancel a session that is mid-connect.
|
// Connecting and makes the consumer cancel a session that is mid-connect.
|
||||||
@@ -101,7 +107,7 @@ void WebRtcMediaController::StartSession(std::unique_ptr<ICameraSignalingChannel
|
|||||||
signaling->open();
|
signaling->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcMediaController::StopSession()
|
void WebRtcMediaController::Stop()
|
||||||
{
|
{
|
||||||
teardown(true);
|
teardown(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IMediaController.hpp"
|
#include "IMediaController.hpp"
|
||||||
|
#include <slic3r/Utils/IPrinterAgent.hpp>
|
||||||
|
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ public:
|
|||||||
DECODE_ERROR,
|
DECODE_ERROR,
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
} code = ICE_FAILED;
|
} code = ICE_FAILED;
|
||||||
// Identifies the StartSession attempt this status belongs to, so the
|
// Identifies the Play attempt this status belongs to, so the
|
||||||
// consumer can drop CallAfter-queued events from a superseded attempt.
|
// consumer can drop CallAfter-queued events from a superseded attempt.
|
||||||
std::uint64_t epoch = 0;
|
std::uint64_t epoch = 0;
|
||||||
};
|
};
|
||||||
@@ -45,14 +46,13 @@ public:
|
|||||||
std::function<void(Status)> on_status);
|
std::function<void(Status)> on_status);
|
||||||
~WebRtcMediaController() override;
|
~WebRtcMediaController() override;
|
||||||
|
|
||||||
void StartSession(std::unique_ptr<ICameraSignalingChannel> channel) override;
|
void set_signalling_channel(std::unique_ptr<ICameraSignalingChannel> channel);
|
||||||
void StopSession() override;
|
|
||||||
std::uint64_t epoch() const { return m_epoch.load(); }
|
std::uint64_t epoch() const { return m_epoch.load(); }
|
||||||
bool is_active() const { return m_alive.load(); }
|
bool is_active() const { return m_alive.load(); }
|
||||||
|
|
||||||
void Load(wxURI) override {}
|
void Load(wxURI) override {}
|
||||||
void Play() override {}
|
void Play() override;
|
||||||
void Stop() override { StopSession(); }
|
void Stop() override;
|
||||||
wxMediaState GetState() override;
|
wxMediaState GetState() override;
|
||||||
wxSize GetVideoSize() const override;
|
wxSize GetVideoSize() const override;
|
||||||
|
|
||||||
@@ -75,6 +75,7 @@ private:
|
|||||||
// addRemoteCandidate until a remote description is set, so buffer them.
|
// addRemoteCandidate until a remote description is set, so buffer them.
|
||||||
std::vector<std::pair<std::string, std::string>> m_pending_candidates;
|
std::vector<std::pair<std::string, std::string>> m_pending_candidates;
|
||||||
bool m_remote_description_set = false;
|
bool m_remote_description_set = false;
|
||||||
|
std::unique_ptr<ICameraSignalingChannel> m_pending_signaling;
|
||||||
std::unique_ptr<ICameraSignalingChannel> m_signaling;
|
std::unique_ptr<ICameraSignalingChannel> m_signaling;
|
||||||
std::shared_ptr<rtc::PeerConnection> m_peer_connection;
|
std::shared_ptr<rtc::PeerConnection> m_peer_connection;
|
||||||
std::shared_ptr<rtc::DataChannel> m_data_channel;
|
std::shared_ptr<rtc::DataChannel> m_data_channel;
|
||||||
|
|||||||
@@ -163,13 +163,13 @@ wxMediaState wxMediaCtrl3::GetState()
|
|||||||
return m_state;
|
return m_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxMediaCtrl3::GetLastError()
|
int wxMediaCtrl3::GetLastError() const
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mutex);
|
std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
return m_error;
|
return m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize wxMediaCtrl3::GetVideoSize()
|
wxSize wxMediaCtrl3::GetVideoSize() const
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mutex);
|
std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
return m_video_size;
|
return m_video_size;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "wx/bitmap.h"
|
#include "wx/bitmap.h"
|
||||||
#include "wx/uri.h"
|
#include "wx/uri.h"
|
||||||
#include "wx/mediactrl.h"
|
#include "wx/mediactrl.h"
|
||||||
|
#include "IMediaController.hpp"
|
||||||
|
|
||||||
wxDECLARE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
wxDECLARE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
||||||
|
|
||||||
@@ -27,18 +28,18 @@ void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, in
|
|||||||
|
|
||||||
class AVVideoDecoder;
|
class AVVideoDecoder;
|
||||||
|
|
||||||
class wxMediaCtrl3 : public wxWindow, BambuLib
|
class wxMediaCtrl3 : public wxWindow, public Slic3r::GUI::IMediaController, BambuLib
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxMediaCtrl3(wxWindow *parent);
|
wxMediaCtrl3(wxWindow *parent);
|
||||||
|
|
||||||
~wxMediaCtrl3();
|
~wxMediaCtrl3() override;
|
||||||
|
|
||||||
void Load(wxURI url);
|
void Load(wxURI url) override;
|
||||||
|
|
||||||
void Play();
|
void Play() override;
|
||||||
|
|
||||||
void Stop();
|
void Stop() override;
|
||||||
|
|
||||||
// Render frames supplied by a controller which owns its own transport.
|
// Render frames supplied by a controller which owns its own transport.
|
||||||
// The frame is copied while m_mutex is held; callers may release it after
|
// The frame is copied while m_mutex is held; callers may release it after
|
||||||
@@ -52,11 +53,11 @@ public:
|
|||||||
|
|
||||||
void SetIdleImage(wxString const & image);
|
void SetIdleImage(wxString const & image);
|
||||||
|
|
||||||
wxMediaState GetState();
|
wxMediaState GetState() override;
|
||||||
|
|
||||||
int GetLastError();
|
int GetLastError() const override;
|
||||||
|
|
||||||
wxSize GetVideoSize();
|
wxSize GetVideoSize() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
@@ -93,7 +94,7 @@ private:
|
|||||||
std::uint64_t m_last_PTS{0};
|
std::uint64_t m_last_PTS{0};
|
||||||
std::chrono::system_clock::time_point m_last_PTS_expected;
|
std::chrono::system_clock::time_point m_last_PTS_expected;
|
||||||
std::chrono::system_clock::time_point m_last_PTS_practical;
|
std::chrono::system_clock::time_point m_last_PTS_practical;
|
||||||
std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
std::condition_variable m_cond;
|
std::condition_variable m_cond;
|
||||||
std::thread m_thread;
|
std::thread m_thread;
|
||||||
std::atomic_bool m_refresh_pending{false};
|
std::atomic_bool m_refresh_pending{false};
|
||||||
|
|||||||
Reference in New Issue
Block a user