Auto reconnect
This commit is contained in:
parent
b3a1d2b7f3
commit
f57d39af48
2 changed files with 187 additions and 5 deletions
|
|
@ -156,7 +156,7 @@ void registryEventGlobal(void *data, uint32_t id, uint32_t permissions,
|
||||||
void registryEventGlobalRemove(void *data, uint32_t id)
|
void registryEventGlobalRemove(void *data, uint32_t id)
|
||||||
{
|
{
|
||||||
auto *self = static_cast<PipeWireController*>(data);
|
auto *self = static_cast<PipeWireController*>(data);
|
||||||
|
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&self->m_nodesMutex);
|
QMutexLocker lock(&self->m_nodesMutex);
|
||||||
if (self->m_nodes.contains(id)) {
|
if (self->m_nodes.contains(id)) {
|
||||||
|
|
@ -164,18 +164,27 @@ void registryEventGlobalRemove(void *data, uint32_t id)
|
||||||
emit self->nodeRemoved(id);
|
emit self->nodeRemoved(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->m_ports.contains(id)) {
|
if (self->m_ports.contains(id)) {
|
||||||
self->m_ports.remove(id);
|
self->m_ports.remove(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool linkRemoved = false;
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&self->m_nodesMutex);
|
||||||
if (self->m_links.contains(id)) {
|
if (self->m_links.contains(id)) {
|
||||||
self->m_links.remove(id);
|
self->m_links.remove(id);
|
||||||
emit self->linkRemoved(id);
|
linkRemoved = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (linkRemoved) {
|
||||||
|
emit self->linkRemoved(id);
|
||||||
|
self->handleLinkRemoval(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void coreEventDone(void *data, uint32_t id, int seq)
|
void coreEventDone(void *data, uint32_t id, int seq)
|
||||||
|
|
@ -769,6 +778,11 @@ bool PipeWireController::destroyLink(uint32_t linkId)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
linkInfo = m_links.value(linkId);
|
linkInfo = m_links.value(linkId);
|
||||||
|
m_userRemovedLinks.insert(linkId);
|
||||||
|
if (m_linkIntentKeys.contains(linkId)) {
|
||||||
|
const QString key = m_linkIntentKeys.take(linkId);
|
||||||
|
m_linkIntents.remove(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
|
|
@ -786,6 +800,154 @@ bool PipeWireController::destroyLink(uint32_t linkId)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PipeWireController::rememberLinkIntent(const LinkInfo &link)
|
||||||
|
{
|
||||||
|
QString key;
|
||||||
|
if (!buildLinkIntentKey(link, key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
m_linkIntents.insert(key);
|
||||||
|
m_linkIntentKeys.insert(link.id, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeWireController::handleLinkRemoval(uint32_t linkId)
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
if (m_userRemovedLinks.contains(linkId)) {
|
||||||
|
m_userRemovedLinks.remove(linkId);
|
||||||
|
}
|
||||||
|
if (m_linkIntentKeys.contains(linkId)) {
|
||||||
|
m_linkIntentKeys.remove(linkId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeWireController::tryRestoreLinks()
|
||||||
|
{
|
||||||
|
QList<QString> intents;
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
intents = m_linkIntents.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &key : intents) {
|
||||||
|
uint32_t outNodeId = 0;
|
||||||
|
uint32_t outPortId = 0;
|
||||||
|
uint32_t inNodeId = 0;
|
||||||
|
uint32_t inPortId = 0;
|
||||||
|
if (!resolveLinkIntentKey(key, outNodeId, outPortId, inNodeId, inPortId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
createLink(outNodeId, outPortId, inNodeId, inPortId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeWireController::updateLinkIntentsForNode(uint32_t nodeId)
|
||||||
|
{
|
||||||
|
QVector<LinkInfo> links;
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
for (auto it = m_links.cbegin(); it != m_links.cend(); ++it) {
|
||||||
|
const LinkInfo &link = it.value();
|
||||||
|
if (link.outputNodeId == nodeId || link.inputNodeId == nodeId) {
|
||||||
|
links.append(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &link : links) {
|
||||||
|
rememberLinkIntent(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isMeterNodeName(const QString &name)
|
||||||
|
{
|
||||||
|
return name.startsWith("Potato-Meter") || name.startsWith("Potato-Node-Meter");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PipeWireController::buildLinkIntentKey(const LinkInfo &link, QString &key) const
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
if (!m_nodes.contains(link.outputNodeId) || !m_nodes.contains(link.inputNodeId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeInfo &outNode = m_nodes.value(link.outputNodeId);
|
||||||
|
const NodeInfo &inNode = m_nodes.value(link.inputNodeId);
|
||||||
|
if (isMeterNodeName(outNode.name) || isMeterNodeName(inNode.name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString outPortName;
|
||||||
|
QString inPortName;
|
||||||
|
for (const auto &port : outNode.outputPorts) {
|
||||||
|
if (port.id == link.outputPortId) {
|
||||||
|
outPortName = port.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &port : inNode.inputPorts) {
|
||||||
|
if (port.id == link.inputPortId) {
|
||||||
|
inPortName = port.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outPortName.isEmpty() || inPortName.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (outNode.stableId.isEmpty() || inNode.stableId.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = QString("%1||%2>>%3||%4").arg(outNode.stableId, outPortName, inNode.stableId, inPortName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PipeWireController::resolveLinkIntentKey(const QString &key, uint32_t &outNodeId, uint32_t &outPortId,
|
||||||
|
uint32_t &inNodeId, uint32_t &inPortId) const
|
||||||
|
{
|
||||||
|
const QStringList halves = key.split(">>");
|
||||||
|
if (halves.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const QStringList outParts = halves.at(0).split("||");
|
||||||
|
const QStringList inParts = halves.at(1).split("||");
|
||||||
|
if (outParts.size() != 2 || inParts.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString outStableId = outParts.at(0);
|
||||||
|
const QString outPortName = outParts.at(1);
|
||||||
|
const QString inStableId = inParts.at(0);
|
||||||
|
const QString inPortName = inParts.at(1);
|
||||||
|
|
||||||
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
for (const auto &nodeEntry : m_nodes) {
|
||||||
|
const NodeInfo &node = nodeEntry;
|
||||||
|
if (node.stableId == outStableId) {
|
||||||
|
for (const auto &port : node.outputPorts) {
|
||||||
|
if (port.name == outPortName) {
|
||||||
|
outNodeId = node.id;
|
||||||
|
outPortId = port.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.stableId == inStableId) {
|
||||||
|
for (const auto &port : node.inputPorts) {
|
||||||
|
if (port.name == inPortName) {
|
||||||
|
inNodeId = node.id;
|
||||||
|
inPortId = port.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outNodeId != 0 && outPortId != 0 && inNodeId != 0 && inPortId != 0;
|
||||||
|
}
|
||||||
|
|
||||||
QString PipeWireController::dumpGraph() const
|
QString PipeWireController::dumpGraph() const
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&m_nodesMutex);
|
QMutexLocker lock(&m_nodesMutex);
|
||||||
|
|
@ -870,6 +1032,9 @@ void PipeWireController::handleNodeInfo(uint32_t id, const struct spa_dict *prop
|
||||||
qDebug() << "Node changed:" << node.id << node.name;
|
qDebug() << "Node changed:" << node.id << node.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateLinkIntentsForNode(id);
|
||||||
|
tryRestoreLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipeWireController::handlePortInfo(uint32_t id, const struct spa_dict *props)
|
void PipeWireController::handlePortInfo(uint32_t id, const struct spa_dict *props)
|
||||||
|
|
@ -922,6 +1087,9 @@ void PipeWireController::handlePortInfo(uint32_t id, const struct spa_dict *prop
|
||||||
emit nodeChanged(nodeSnapshot);
|
emit nodeChanged(nodeSnapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateLinkIntentsForNode(nodeId);
|
||||||
|
tryRestoreLinks();
|
||||||
|
|
||||||
qDebug() << "Port added:" << id << portName << "direction:" << direction;
|
qDebug() << "Port added:" << id << portName << "direction:" << direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -949,6 +1117,8 @@ void PipeWireController::handleLinkInfo(uint32_t id, const struct spa_dict *prop
|
||||||
}
|
}
|
||||||
|
|
||||||
emit linkAdded(link);
|
emit linkAdded(link);
|
||||||
|
|
||||||
|
rememberLinkIntent(link);
|
||||||
|
|
||||||
qDebug() << "Link added:" << id << "from" << outputNode << ":" << outputPort
|
qDebug() << "Link added:" << id << "from" << outputNode << ":" << outputPort
|
||||||
<< "to" << inputNode << ":" << inputPort;
|
<< "to" << inputNode << ":" << inputPort;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QAtomicInteger>
|
#include <QAtomicInteger>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QSet>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -82,6 +84,13 @@ private:
|
||||||
bool createVirtualDevice(const QString &name, const QString &description,
|
bool createVirtualDevice(const QString &name, const QString &description,
|
||||||
const char *factoryName, const char *mediaClass,
|
const char *factoryName, const char *mediaClass,
|
||||||
int channels, int rate);
|
int channels, int rate);
|
||||||
|
void rememberLinkIntent(const LinkInfo &link);
|
||||||
|
void handleLinkRemoval(uint32_t linkId);
|
||||||
|
void tryRestoreLinks();
|
||||||
|
void updateLinkIntentsForNode(uint32_t nodeId);
|
||||||
|
bool buildLinkIntentKey(const LinkInfo &link, QString &key) const;
|
||||||
|
bool resolveLinkIntentKey(const QString &key, uint32_t &outNodeId, uint32_t &outPortId,
|
||||||
|
uint32_t &inNodeId, uint32_t &inPortId) const;
|
||||||
|
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
@ -99,6 +108,9 @@ private:
|
||||||
QMap<uint32_t, NodeInfo> m_nodes;
|
QMap<uint32_t, NodeInfo> m_nodes;
|
||||||
QMap<uint32_t, PortInfo> m_ports;
|
QMap<uint32_t, PortInfo> m_ports;
|
||||||
QMap<uint32_t, LinkInfo> m_links;
|
QMap<uint32_t, LinkInfo> m_links;
|
||||||
|
QSet<QString> m_linkIntents;
|
||||||
|
QHash<uint32_t, QString> m_linkIntentKeys;
|
||||||
|
QSet<uint32_t> m_userRemovedLinks;
|
||||||
|
|
||||||
QAtomicInteger<bool> m_connected{false};
|
QAtomicInteger<bool> m_connected{false};
|
||||||
QAtomicInteger<bool> m_initialized{false};
|
QAtomicInteger<bool> m_initialized{false};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue