11 个版本 (7 个重大变更)
0.8.0 | 2024年2月6日 |
---|---|
0.7.2 | 2023年8月24日 |
0.6.0 | 2023年2月12日 |
0.5.0 | 2022年3月22日 |
0.1.0 | 2019年8月13日 |
#19 in 多媒体
9,168 每月下载量
用于 9 个包(8 个直接使用)
490KB
11K SLoC
pipewire
PipeWire 的 Rust 绑定。
这些绑定提供了一个安全的 API,可以用来与 PipeWire 交互。
文档
请参阅 crate 文档。
lib.rs
:
Rust 对 pipewire 的绑定
pipewire
是一个 crate,提供了对 libpipewire
(与 pipewire 服务器交互的库)的 rustic 绑定。
与 pipewire 交互的程序通常通过注册回调来响应来自服务器的事件,并通过在本地代理对象上调用方法来调用服务器上对象的方法。
入门
大多数与 pipewire 交互的程序都需要一些基本对象
- 一个
MainLoop
,它驱动程序,响应任何传入的事件并将方法调用分派。大多数时候,程序/线程将空闲在这个循环中,等待事件发生。 - 一个
Context
,用于跟踪任何 pipewire 资源。 - 一个
Core
,它是远程 pipewire 实例的代理,用于向远程服务器发送消息并接收事件。 - 可选的,一个
Registry
,可以用来管理和跟踪服务器上可用的对象。
它们可以这样创建
use pipewire::{main_loop::MainLoop, context::Context};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mainloop = MainLoop::new(None)?;
let context = Context::new(&mainloop)?;
let core = context.connect(None)?;
let registry = core.get_registry()?;
Ok(())
}
现在你可以开始将不同类型的回调连接到对象,以响应事件,并通过调用对象上的方法来更改远程的状态。
use pipewire::{main_loop::MainLoop, context::Context};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mainloop = MainLoop::new(None)?;
let context = Context::new(&mainloop)?;
let core = context.connect(None)?;
let registry = core.get_registry()?;
// Register a callback to the `global` event on the registry, which notifies of any new global objects
// appearing on the remote.
// The callback will only get called as long as we keep the returned listener alive.
let _listener = registry
.add_listener_local()
.global(|global| println!("New global: {:?}", global))
.register();
// Calling the `destroy_global` method on the registry will destroy the object with the specified id on the remote.
// We don't have a specific object to destroy now, so this is commented out.
# // FIXME: Find a better method for this example we can actually call.
// registry.destroy_global(313).into_result()?;
mainloop.run();
Ok(())
}
请注意,注册任何回调都需要闭包具有 'static
生命周期,因此如果您需要捕获任何变量,请使用 move ||
闭包,并使用 std::rc::Rc
来访问共享变量,如果您需要修改它们,则使用一些 std::cell
变体。
还请注意,我们在最后调用了 mainloop.run()
。这将进入循环,并且只有在从某些事件中调用 mainloop.quit()
时才会返回。如果我们没有运行循环,事件和方法调用将不会被处理,因此程序将无法完成任何操作而终止。
主循环
有时,即使我们在主循环中等待,也需要做其他事情。
这可以通过向循环中添加源来实现。
例如,我们可以在间隔上调用一个函数
use pipewire::main_loop::MainLoop;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mainloop = MainLoop::new(None)?;
let timer = mainloop.loop_().add_timer(|_| println!("Hello"));
// Call the first time in half a second, and then in a one second interval.
timer.update_timer(Some(Duration::from_millis(500)), Some(Duration::from_secs(1))).into_result()?;
mainloop.run();
Ok(())
}
此程序将每秒打印出 "Hello",永远如此。
使用类似的方法,您也可以对IO或信号做出反应,或者当循环空闲时调用回调。
多线程
pipewire库实际上并不是线程安全的,因此pipewire对象没有实现 Send
或 Sync
。
然而,您可以在另一个线程中启动一个 MainLoop
并使用两个通道进行双向通信。
要向主线程发送消息,我们可以轻松使用一个 std::sync::mpsc
。因为我们卡在pipewire线程中的主循环中,不能简单地阻塞在接收消息,所以我们使用一个 pipewire::channel
。
有关详细信息,请参阅 pipewire::channel
模块。
依赖项
~3.5–7MB
~127K SLoC