// SPDX-FileCopyrightText: 2021 Nheko Contributors
// SPDX-FileCopyrightText: 2022 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QQmlEngine>
#include <QQuickItem>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <optional>
#include <string_view>
#include <thread>
#include <utility>
#include "CallDevices.h"
#include "ChatPage.h"
#include "Logging.h"
#include "UserSettingsPage.h"
#include "WebRTCSession.h"
#ifdef GSTREAMER_AVAILABLE
extern "C"
{
#include "gst/gst.h"
#include "gst/sdp/sdp.h"
#define GST_USE_UNSTABLE_API
#include "gst/webrtc/webrtc.h"
}
#if !GST_CHECK_VERSION(1, 20, 0)
#define gst_element_request_pad_simple gst_element_get_request_pad
#endif
#endif
// https://github.com/vector-im/riot-web/issues/10173
#define STUN_SERVER "stun://turn.matrix.org:3478"
Q_DECLARE_METATYPE(webrtc::CallType)
Q_DECLARE_METATYPE(webrtc::State)
using webrtc::CallType;
using webrtc::State;
WebRTCSession::WebRTCSession()
: devices_(CallDevices::instance())
{
qRegisterMetaType<webrtc::CallType>();
qmlRegisterUncreatableMetaObject(webrtc::staticMetaObject,
"im.nheko",
1,
0,
"CallType",
QStringLiteral("Can't instantiate enum"));
qRegisterMetaType<webrtc::State>();
qmlRegisterUncreatableMetaObject(webrtc::staticMetaObject,
"im.nheko",
1,
0,
"WebRTCState",
QStringLiteral("Can't instantiate enum"));
connect(this, &WebRTCSession::stateChanged, this, &WebRTCSession::setState);
init();
}
bool
WebRTCSession::init(std::string *errorMessage)
{
#ifdef GSTREAMER_AVAILABLE
if (initialised_)
return true;
GError *error = nullptr;
if (!gst_init_check(nullptr, nullptr, &error)) {
std::string strError("WebRTC: failed to initialise GStreamer: ");
if (error) {
strError += error->message;
g_error_free(error);
}
nhlog::ui()->error(strError);
if (errorMessage)
*errorMessage = strError;
return false;
}
initialised_ = true;
gchar *version = gst_version_string();
nhlog::ui()->info("WebRTC: initialised {}", version);
g_free(version);
devices_.init();
return true;
#else
(void)errorMessage;
return false;
#endif
}
#ifdef GSTREAMER_AVAILABLE
namespace {
std::string localsdp_;
std::vector<mtx::events::msg::CallCandidates::Candidate> localcandidates_;
bool haveAudioStream_ = false;
bool haveVideoStream_ = false;
GstPad *localPiPSinkPad_ = nullptr;
GstPad