Files
tdesktop/Telegram/lib_webrtc/webrtc/webrtc_device_resolver.cpp
allhaileris afb81b8278
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
init
2026-02-16 15:50:16 +03:00

137 lines
3.4 KiB
C++

// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "webrtc/webrtc_device_resolver.h"
#include "webrtc/webrtc_environment.h"
namespace Webrtc {
namespace {
[[nodiscard]] bool IsDefault(const QString &id) {
return id.isEmpty() || id == kDefaultDeviceId;
}
} // namespace
DeviceResolver::DeviceResolver(
not_null<Environment*> environment,
DeviceType type,
rpl::producer<QString> savedId)
: _environment(environment)
, _current{ .type = type }
, _data(_current) {
_data.changes() | rpl::on_next([=](DeviceResolvedId id) {
QMutexLocker lock(&_mutex);
_current = id;
}, _lifetime);
std::move(
savedId
) | rpl::on_next([=](QString id) {
QMutexLocker lock(&_mutex);
_savedId = id;
lock.unlock();
trackSavedId();
}, _lifetime);
}
void DeviceResolver::trackSavedId() {
const auto now = _environment->defaultId(_current.type);
if (IsDefault(_savedId)) {
_data = rpl::single(
DeviceChange{ now, now }
) | rpl::then(
_environment->defaultChanges(_current.type)
) | rpl::map([=](const DeviceChange &change) {
_lastChangeReason = change.reason;
return DeviceResolvedId{ change.nowId, _current.type, true };
});
return;
}
_data = rpl::single(DevicesChange{
DeviceChange{ now, now },
_environment->devices(_current.type),
}) | rpl::then(
_environment->changes(_current.type)
) | rpl::map([=](const DevicesChange &change) {
const auto now = _data.current();
const auto i = ranges::find(
change.nowList,
_savedId,
&DeviceInfo::id);
if (i != end(change.nowList) && !i->inactive) {
auto result = DeviceResolvedId{ _savedId, now.type };
if (now != result) {
_lastChangeReason = DeviceChangeReason::Connected;
}
return result;
} else {
_lastChangeReason = (now == DeviceResolvedId{ _savedId })
? DeviceChangeReason::Disconnected
: change.defaultChange.reason;
const auto &defaultId = change.defaultChange.nowId;
return DeviceResolvedId{ defaultId, now.type, true };
}
});
}
DeviceResolvedId DeviceResolver::current() const {
if (IsDefault(_savedId)) {
_environment->validateDefaultId(_current.type);
} else {
_environment->validateDevices(_current.type);
}
return _data.current();
}
DeviceResolvedId DeviceResolver::threadSafeCurrent() const {
QMutexLocker lock(&_mutex);
auto savedId = _savedId;
auto current = _current;
lock.unlock();
return _environment->threadSafeResolveId(current, savedId);
}
rpl::producer<DeviceResolvedId> DeviceResolver::value() const {
return _data.value();
}
rpl::producer<DeviceResolvedId> DeviceResolver::changes() const {
return _data.changes();
}
DeviceChangeReason DeviceResolver::lastChangeReason() const {
return _lastChangeReason;
}
rpl::producer<QString> DeviceIdOrDefault(
rpl::producer<QString> id) {
return std::move(id) | rpl::map([](const QString &id) {
return !id.isEmpty() ? id : kDefaultDeviceId;
}) | rpl::distinct_until_changed();
}
rpl::producer<QString> DeviceIdValueWithFallback(
rpl::producer<QString> id,
rpl::producer<QString> fallback) {
return rpl::combine(
std::move(id),
std::move(fallback)
) | rpl::map([](const QString &id, const QString &fallback) {
return !id.isEmpty()
? id
: !fallback.isEmpty()
? fallback
: kDefaultDeviceId;
}) | rpl::distinct_until_changed();
}
} // namespace Webrtc