Auto reconnect
This commit is contained in:
parent
b3a1d2b7f3
commit
f57d39af48
2 changed files with 187 additions and 5 deletions
|
|
@ -169,13 +169,22 @@ void registryEventGlobalRemove(void *data, uint32_t id)
|
|||
self->m_ports.remove(id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool linkRemoved = false;
|
||||
{
|
||||
QMutexLocker lock(&self->m_nodesMutex);
|
||||
if (self->m_links.contains(id)) {
|
||||
self->m_links.remove(id);
|
||||
emit self->linkRemoved(id);
|
||||
return;
|
||||
linkRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (linkRemoved) {
|
||||
emit self->linkRemoved(id);
|
||||
self->handleLinkRemoval(id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void coreEventDone(void *data, uint32_t id, int seq)
|
||||
|
|
@ -769,6 +778,11 @@ bool PipeWireController::destroyLink(uint32_t linkId)
|
|||
return false;
|
||||
}
|
||||
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();
|
||||
|
|
@ -786,6 +800,154 @@ bool PipeWireController::destroyLink(uint32_t linkId)
|
|||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
updateLinkIntentsForNode(id);
|
||||
tryRestoreLinks();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
updateLinkIntentsForNode(nodeId);
|
||||
tryRestoreLinks();
|
||||
|
||||
qDebug() << "Port added:" << id << portName << "direction:" << direction;
|
||||
}
|
||||
|
||||
|
|
@ -950,6 +1118,8 @@ void PipeWireController::handleLinkInfo(uint32_t id, const struct spa_dict *prop
|
|||
|
||||
emit linkAdded(link);
|
||||
|
||||
rememberLinkIntent(link);
|
||||
|
||||
qDebug() << "Link added:" << id << "from" << outputNode << ":" << outputPort
|
||||
<< "to" << inputNode << ":" << inputPort;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QAtomicInteger>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -82,6 +84,13 @@ private:
|
|||
bool createVirtualDevice(const QString &name, const QString &description,
|
||||
const char *factoryName, const char *mediaClass,
|
||||
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 unlock();
|
||||
|
|
@ -99,6 +108,9 @@ private:
|
|||
QMap<uint32_t, NodeInfo> m_nodes;
|
||||
QMap<uint32_t, PortInfo> m_ports;
|
||||
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_initialized{false};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue