Initial commit

This commit is contained in:
Andre Henriques 2022-08-05 08:25:13 +01:00
commit 97541d7d3c
4 changed files with 977 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/target
links
# Added by cargo
#
# already existing elements were commented out
#/target

575
Cargo.lock generated Normal file
View File

@ -0,0 +1,575 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bindgen"
version = "0.59.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-expr"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db"
dependencies = [
"smallvec",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cookie-factory"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b"
[[package]]
name = "either"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
[[package]]
name = "env_logger"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "libloading"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
dependencies = [
"cfg-if 1.0.0",
"winapi",
]
[[package]]
name = "libspa"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8bb02bbc8d550e2f0a31989c61e1ac3c883bab2edee49ffcb5d5ca18266786d"
dependencies = [
"bitflags",
"cc",
"cookie-factory",
"errno",
"libc",
"libspa-sys",
"nom",
"system-deps",
]
[[package]]
name = "libspa-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8d2e38d6cdd10d7d78eb0cb409c127cf16da2c296d9623375551e309616d4d"
dependencies = [
"bindgen",
"system-deps",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nix"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]]
name = "nom"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pipewire"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d80fef8219c37f479f3d62d70167f3daaa90b71a083f7fd88d69e49f05f0ecdc"
dependencies = [
"anyhow",
"bitflags",
"errno",
"libc",
"libspa",
"libspa-sys",
"once_cell",
"pipewire-sys",
"signal",
"thiserror",
]
[[package]]
name = "pipewire-autoconnect"
version = "0.1.0"
dependencies = [
"lazy_static",
"libspa",
"pipewire",
"regex",
]
[[package]]
name = "pipewire-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6d4262ea1fd3b01786046d1892cc49e9578d872faf8723d95dc7affc810ee4"
dependencies = [
"bindgen",
"libspa-sys",
"system-deps",
]
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro2"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "serde"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "signal"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f6ce83b159ab6984d2419f495134972b48754d13ff2e3f8c998339942b56ed9"
dependencies = [
"libc",
"nix",
]
[[package]]
name = "smallvec"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "system-deps"
version = "6.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml",
"version-compare",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version-compare"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "which"
version = "4.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
dependencies = [
"either",
"lazy_static",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "pipewire-autoconnect"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
pipewire = "0.5.0"
libspa = "0.5.0"
regex = "1.6.0"
lazy_static = "1.4.0"

381
src/main.rs Normal file
View File

@ -0,0 +1,381 @@
use std::{cell::RefCell, env, fs, io::BufRead, collections::HashMap};
use std::vec::Vec;
use std::{cell::RefMut, rc::Rc};
use libspa::ReadableDict;
use pipewire::{types::ObjectType, Context, MainLoop};
use pipewire as pw;
use regex::Regex;
#[macro_use]
extern crate lazy_static;
#[derive(Debug)]
struct Port {
id: u32,
name: String,
node: Rc<Node>,
}
#[derive(Debug)]
struct Node {
id: u32,
name: String,
}
#[derive(Debug)]
struct NodeDef {
name: String,
}
#[derive(Debug)]
struct PortDef {
node: Rc<NodeDef>,
name: String,
}
#[derive(Debug)]
struct LinkDef {
port_in: Rc<PortDef>,
port_out: Rc<PortDef>,
}
struct AppState {
ports: Vec<Rc<Port>>,
nodes: Vec<Rc<Node>>,
get_names: bool,
node_def: Vec<Rc<NodeDef>>,
link_def: Vec<Rc<LinkDef>>,
port_def: Vec<Rc<PortDef>>,
}
fn search<T, P>(v: &[Rc<T>], f: P) -> Option<Rc<T>>
where
T: Sized,
P: FnMut(&&Rc<T>) -> bool,
{
let n = v.iter().filter(f).cloned().collect::<Vec<Rc<T>>>();
if n.len() != 1 {
return None;
}
Some(n[0].clone())
}
impl AppState {
fn new(
node_def: Vec<Rc<NodeDef>>,
link_def: Vec<Rc<LinkDef>>,
port_def: Vec<Rc<PortDef>>,
get_names: bool,
) -> AppState {
AppState {
node_def,
link_def,
port_def,
get_names,
ports: Vec::new(),
nodes: Vec::new(),
}
}
fn try_add_node(&mut self, def: Node) -> bool {
if !self.node_def.iter().any(|a| a.name.eq(&def.name)) {
return false;
};
let mut nodes = self
.nodes
.iter()
.filter(|a| !a.name.eq(&def.name))
.cloned()
.collect::<Vec<Rc<Node>>>();
nodes.push(Rc::new(def));
self.nodes = nodes;
true
}
fn get_node(&self, id: u32) -> Option<Rc<Node>> {
search(&self.nodes, |a| a.id == id)
}
fn get_port_by_name(&self, name: String) -> Option<Rc<Port>> {
search(&self.ports, |a| a.name.eq(&name))
}
fn try_add_port(&mut self, id: u32, name: String, node_id: u32) -> bool {
let node = self.get_node(node_id);
if node.is_none() {
return false;
}
let node = node.unwrap();
if self
.port_def
.iter()
.filter(|a| a.name.eq(&name) && a.node.name.eq(&node.name))
.count()
!= 1
{
if self.get_names && node.id == node_id {
println!("Port from node {} -> {}: {}", &node.name, id, name);
}
return false;
}
let mut ports = self
.ports
.iter()
.filter(|a| !(a.name.eq(&name) && a.node.name.eq(&node.name)))
.cloned()
.collect::<Vec<Rc<Port>>>();
ports.push(Rc::new(Port { id, name, node }));
self.ports = ports;
true
}
fn create_links(&mut self, port_name: String, core: Rc<pw::Core>) {
#[derive(Debug)]
struct TempLink {
port_in: Option<Rc<Port>>,
port_out: Option<Rc<Port>>,
}
self.link_def
.iter()
.filter(|link| (link.port_in.name.eq(&port_name) || link.port_out.name.eq(&port_name)))
.map(|a| TempLink {
port_in: self.get_port_by_name(a.port_in.name.to_string()),
port_out: self.get_port_by_name(a.port_out.name.to_string()),
}).filter(|a| a.port_in.is_some() && a.port_out.is_some()).for_each(|a| {
let port_in = a.port_in.unwrap();
let port_out = a.port_out.unwrap();
println!("Try to created link: [{}]{} -> [{}]{}", port_out.node.name, port_out.name, port_in.node.name, port_in.name);
// Try to create the link
if core.create_object::<pw::link::Link, _>(
// The actual name for a link factory might be different for your system,
// you should probably obtain a factory from the registry.
"link-factory",
&pw::properties! {
"link.output.port" => port_out.id.to_string(),
"link.input.port" => port_in.id.to_string(),
"link.output.node" => port_out.node.id.to_string(),
"link.input.node" => port_in.node.id.to_string(),
"object.linger" => "1"
},
).is_err() {
println!("Failed to create link");
}
});
}
}
fn deal_with_node(
global_object: &pipewire::registry::GlobalObject<libspa::ForeignDict>,
mut state: RefMut<AppState>,
) {
if let Some(props) = &global_object.props {
if let (Some(class), Some(name)) = (props.get("media.class"), props.get("node.name")) {
if class.starts_with("Audio") {
if state.get_names {
println!(
"Got Audio device {}: {}({})",
global_object.id,
name,
props.get("node.nick").unwrap_or("<no nick>")
);
}
if state.try_add_node(Node {
id: global_object.id,
name: name.to_string(),
}) {
println!(
"Got {}: {}({})",
global_object.id,
name,
props.get("node.nick").unwrap_or("<no nick>")
);
}
}
}
} else {
println!("No props! Skiping id: {:?}", global_object.id);
}
}
fn deal_with_port(
port: &pipewire::registry::GlobalObject<libspa::ForeignDict>,
mut state: RefMut<AppState>,
core: Rc<pw::Core>,
) {
if let Some(props) = &port.props {
if let (Some(name), Some(node_id)) = (props.get("port.name"), props.get("node.id")) {
if let Ok(node_id) = node_id.parse::<u32>() {
if state.try_add_port(port.id, name.to_string(), node_id) {
println!(
"Got port {} for {}",
name,
state.get_node(node_id).unwrap().name
);
state.create_links(name.to_string(), core)
}
} else {
println!("Clould not parse {}'s node.id({})", name, node_id)
}
}
} else {
println!("No props! Skiping id: {}", port.id);
}
}
fn help() {
println!("Usage: \n");
println!("pw-autoconnect <filename> \n")
}
fn parse_file(path: std::path::PathBuf, get_names: bool) -> Result<AppState, Box<dyn std::error::Error>> {
let file = fs::File::open(path)?;
let reader = std::io::BufReader::new(file);
lazy_static! {
static ref RE: Regex = Regex::new("\\[(?P<node_out>.*)\\]\\((?P<port_out>.*)\\)\\s*->\\s*\\[(?P<node_in>.*)\\]\\((?P<port_in>.*)\\)").unwrap();
}
let mut node_def: HashMap<String, Rc<NodeDef>> = HashMap::new();
let mut port_def: HashMap<String, Rc<PortDef>> = HashMap::new();
let mut link_def: Vec<Rc<LinkDef>> = Vec::new();
for line in reader.lines() {
let line = line?;
if RE.is_match(&line) {
let caps = RE.captures(&line).unwrap();
println!("Found link: [{}]{} -> [{}]{}", &caps["node_out"], &caps["port_out"], &caps["node_in"], &caps["port_in"]);
let node_out = match node_def.get_mut(&caps["node_out"]) {
Some(node) => node.to_owned(),
None => {
let node = Rc::new(NodeDef {name: caps["node_out"].to_string()});
node_def.insert(caps["node_out"].to_string(), node.clone());
node
},
};
let node_in = match node_def.get_mut(&caps["node_in"]) {
Some(node) => node.to_owned(),
None => {
let node = Rc::new(NodeDef {name: caps["node_in"].to_string()});
node_def.insert(caps["node_in"].to_string(), node.clone());
node
},
};
let port_out = match port_def.get_mut(&caps["port_out"]) {
Some(port) => port.to_owned(),
None => {
let port = Rc::new(PortDef { node: node_out.clone(), name: caps["port_out"].to_string() } );
port_def.insert(caps["port_out"].to_string(), port.clone());
port
},
};
let port_in = match port_def.get_mut(&caps["port_in"]) {
Some(port) => port.to_owned(),
None => {
let port = Rc::new(PortDef { node: node_in.clone(), name: caps["port_in"].to_string() } );
port_def.insert(caps["port_in"].to_string(), port.clone());
port
},
};
let link = Rc::new(LinkDef { port_out: port_out.clone(), port_in: port_in.clone() });
link_def.push(link)
} else if !line.starts_with('#') {
println!("invalid line: {}", line);
}
}
let node_def = node_def.values().cloned().collect::<Vec<Rc<NodeDef>>>();
let port_def = port_def.values().cloned().collect::<Vec<Rc<PortDef>>>();
Ok(AppState::new(node_def, link_def, port_def, get_names))
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Hello, world!");
let mut args = env::args();
// Skip the current directory
args.next();
let mut find_names = false;
let mut file_name = None;
for a in args {
if a.eq("-f") {
find_names = true;
continue;
}
if file_name.is_some() {
println!("File name already exists");
return Ok(());
} else {
file_name = Some(a);
}
}
if file_name.is_none() {
help();
return Ok(());
}
let file_name = file_name.unwrap();
let path = std::path::Path::new(&file_name);
if !path.exists() || !path.is_file() {
println!("File not found does not exists");
return Ok(());
}
// Create DeSized State
let state = RefCell::new(parse_file(path.to_path_buf(), find_names)?);
println!("\n\nGot state! Starting up\n\n");
let mainloop = MainLoop::new()?;
let context = Context::new(&mainloop)?;
let core = Rc::new(context.connect(None)?);
let registry = core.get_registry()?;
let _listener = registry
.add_listener_local()
.global(move |global| match global.type_ {
ObjectType::Port => deal_with_port(global, state.borrow_mut(), core.clone()),
ObjectType::Node => deal_with_node(global, state.borrow_mut()),
_ => (),
})
.register();
mainloop.run();
Ok(())
}