Compare commits

..

5 Commits

Author SHA1 Message Date
Tarasov Aleksandr 78e0a133b6 Bump version to 1.7.3 and update dependencies (#70)
* change version to 1.7.3

* deps: cargo update

orbclient -> v0.3.53
wasip2 -> v1.0.3+wasi-0.2.9
wit-bindgen + v0.57.1

* deps: update cargo-sources.json for flatpak
2026-04-21 19:41:19 +03:00
Tarasov Aleksandr 7f8b7194b6 refactor: move PipeWire initialization into a reusable helper function (#69)
Extract duplicated `pipewire::init()`, `MainLoopRc::new()`, and `ContextRc::new()` setup code from `pw_get_global_objects_thread`, `create_virtual_mic`, and `create_link` into a shared `setup_pipewire_context` helper in `src/utils/pipewire.rs`. Also ran codebase-wide linters to improve code quality.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-20 19:22:50 +03:00
Tarasov Aleksandr 302f153b91 refactor: break down handle_input into smaller methods in src/gui/input.rs (#67)
Extract sections from the long `handle_input` function into smaller,
context-specific helper methods such as `handle_hotkey_assignment`,
`handle_toggles`, `handle_playback_and_focus`, `handle_file_playback`,
`handle_navigation`, and `handle_hotkey_triggers`. This significantly
improves the maintainability and readability of `src/gui/input.rs`
while preserving original functionality.

In addition, ran `cargo clippy --fix` on the project to resolve a few
other minor health issues, like collapsing nested `if` statements and
reducing unnecessary allocations.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-20 19:21:59 +03:00
Tarasov Aleksandr f87dcb1564 refactor: remove unnecessary string cloning when finding hotkey conflicts (#68)
Changed `HotkeyConfig::find_conflicts` to return a `Vec<(&str, &str)>` rather than allocating owned `Strings`. In `src/gui/draw.rs`, the code now builds a `HashSet<&str>` directly from the borrowed strings using array-based flat-mapping, avoiding intermediate `Vec` allocations and redundant clones.

Benchmarked to be approximately 3.5x faster in scenarios involving many configured slots.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-20 19:20:54 +03:00
Tarasov Aleksandr d4d16f6ce7 Prepare Application for Flathub Submission (#64)
* chore(flatpak): prepare application for Flathub submission

- Change Flatpak filesystem permissions from `host` to `home` to comply with Flathub sandbox rules
- Remove `--share=network` build argument and implement offline Rust building using `flatpak-cargo-generator.py`
- Add generated `cargo-sources.json` to the Flatpak manifest to download dependencies
- Update `CARGO_HOME` environment variable to ensure vendored dependencies are found by `cargo build --offline`
- Update `.desktop` categories to meet Flathub specs (`AudioVideo` requirement)
- Add required `<releases>`, `bugtracker`, `vcs-browser` URLs, and valid `<developer>` tags to `metainfo.xml`

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

* chore(flatpak): prepare application for Flathub submission

- Change Flatpak filesystem permissions from `host` to `home` to comply with Flathub sandbox rules
- Remove `--share=network` build argument and implement offline Rust building using `flatpak-cargo-generator.py`
- Add generated `cargo-sources.json` to the Flatpak manifest to download dependencies
- Explicitly set `CARGO_HOME=$PWD/cargo` in build-commands to ensure vendored dependencies are found by `cargo build --offline`
- Update `.desktop` categories to meet Flathub specs (`AudioVideo` requirement)
- Add required `<releases>`, `bugtracker`, `vcs-browser` URLs, and valid `<developer>` tags to `metainfo.xml`

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

* chore(flatpak): add script to generate cargo sources

- Added `packages/flatpak/generate-sources.sh` to automate the generation of `cargo-sources.json`
- Script downloads the `flatpak-cargo-generator.py` tool from upstream, generates the offline sources map based on `Cargo.lock`, and cleans up after itself

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-17 19:35:36 +03:00
21 changed files with 6789 additions and 133 deletions
Generated
+13 -7
View File
@@ -2655,9 +2655,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "orbclient"
version = "0.3.51"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6"
checksum = "12c6933ddbbd16539a7672e697bb8d41ac3a4e99ac43eeb40c07236bd7fcb2dd"
dependencies = [
"libc",
"libredox",
@@ -2913,7 +2913,7 @@ checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
[[package]]
name = "pwsp"
version = "1.7.2"
version = "1.7.3"
dependencies = [
"async-trait",
"clap",
@@ -4017,11 +4017,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
"wit-bindgen",
"wit-bindgen 0.57.1",
]
[[package]]
@@ -4030,7 +4030,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen",
"wit-bindgen 0.51.0",
]
[[package]]
@@ -4840,6 +4840,12 @@ dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "pwsp"
version = "1.7.2"
version = "1.7.3"
edition = "2024"
authors = ["arabian"]
description = "PWSP lets you play audio files through your microphone. Has both CLI and GUI clients."
+3 -3
View File
@@ -1,6 +1,6 @@
pkgbase = pwsp-bin
pkgdesc = Lets you play audio files through your microphone (Pre-built binaries)
pkgver = 1.7.2
pkgver = 1.7.3
pkgrel = 2
url = https://github.com/arabianq/pipewire-soundpad
arch = x86_64
@@ -9,8 +9,8 @@ depends = pipewire
depends = alsa-lib
provides = pwsp
conflicts = pwsp
source = pwsp-bin-1.7.2.zip :: https://github.com/arabianq/pipewire-soundpad/releases/download/v1.7.2/pwsp-v1.7.2-linux-x64.zip
source = pipewire-soundpad-1.7.2.tar.gz :: https://github.com/arabianq/pipewire-soundpad/archive/refs/tags/v1.7.2.tar.gz
source = pwsp-bin-1.7.3.zip :: https://github.com/arabianq/pipewire-soundpad/releases/download/v1.7.3/pwsp-v1.7.3-linux-x64.zip
source = pipewire-soundpad-1.7.3.tar.gz :: https://github.com/arabianq/pipewire-soundpad/archive/refs/tags/v1.7.3.tar.gz
sha256sums = SKIP
sha256sums = SKIP
+1 -1
View File
@@ -1,7 +1,7 @@
# Maintainer: Alexander Tarasov <a.tevg@ya.ru>
pkgname=pwsp-bin
_pkgname=pipewire-soundpad
pkgver=1.7.2
pkgver=1.7.3
pkgrel=2
pkgdesc="Lets you play audio files through your microphone (Pre-built binaries)"
arch=('x86_64')
+2 -2
View File
@@ -1,6 +1,6 @@
pkgbase = pwsp
pkgdesc = Lets you play audio files through your microphone
pkgver = 1.7.2
pkgver = 1.7.3
pkgrel = 1
url = https://github.com/arabianq/pipewire-soundpad
arch = any
@@ -10,7 +10,7 @@ pkgbase = pwsp
makedepends = cargo
makedepends = pipewire
makedepends = alsa-lib
source = https://github.com/arabianq/pipewire-soundpad/archive/refs/tags/v1.7.2.tar.gz
source = https://github.com/arabianq/pipewire-soundpad/archive/refs/tags/v1.7.3.tar.gz
sha256sums = SKIP
pkgname = pwsp
+1 -1
View File
@@ -1,7 +1,7 @@
# Maintainer: Alexander Tarasov <a.tevg@ya.ru>
pkgsubn=pwsp
pkgname=pwsp
pkgver=1.7.2
pkgver=1.7.3
pkgrel=1
pkgdesc="Lets you play audio files through your microphone"
arch=('any')
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
set -e
if [ ! -f "Cargo.lock" ]; then
echo "Error: Cargo.lock not found. Please run this script from the project root."
return 1
fi
echo "Downloading flatpak-cargo-generator.py..."
curl -sLO https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/master/cargo/flatpak-cargo-generator.py
chmod +x flatpak-cargo-generator.py
echo "Generating cargo-sources.json..."
python3 flatpak-cargo-generator.py Cargo.lock -o packages/flatpak/cargo-sources.json
echo "Cleaning up..."
rm flatpak-cargo-generator.py
echo "Successfully generated packages/flatpak/cargo-sources.json"
+1 -1
View File
@@ -5,5 +5,5 @@ Exec=pwsp-wrapper.py %u
Icon=ru.arabianq.pwsp
Terminal=false
Type=Application
Categories=Audio;Utility;
Categories=AudioVideo;Audio;
Keywords=soundpad;pipewire;audio;
@@ -15,11 +15,17 @@
<launchable type="desktop-id">ru.arabianq.pwsp.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>
https://raw.githubusercontent.com/arabianq/pipewire-soundpad/master/assets/screenshot.png</image>
<image>https://raw.githubusercontent.com/arabianq/pipewire-soundpad/master/assets/screenshot.png</image>
</screenshot>
</screenshots>
<url type="homepage">https://pwsp.arabianq.ru</url>
<developer_name>arabian</developer_name>
<url type="bugtracker">https://github.com/arabianq/pipewire-soundpad/issues</url>
<url type="vcs-browser">https://github.com/arabianq/pipewire-soundpad</url>
<developer id="ru.arabianq">
<name>arabian</name>
</developer>
<releases>
<release version="1.7.3" date="2026-04-20" />
</releases>
<content_rating type="oars-1.1" />
</component>
+3 -6
View File
@@ -14,10 +14,9 @@ finish-args:
- --filesystem=xdg-run/pipewire-0
- --filesystem=xdg-run/pwsp:create
- --filesystem=xdg-run/app/ru.arabianq.pwsp:create
- --filesystem=host
- --filesystem=home
- --device=all
- --device=dri
- --share=network
- --talk-name=org.freedesktop.portal.Desktop
- --talk-name=org.freedesktop.portal.Documents
@@ -30,11 +29,8 @@ build-options:
modules:
- name: pwsp
buildsystem: simple
build-options:
build-args:
- --share=network
build-commands:
- cargo build --release
- export CARGO_HOME=$PWD/cargo && cargo build --release --offline
- install -Dm755 target/release/pwsp-daemon /app/bin/pwsp-daemon
- install -Dm755 target/release/pwsp-cli /app/bin/pwsp-cli
- install -Dm755 target/release/pwsp-gui /app/bin/pwsp-gui
@@ -45,3 +41,4 @@ modules:
sources:
- type: dir
path: ../../
- cargo-sources.json
+1 -1
View File
@@ -4,7 +4,7 @@
%global cargo_install_lib 0
Name: pwsp
Version: 1.7.2
Version: 1.7.3
Release: %autorelease
Summary: Lets you play audio files through your microphone
+3 -3
View File
@@ -42,11 +42,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
lock_file.lock()?;
let socket_path = runtime_dir.join("daemon.sock");
if let Err(e) = fs::remove_file(&socket_path) {
if e.kind() != std::io::ErrorKind::NotFound {
if let Err(e) = fs::remove_file(&socket_path)
&& e.kind() != std::io::ErrorKind::NotFound
{
return Err(e.into());
}
}
let listener = UnixListener::bind(&socket_path)?;
fs::set_permissions(&socket_path, fs::Permissions::from_mode(0o600))?;
+15 -20
View File
@@ -196,10 +196,8 @@ impl SoundpadGui {
ui.add_space(5.0);
let conflicts = self.app_state.hotkey_config.find_conflicts();
let conflict_slots: std::collections::HashSet<String> = conflicts
.iter()
.flat_map(|(a, b)| vec![a.clone(), b.clone()])
.collect();
let conflict_slots: std::collections::HashSet<&str> =
conflicts.into_iter().flat_map(|(a, b)| [a, b]).collect();
let search = self.app_state.hotkey_search_query.to_lowercase();
@@ -266,7 +264,7 @@ impl SoundpadGui {
for slot in &slots {
ui.horizontal(|ui| {
// Conflict badge
if conflict_slots.contains(&slot.slot) {
if conflict_slots.contains(slot.slot.as_str()) {
ui.label(
RichText::new(ICON_WARNING.codepoint)
.color(Color32::from_rgb(255, 165, 0)),
@@ -609,11 +607,11 @@ impl SoundpadGui {
.unwrap_or_else(|| path.to_string_lossy().to_string());
let mut dir_button_text = RichText::new(name.clone());
if let Some(current_dir) = &self.app_state.current_dir {
if current_dir.eq(&path) {
if let Some(current_dir) = &self.app_state.current_dir
&& current_dir.eq(&path)
{
dir_button_text = dir_button_text.color(Color32::WHITE);
}
}
let dir_button =
Button::new(dir_button_text.atom_max_width(area_size.x)).frame(false);
@@ -645,11 +643,10 @@ impl SoundpadGui {
ICON_OPEN_IN_BROWSER.codepoint, "Open in File Manager"
))
.clicked()
&& let Err(e) = opener::open(&path)
{
if let Err(e) = opener::open(&path) {
eprintln!("Failed to open file manager: {}", e);
}
}
ui.separator();
@@ -728,11 +725,11 @@ impl SoundpadGui {
}
let mut file_button_text = RichText::new(&file_name);
if let Some(current_file) = &self.app_state.selected_file {
if current_file.eq(&entry_path) {
if let Some(current_file) = &self.app_state.selected_file
&& current_file.eq(&entry_path)
{
file_button_text = file_button_text.color(Color32::WHITE);
}
}
let file_button = Button::new(file_button_text).frame(false);
let file_button_response = ui.add(file_button);
@@ -792,11 +789,10 @@ impl SoundpadGui {
ICON_OPEN_IN_BROWSER.codepoint, "Show in File Manager"
))
.clicked()
&& let Err(e) = opener::reveal(&entry_path)
{
if let Err(e) = opener::reveal(&entry_path) {
eprintln!("Failed to open file manager: {}", e);
}
}
ui.separator();
@@ -822,9 +818,10 @@ impl SoundpadGui {
fn get_hotkey_badge(&self, path: &PathBuf) -> Option<String> {
for slot in &self.app_state.hotkey_config.slots {
if slot.action.name == "play" {
if let Some(file_path_str) = slot.action.args.get("file_path") {
if Path::new(file_path_str) == path.as_path() {
if slot.action.name == "play"
&& let Some(file_path_str) = slot.action.args.get("file_path")
&& Path::new(file_path_str) == path.as_path()
{
if let Some(chord) = &slot.key_chord {
return Some(format!("[{}]", chord));
} else {
@@ -832,8 +829,6 @@ impl SoundpadGui {
}
}
}
}
}
None
}
+4 -4
View File
@@ -192,8 +192,9 @@ impl SoundpadGui {
}
// Play selected file on Enter
if self.key_pressed(ctx, Key::Enter) {
if let Some(path) = self.app_state.selected_file.clone() {
if self.key_pressed(ctx, Key::Enter)
&& let Some(path) = self.app_state.selected_file.clone()
{
if modifiers.ctrl {
self.play_file(&path, true);
} else if modifiers.shift
@@ -205,14 +206,13 @@ impl SoundpadGui {
self.play_file(&path, false);
}
}
}
// Iterate through dirs and files with Ctrl + Up/Down
let arrow_up_pressed = self.key_pressed(ctx, Key::ArrowUp);
let arrow_down_pressed = self.key_pressed(ctx, Key::ArrowDown);
if modifiers.ctrl && (arrow_up_pressed || arrow_down_pressed) {
if modifiers.shift && !self.app_state.dirs.is_empty() {
let mut dirs: Vec<PathBuf> = self.app_state.dirs.iter().cloned().collect();
let mut dirs: Vec<PathBuf> = self.app_state.dirs.to_vec();
dirs.sort();
let current_dir_index = self
+12 -13
View File
@@ -106,7 +106,7 @@ impl AudioPlayer {
fn abort_link_thread(&mut self) {
if let Some(sender) = &self.input_link_sender {
if let Ok(_) = sender.send(Terminate {}) {
if sender.send(Terminate {}).is_ok() {
println!("Sent terminate signal to input link thread");
self.input_link_sender = None;
} else {
@@ -117,7 +117,7 @@ impl AudioPlayer {
fn abort_player_link_thread(&mut self) {
if let Some(sender) = &self.player_link_sender {
if let Ok(_) = sender.send(Terminate {}) {
if sender.send(Terminate {}).is_ok() {
println!("Sent terminate signal to player link thread");
self.player_link_sender = None;
} else {
@@ -254,12 +254,12 @@ impl AudioPlayer {
pub fn get_volume(&mut self, id: Option<u32>) -> Option<f32> {
if let Some(id) = id {
if let Some(sound) = self.tracks.get_mut(&id) {
return Some(sound.sink.volume());
Some(sound.sink.volume())
} else {
return None;
None
}
} else {
return Some(self.volume);
Some(self.volume)
}
}
@@ -443,11 +443,11 @@ impl AudioPlayer {
if let Some(sound) = self.tracks.get(&id) {
let path = sound.path.clone();
let handle = tokio::task::spawn_blocking(move || {
if let Ok(file) = fs::File::open(&path) {
if let Ok(source) = Decoder::try_from(file) {
if let Ok(file) = fs::File::open(&path)
&& let Ok(source) = Decoder::try_from(file)
{
return Some((id, source));
}
}
None
});
restart_futures.push(handle);
@@ -455,15 +455,14 @@ impl AudioPlayer {
}
for handle in restart_futures {
if let Ok(res) = handle.await {
if let Some((id, source)) = res {
if let Some(sound) = self.tracks.get_mut(&id) {
if let Ok(res) = handle.await
&& let Some((id, source)) = res
&& let Some(sound) = self.tracks.get_mut(&id)
{
sound.sink.append(source);
sound.sink.play();
}
}
}
}
self.tracks
.retain(|_, sound| !sound.sink.empty() || sound.looped);
+1 -1
View File
@@ -673,7 +673,7 @@ impl Executable for PlayHotkeyCommand {
if let Some(cmd) = parse_command(&action) {
cmd.execute().await
} else {
Response::new(false, "Unknown command in hotkey slot".to_string())
Response::new(false, "Unknown command in hotkey slot")
}
}
}
+8 -8
View File
@@ -13,11 +13,11 @@ impl DaemonConfig {
pub fn save_to_file(&self) -> Result<(), Box<dyn Error>> {
let config_path = get_config_path()?.join("daemon.json");
if let Some(config_dir) = config_path.parent() {
if !config_path.exists() {
if let Some(config_dir) = config_path.parent()
&& !config_path.exists()
{
fs::create_dir_all(config_dir)?;
}
}
let config_json = serde_json::to_string_pretty(self)?;
fs::write(config_path, config_json.as_bytes())?;
@@ -68,11 +68,11 @@ impl GuiConfig {
pub fn save_to_file(&mut self) -> Result<(), Box<dyn Error>> {
let config_path = get_config_path()?.join("gui.json");
if let Some(config_dir) = config_path.parent() {
if !config_path.exists() {
if let Some(config_dir) = config_path.parent()
&& !config_path.exists()
{
fs::create_dir_all(config_dir)?;
}
}
// Do not save scale factor if user does not want to
if !self.save_scale_factor {
@@ -172,7 +172,7 @@ impl HotkeyConfig {
}
/// Returns pairs of slot names that share the same key chord.
pub fn find_conflicts(&self) -> Vec<(String, String)> {
pub fn find_conflicts(&self) -> Vec<(&str, &str)> {
let mut conflicts = vec![];
let mut chord_map: HashMap<&str, Vec<&str>> = HashMap::new();
@@ -186,7 +186,7 @@ impl HotkeyConfig {
if slots.len() > 1 {
for i in 0..slots.len() {
for j in (i + 1)..slots.len() {
conflicts.push((slots[i].to_string(), slots[j].to_string()));
conflicts.push((slots[i], slots[j]));
}
}
}
+1 -3
View File
@@ -1,9 +1,7 @@
use crate::{
types::{
use crate::types::{
audio_player::AudioPlayer,
config::DaemonConfig,
socket::{MAX_MESSAGE_SIZE, Request, Response},
},
};
use std::os::unix::fs::PermissionsExt;
+3 -3
View File
@@ -112,14 +112,14 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc<Mutex<AudioPlayerSt
let hotkey_res = make_request(Request::get_hotkeys())
.await
.unwrap_or_default();
if hotkey_res.status {
if let Ok(config) = serde_json::from_str::<HotkeyConfig>(&hotkey_res.message) {
if hotkey_res.status
&& let Ok(config) = serde_json::from_str::<HotkeyConfig>(&hotkey_res.message)
{
let mut guard = audio_player_state_shared
.lock()
.unwrap_or_else(|e| e.into_inner());
guard.hotkey_config = Some(config);
}
}
last_hotkey_poll = Instant::now();
}
+14 -16
View File
@@ -9,6 +9,13 @@ use tokio::{
time::{Duration, timeout},
};
pub fn setup_pipewire_context() -> (MainLoopRc, ContextRc) {
pipewire::init();
let main_loop = MainLoopRc::new(None).expect("Failed to initialize pipewire main loop");
let context = ContextRc::new(&main_loop, None).expect("Failed to create pipewire context");
(main_loop, context)
}
fn parse_global_object(
global_object: &GlobalObject<&DictRef>,
) -> (Option<AudioDevice>, Option<Port>) {
@@ -56,12 +63,13 @@ fn parse_global_object(
(None, None)
};
// Check if the object is a port
} else if props.get("port.direction").is_some() {
if let (Some(node_id), Some(port_id), Some(port_name)) = (
} else if props.get("port.direction").is_some()
&& let (Some(node_id), Some(port_id), Some(port_name)) = (
props.get("node.id").and_then(|id| id.parse::<u32>().ok()),
props.get("port.id").and_then(|id| id.parse::<u32>().ok()),
props.get("port.name"),
) {
)
{
let port = Port {
node_id,
port_id,
@@ -71,7 +79,6 @@ fn parse_global_object(
return (None, Some(port));
}
}
}
(None, None)
}
@@ -79,9 +86,7 @@ async fn pw_get_global_objects_thread(
main_sender: mpsc::Sender<(Option<AudioDevice>, Option<Port>)>,
pw_receiver: pipewire::channel::Receiver<Terminate>,
) {
pipewire::init();
let main_loop = MainLoopRc::new(None).expect("Failed to initialize pipewire main loop");
let (main_loop, context) = setup_pipewire_context();
// Stop main loop on Terminate message
let _receiver = pw_receiver.attach(main_loop.loop_(), {
@@ -89,7 +94,6 @@ async fn pw_get_global_objects_thread(
move |_| _main_loop.quit()
});
let context = ContextRc::new(&main_loop, None).expect("Failed to create pipewire context");
let core = context
.connect(None)
.expect("Failed to connect to pipewire context");
@@ -224,10 +228,7 @@ pub fn create_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>, Box<
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
let _pw_thread = thread::spawn(move || {
pipewire::init();
let main_loop = MainLoopRc::new(None).expect("Failed to initialize pipewire main loop");
let context = ContextRc::new(&main_loop, None).expect("Failed to create pipewire context");
let (main_loop, context) = setup_pipewire_context();
let core = context
.connect(None)
.expect("Failed to connect to pipewire context");
@@ -305,10 +306,7 @@ pub fn create_link(
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
let _pw_thread = thread::spawn(move || {
pipewire::init();
let main_loop = MainLoopRc::new(None).expect("Failed to initialize pipewire main loop");
let context = ContextRc::new(&main_loop, None).expect("Failed to create pipewire context");
let (main_loop, context) = setup_pipewire_context();
let core = context
.connect(None)
.expect("Failed to connect to pipewire context");