Introduce initial implementation of the vmic CLI with PipeWire integration

- Added `Cargo.toml` to define dependencies and project metadata.
- Implemented core CLI functionality for managing virtual microphones (`create`, `edit`, `delete`, `list`, `route`, and `wipe` commands) using `clap`.
- Integrated `rusqlite` for persistent state storage and `pipewire` to manage PipeWire nodes.
- Ensured graceful handling of feedback loops and system defaults during virtual mic creation and deletion.
- Added error handling via `thiserror` for cleaner error definitions.
This commit is contained in:
2026-08-11 13:28:33 +02:00
parent 76c129a5dc
commit e19f398397
18 changed files with 2151 additions and 1 deletions

90
src/cli.rs Normal file
View File

@@ -0,0 +1,90 @@
use clap::{Args, Parser, Subcommand};
use clap_complete::Shell;
/// vmic - create and manage PipeWire virtual microphones.
#[derive(Parser)]
#[command(name = "vmic", version, about)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
/// Create a new virtual microphone.
#[command(visible_alias = "mk", visible_alias = "make")]
Create(CreateArgs),
/// Move app streams and mix a hardware source into a vmic.
Route(RouteArgs),
/// Change loopback and volume settings on a vmic.
Edit(EditArgs),
/// Delete a virtual microphone.
#[command(visible_alias = "rm", visible_alias = "remove")]
Delete(DeleteArgs),
/// List all virtual microphones.
#[command(visible_alias = "ls")]
List,
/// Tear down every vmic, tracked or not.
#[command(visible_alias = "reset")]
Wipe,
/// Generate a shell completion script.
Completions { shell: Shell },
}
#[derive(Args)]
pub struct CreateArgs {
/// Name for the new vmic.
pub name: String,
/// Enable a self-monitor loopback.
#[arg(short, long)]
pub loopback: bool,
}
#[derive(Args)]
pub struct RouteArgs {
/// Name of the vmic to route into.
pub name: String,
/// Move matching sink-inputs into this vmic's sink.
#[arg(short, long = "input", value_name = "APP[:MEDIA]")]
pub inputs: Vec<String>,
/// Move matching source-outputs off this vmic's source.
#[arg(short, long = "output", value_name = "APP[:MEDIA]")]
pub outputs: Vec<String>,
/// Mix a hardware source into the vmic, or "off" to remove it.
#[arg(short, long = "source", value_name = "SOURCE|off")]
pub source: Option<String>,
}
#[derive(Args)]
pub struct EditArgs {
/// Name of the vmic to edit.
pub name: String,
/// Enable or disable the self-monitor loopback.
#[arg(short, long)]
pub loopback: Option<bool>,
/// Loopback volume: fraction (0.8) or percent (80).
#[arg(short, long)]
pub volume: Option<f32>,
/// Mixed-in source volume: fraction (0.8) or percent (80).
#[arg(long = "source-volume", visible_alias = "sv")]
pub source_volume: Option<f32>,
}
#[derive(Args)]
pub struct DeleteArgs {
/// Name of the vmic to delete.
pub name: String,
}