/node-pipewire

NodeJS native module written in Rust and Typescript to interact with Pipewire.

Primary LanguageRustMIT LicenseMIT

node-pipewire

Requirements

As said, this module is a native Node.js module. So, if you want to use it, you need to have to compile it. For that, you need to have the following dependencies installed:

Many distributions have pipewire as audio server by default, but maybe your distro doesn't. You can check if you have pipewire installed by running the following command:

$ pactl info

If that's the case, you will need to install it manually. Fedora (34 and above) and Ubuntu (22.10 and above) has pipewire as default audio server, so you don't need to install it manually.

Depending on your linux distribution, you may need to install some other dependencies to compile the module.

Fedora:

$ sudo dnf install pipewire-devel clang

Ubuntu:

$ sudo apt install build-essential libpipewire-0.3-dev

If you are using a different distribution, you will need to find the equivalent packages. (If you find them, please open a PR to add them to this README)

Installation

First of all, we'll need to install the module:

$ npm install node-pipewire

If you have all the dependencies installed, you should be able to compile the module. If you have any problem, please open an issue.

Usage

import { createPwThread, getNodes } from 'node-pipewire';

async function main() {
  createPwThread();

  await new Promise((resolve) => setTimeout(resolve, 1000));

  const nodes = await getNodes();
  console.log(nodes);
}

main();

API

//Creates a thread that runs the pipewire loop.
createPwThread(enableDebug?: boolean)

//Returns a list of nodes.
getNodes() 

//Returns a list of ports.
getPorts()

//Returns a list of links.
getLinks()

//Returns a list of output nodes.
getOutputNodes()

//Returns a list of input nodes.
getInputNodes()

//Returns a list of name of input nodes.
getInputNodesName()

//Returns a list of name of output nodes.
getOutputNodesName()

//Links two ports.
linkPorts(inputPortId: number, outputPortId, number)

//Unlinks two ports.
unlinkPorts(inputPortId: number, outputPortId: number)

//Link all nodes that have the name `nodeName` to the node with the id `nodeId`.
linkNodesNameToId(nodeName: string, nodeId: number)

//Unlink all nodes that have the name `nodeName` to the node with the id `nodeId`.
unlinkNodesNameToId(nodeName: string, nodeId: number)

//Wait for a node to be created.
waitForNewNode(nodeName: string, direction?: 'Input' | 'Output' | 'Both', timeout?: number)

Development

This project was bootstrapped by create-neon.

Clone the repository:

  $ git clone https://github.com/kakxem/node-pipewire.git
  $ cd node-pipewire

Installing node-pipewire

Installing node-pipewire requires a supported version of Node and Rust.

You can install the project with npm. In the project directory, run:

$ npm install

This fully installs the project, including installing any dependencies and running the build.

Building node-pipewire

If you have already installed the project and only want to run the build, run:

$ npm run build

This command uses the cargo-cp-artifact utility to run the Rust build and copy the built library into ./index.node.

Exploring node-pipewire

After building node-pipewire, you can explore its exports at the Node REPL:

$ npm install
$ node
> const pipewire = require('.')
> pipewire.createPwThread()
> console.log(pipewire.getNodes())
"
[
  ..
]
"

You can also create a new file in the project directory and make your own experiments:

const test = require('.');

test.createPwThread();

setTimeout(() => {
  console.log(test.getNodes());
}, 1000);

Available Scripts

In the project directory, you can run:

npm install

Installs the project, including running npm run build.

npm build

Builds the Node addon (index.node) from source and transpile TS file to JS.

Additional cargo build arguments may be passed to npm build and npm build-* commands. For example, to enable a cargo feature:

npm run build -- --feature=beetle

npm build-debug

Alias for npm build.

npm build-release

Same as npm build but, builds the module with the release profile. Release builds will compile slower, but run faster.

npm test

Runs the unit tests by calling cargo test. You can learn more about adding tests to your Rust code from the Rust book.

Project Layout

The directory structure of this project is:

node-pipewire/
├── Cargo.toml
├── README.md
├── package.json
├── src/
|   ├── lib.rs
|   ├── pipewire_thread.rs
|   └── node/
|       ├── index.ts
|       └── types.ts
├── build/
|   ├── (.js, .d.ts, .js.map files)
|   └── index.node
└── target/

Cargo.toml

The Cargo manifest file, which informs the cargo command.

README.md

This file.

package.json

The npm manifest file, which informs the npm command.

src/

The directory tree containing the source code for the project.

src/lib.rs

The Rust library's main module.

src/pipewire_thread.rs

The Rust code for the pipewire thread.

src/node/

The directory tree containing the TypeScript source code for the project.

src/node/index.ts

The TypeScript module's main module.

src/node/types.ts

The TypeScript module's type definitions.

build/

The directory tree containing the built JS/TS files and the native module compiled.

build/(.js, .d.ts, .js.map files)

The built JavaScript and TypeScript files.

build/index.node

The Node addon—i.e., a binary Node module—generated by building the project. This is the main module for this package, as dictated by the "main" key in package.json.

Under the hood, a Node addon is a dynamically-linked shared object. The "build" script produces this file by copying it from within the target/ directory, which is where the Rust build produces the shared object.

target/

Binary artifacts generated by the Rust build.

Learn More

To learn more about Neon, see the Neon documentation.

To learn more about Rust, see the Rust documentation.

To learn more about Node, see the Node documentation.

Contribution

If you are interested in contributing to this project, please read the CONTRIBUTING file for more information.

Thank you for your interest in contributing!