mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Add screen sharing window preview
This commit is contained in:
parent
efe240d609
commit
402bd565cb
3 changed files with 100 additions and 4 deletions
|
@ -127,6 +127,13 @@ Popup {
|
|||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Preview")
|
||||
onClicked: {
|
||||
CallManager.previewWindow(windowCombo.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
#include <xcb/xcb_ewmh.h>
|
||||
#endif
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
extern "C"
|
||||
{
|
||||
#include "gst/gst.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE(std::vector<mtx::events::msg::CallCandidates::Candidate>)
|
||||
Q_DECLARE_METATYPE(mtx::events::msg::CallCandidates::Candidate)
|
||||
Q_DECLARE_METATYPE(mtx::responses::TurnServer)
|
||||
|
@ -235,8 +242,8 @@ void
|
|||
CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
|
||||
{
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
if (handleEvent_<CallInvite>(event) || handleEvent_<CallCandidates>(event) ||
|
||||
handleEvent_<CallAnswer>(event) || handleEvent_<CallHangUp>(event))
|
||||
if (handleEvent<CallInvite>(event) || handleEvent<CallCandidates>(event) ||
|
||||
handleEvent<CallAnswer>(event) || handleEvent<CallHangUp>(event))
|
||||
return;
|
||||
#else
|
||||
(void)event;
|
||||
|
@ -245,7 +252,7 @@ CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
|
|||
|
||||
template<typename T>
|
||||
bool
|
||||
CallManager::handleEvent_(const mtx::events::collections::TimelineEvents &event)
|
||||
CallManager::handleEvent(const mtx::events::collections::TimelineEvents &event)
|
||||
{
|
||||
if (std::holds_alternative<RoomEvent<T>>(event)) {
|
||||
handleEvent(std::get<RoomEvent<T>>(event));
|
||||
|
@ -565,6 +572,87 @@ CallManager::windowList()
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
namespace {
|
||||
|
||||
GstElement *pipe_ = nullptr;
|
||||
unsigned int busWatchId_ = 0;
|
||||
|
||||
gboolean
|
||||
newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer G_GNUC_UNUSED)
|
||||
{
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
if (pipe_) {
|
||||
gst_element_set_state(GST_ELEMENT(pipe_), GST_STATE_NULL);
|
||||
gst_object_unref(pipe_);
|
||||
pipe_ = nullptr;
|
||||
}
|
||||
if (busWatchId_) {
|
||||
g_source_remove(busWatchId_);
|
||||
busWatchId_ = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CallManager::previewWindow(unsigned int index) const
|
||||
{
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
if (windows_.empty() || index >= windows_.size() || !gst_is_initialized())
|
||||
return;
|
||||
|
||||
GstElement *ximagesrc = gst_element_factory_make("ximagesrc", nullptr);
|
||||
if (!ximagesrc) {
|
||||
nhlog::ui()->error("Failed to create ximagesrc");
|
||||
return;
|
||||
}
|
||||
GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
|
||||
GstElement *videoscale = gst_element_factory_make("videoscale", nullptr);
|
||||
GstElement *capsfilter = gst_element_factory_make("capsfilter", nullptr);
|
||||
GstElement *ximagesink = gst_element_factory_make("ximagesink", nullptr);
|
||||
|
||||
g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
|
||||
g_object_set(ximagesrc, "show-pointer", FALSE, nullptr);
|
||||
g_object_set(ximagesrc, "xid", windows_[index].second, nullptr);
|
||||
|
||||
GstCaps *caps = gst_caps_new_simple(
|
||||
"video/x-raw", "width", G_TYPE_INT, 480, "height", G_TYPE_INT, 360, nullptr);
|
||||
g_object_set(capsfilter, "caps", caps, nullptr);
|
||||
gst_caps_unref(caps);
|
||||
|
||||
pipe_ = gst_pipeline_new(nullptr);
|
||||
gst_bin_add_many(
|
||||
GST_BIN(pipe_), ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr);
|
||||
if (!gst_element_link_many(
|
||||
ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr)) {
|
||||
nhlog::ui()->error("Failed to link preview window elements");
|
||||
gst_object_unref(pipe_);
|
||||
pipe_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (gst_element_set_state(pipe_, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
|
||||
nhlog::ui()->error("Unable to start preview pipeline");
|
||||
gst_object_unref(pipe_);
|
||||
pipe_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
|
||||
busWatchId_ = gst_bus_add_watch(bus, newBusMessage, nullptr);
|
||||
gst_object_unref(bus);
|
||||
#else
|
||||
(void)index;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<std::string>
|
||||
getTurnURIs(const mtx::responses::TurnServer &turnServer)
|
||||
|
|
|
@ -63,6 +63,7 @@ public slots:
|
|||
void hangUp(
|
||||
mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
|
||||
QStringList windowList();
|
||||
void previewWindow(unsigned int windowIndex) const;
|
||||
|
||||
signals:
|
||||
void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
|
||||
|
@ -95,7 +96,7 @@ private:
|
|||
std::vector<std::pair<QString, uint32_t>> windows_;
|
||||
|
||||
template<typename T>
|
||||
bool handleEvent_(const mtx::events::collections::TimelineEvents &event);
|
||||
bool handleEvent(const mtx::events::collections::TimelineEvents &event);
|
||||
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &);
|
||||
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &);
|
||||
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &);
|
||||
|
|
Loading…
Reference in a new issue