mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-29 06:08:48 +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 {
|
Button {
|
||||||
text: qsTr("Cancel")
|
text: qsTr("Cancel")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
|
|
@ -24,6 +24,13 @@
|
||||||
#include <xcb/xcb_ewmh.h>
|
#include <xcb/xcb_ewmh.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GSTREAMER_AVAILABLE
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "gst/gst.h"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::vector<mtx::events::msg::CallCandidates::Candidate>)
|
Q_DECLARE_METATYPE(std::vector<mtx::events::msg::CallCandidates::Candidate>)
|
||||||
Q_DECLARE_METATYPE(mtx::events::msg::CallCandidates::Candidate)
|
Q_DECLARE_METATYPE(mtx::events::msg::CallCandidates::Candidate)
|
||||||
Q_DECLARE_METATYPE(mtx::responses::TurnServer)
|
Q_DECLARE_METATYPE(mtx::responses::TurnServer)
|
||||||
|
@ -235,8 +242,8 @@ void
|
||||||
CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
|
CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
|
||||||
{
|
{
|
||||||
#ifdef GSTREAMER_AVAILABLE
|
#ifdef GSTREAMER_AVAILABLE
|
||||||
if (handleEvent_<CallInvite>(event) || handleEvent_<CallCandidates>(event) ||
|
if (handleEvent<CallInvite>(event) || handleEvent<CallCandidates>(event) ||
|
||||||
handleEvent_<CallAnswer>(event) || handleEvent_<CallHangUp>(event))
|
handleEvent<CallAnswer>(event) || handleEvent<CallHangUp>(event))
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
(void)event;
|
(void)event;
|
||||||
|
@ -245,7 +252,7 @@ CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool
|
bool
|
||||||
CallManager::handleEvent_(const mtx::events::collections::TimelineEvents &event)
|
CallManager::handleEvent(const mtx::events::collections::TimelineEvents &event)
|
||||||
{
|
{
|
||||||
if (std::holds_alternative<RoomEvent<T>>(event)) {
|
if (std::holds_alternative<RoomEvent<T>>(event)) {
|
||||||
handleEvent(std::get<RoomEvent<T>>(event));
|
handleEvent(std::get<RoomEvent<T>>(event));
|
||||||
|
@ -565,6 +572,87 @@ CallManager::windowList()
|
||||||
return ret;
|
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 {
|
namespace {
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
getTurnURIs(const mtx::responses::TurnServer &turnServer)
|
getTurnURIs(const mtx::responses::TurnServer &turnServer)
|
||||||
|
|
|
@ -63,6 +63,7 @@ public slots:
|
||||||
void hangUp(
|
void hangUp(
|
||||||
mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
|
mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
|
||||||
QStringList windowList();
|
QStringList windowList();
|
||||||
|
void previewWindow(unsigned int windowIndex) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
|
void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
|
||||||
|
@ -95,7 +96,7 @@ private:
|
||||||
std::vector<std::pair<QString, uint32_t>> windows_;
|
std::vector<std::pair<QString, uint32_t>> windows_;
|
||||||
|
|
||||||
template<typename T>
|
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::CallInvite> &);
|
||||||
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &);
|
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &);
|
||||||
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &);
|
void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &);
|
||||||
|
|
Loading…
Reference in a new issue