### Get System Interface Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Returns a reference to the initialized system interface. Panics if the interface has not been initialized. ```rust pub fn system(&self) -> &Arc>> { self.system .as_ref() .expect("System interface should be initialized") } ``` -------------------------------- ### Simple Property Setting and Getting Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Demonstrates basic usage of the `Properties` struct, including creating a new instance, setting a key-value pair, retrieving a value, and asserting its type conversions (u32 and bool). ```rust let mut props = Properties::new(); props.set("key1", format! {"{}", 1}); assert_eq!(props.get("key1"), Some("1")); for (k, v) in props.iter() { assert_eq!(k, "key1"); assert_eq!(v, "1"); } assert_eq!(props.get_u32("key1"), Some(1u32)); assert_eq!(props.get_bool("key1"), Some(true)); ``` -------------------------------- ### ThreadLoop::run Source: https://docs.rs/pipewire-native/latest/pipewire_native/thread_loop/struct.ThreadLoop.html Starts and runs the thread main loop. ```APIDOC ## ThreadLoop::run ### Description Run the thread main loop. ### Signature ```rust pub fn run(&self) ``` ``` -------------------------------- ### Create new Properties Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Initializes an empty `Properties` struct. Use this when starting with no predefined properties. ```rust pub fn new() -> Self { Self { map: HashMap::new(), } } ``` -------------------------------- ### Core Initialization and Connection Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/core.rs.html Initializes the PipeWire core proxy, sends a hello message, and updates client properties. This is part of the setup process for a new PipeWire core instance. ```rust proxy_object_invoke!(core_proxy, hello, VERSION)?; proxy_object_invoke!(client_proxy, update_properties, &this.inner.properties)?; this.inner .client .connect(Some(&this.inner.properties.dict()), None)?; Ok(this) } ``` -------------------------------- ### Example Usage Source: https://docs.rs/pipewire-native/latest/pipewire_native/trait.Refcounted.html Demonstrates how to use the `Refcounted` trait, particularly `downgrade` and `upgrade`, within a closure to manage object references. ```APIDOC ## Example usage: ```rust let registry = core.registry(); // Generate a weak reference, so the closure does not force the object to be alive forever. let registry_weak = registry.downgrade(); registry.add_listener(ProxyEvents { // Use the some_closure!() macro to avoid this boilerplate global: move |id, _perms, type_, version, props| { let registry = registry_weak .upgrade() .expect("registry hook should not outlive registry"); let object = registry.bind(id, type_, version); // ... }, ..Default::default() }); ``` The closure! macro can be used to reduce the boilerplate of going through the `downgrade()`/`upgrade()` cycle, especially for values that need to be sent into multiple closures. ``` -------------------------------- ### Get Log Interface Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Returns a reference to the initialized log interface. Panics if the interface has not been initialized. ```rust pub fn log(&self) -> &Arc>> { self.log .as_ref() .expect("Log interface should be initialized") } ``` -------------------------------- ### Run Thread Main Loop Source: https://docs.rs/pipewire-native/latest/pipewire_native/thread_loop/struct.ThreadLoop.html Starts and runs the thread main loop. This method will block until the loop is quit. ```rust pub fn run(&self) ``` -------------------------------- ### Enter Main Loop Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Enters the main loop's context, typically called before starting loop operations. ```rust self.inner.support.loop_control.enter() ``` -------------------------------- ### Get configuration path from default config directory Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/conf.rs.html Constructs a configuration path by joining a given path with the `PIPEWIRE_CONFIG_DIR` constant. ```rust fn get_configdir_path(path: &PathBuf) -> std::io::Result { try_path(PathBuf::from(PIPEWIRE_CONFIG_DIR).join(path)) } ``` -------------------------------- ### Get configuration path from PIPEWIRE_CONFIG_DIR Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/conf.rs.html Constructs a configuration path by joining a given path with the directory specified in the `PIPEWIRE_CONFIG_DIR` environment variable. Returns `None` if the environment variable is not set. ```rust fn get_envconf_path(path: &PathBuf) -> Option> { if let Ok(config_dir) = std::env::var("PIPEWIRE_CONFIG_DIR") { Some(try_path(PathBuf::from(config_dir).join(path))) } else { None } } ``` -------------------------------- ### Get configuration path from XDG_CONFIG_HOME or user home directory Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/conf.rs.html Attempts to resolve a configuration path first using `XDG_CONFIG_HOME` and then falls back to the user's home directory (`~/.config/pipewire/`). ```rust fn get_homeconf_path(path: &PathBuf) -> Option> { if let Ok(xdg_home) = std::env::var("XDG_CONFIG_HOME") { let xdg_home_path = try_path( [&xdg_home, "pipewire"] .iter() .collect::() .join(path), ); if xdg_home_path.is_ok() { return Some(xdg_home_path); } } std::env::home_dir().map(|home| try_path(home.join(".config").join("pipewire").join(path))) } ``` -------------------------------- ### Rust: Get Process Name Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Lazily initializes and returns the current process name. It attempts to get the executable name and falls back to the process ID if unsuccessful. ```rust static PROCESS_NAME: LazyLock = LazyLock::new(|| { if let Ok(exe) = std::env::current_exe() { if let Some(name_part) = exe.file_name() { if let Some(name_str) = name_part.to_str() { return name_str.to_string(); } } } // Fallback to the process ID if we can't get the name format!("pid-{}", std::process::id()) }); ``` -------------------------------- ### init Source: https://docs.rs/pipewire-native/latest/pipewire_native/fn.init.html Initializes global support libraries and sets up logging. This function must be called before using any other API from this crate. ```APIDOC ## init ### Description Must be called before using any other API from this crate. Initialises global support libraries and sets up logging. ### Signature ```rust pub fn init() ``` ``` -------------------------------- ### IdMap Retrieval and Iteration Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/id_map.rs.html Provides methods to get a reference to an object by its ID and to iterate over all occupied slots. `get` returns an `Option<&T>`, and `iter` yields `(Id, &T)` tuples. ```rust pub(crate) fn get(&self, id: Id) -> Option<&T> { if (id as usize) < self.objects.len() { self.objects[id as usize].as_ref() } else { None } } pub(crate) fn iter(&self) -> impl Iterator { // Iterate over (idx, object), get references and return valid (idx, &object) self.objects .iter() .enumerate() .filter_map(|(i, obj)| obj.as_ref().map(|o| (i as Id, o))) } } ``` -------------------------------- ### Support::init_system Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Initializes the system interface if it has not been already. ```APIDOC ## Support::init_system ### Description Initializes the PipeWire system interface (`spa::interface::system::SystemImpl`) if it hasn't been initialized yet. It retrieves the interface from the internal `spa::interface::Support`. ### Function Signature ```rust pub(super) fn init_system(&mut self) ``` ### Behavior - If `self.system` is `None`, it attempts to get the `spa::interface::SYSTEM` interface and stores it in `self.system`. ``` -------------------------------- ### Run the MainLoop indefinitely Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Starts the main loop, taking over the current thread's execution until `MainLoop::quit` is called. It prevents the loop from starting if it's already marked as running. ```rust pub fn run(&self) { if self .inner .running .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) .is_err() { return; } ``` -------------------------------- ### Support::new Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Constructs a new Support instance, initializing internal structures and reading environment variables for configuration. ```APIDOC ## Support::new ### Description Creates a new `Support` instance. It reads environment variables like `PIPEWIRE_DLCLOSE`, `NO_COLOR`, `PIPEWIRE_NO_CONFIG`, `SPA_PLUGIN_DIR`, and `SPA_SUPPORT_LIB` to configure its behavior and paths. ### Function Signature ```rust pub(super) fn new() -> Support ``` ### Environment Variables - `PIPEWIRE_DLCLOSE`: Controls dynamic library closing behavior. - `NO_COLOR`: Disables color output. - `PIPEWIRE_NO_CONFIG`: Disables configuration loading. - `SPA_PLUGIN_DIR`: Specifies directories to search for SPA plugins (colon-separated). - `SPA_SUPPORT_LIB`: Specifies the path to the support library. ### Returns A new `Support` instance. ``` -------------------------------- ### get_time Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Get the time corresponding to the specified timeout. This can be used in conjunction with `MainLoop::wait`. ```APIDOC ## get_time ### Description Get the time corresponding to the specified timeout, which can be used with [MainLoop::wait]. ### Method `pub fn get_time(&self, timeout: std::time::Duration) -> std::io::Result` ### Parameters - **timeout** (std::time::Duration) - The duration for which to calculate the timespec. ### Returns std::io::Result ``` -------------------------------- ### Initialize Support Structure Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Creates a new Support instance, reading environment variables for configuration like DLCLOSE, NO_COLOR, NO_CONFIG, SPA_PLUGIN_DIR, and SPA_SUPPORT_LIB. ```rust pub(super) fn new() -> Support { let do_dlclose = utils::read_env_bool("PIPEWIRE_DLCLOSE", false); let no_color = utils::read_env_bool("NO_COLOR", false); let no_config = utils::read_env_bool("PIPEWIRE_NO_CONFIG", false); let plugin_dir = utils::read_env_string("SPA_PLUGIN_DIR", env!("SPA_DEFAULT_PLUGINDIR")) .split(':') .map(|s| s.to_string()) .collect(); let support_lib = std::env::var("SPA_SUPPORT_LIB").unwrap_or(SUPPORTLIB.to_string()); Support { _do_dlclose: do_dlclose, no_config, no_color, plugin_dirs: plugin_dir, support_lib, inner: Mutex::new(Inner { plugins: HashMap::new(), factories: HashMap::new(), handles: Vec::new(), support: spa::interface::Support::new(), }), log: None, system: None, } } ``` -------------------------------- ### Core Initialization Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/core.rs.html Initializes a new Core instance, setting up the connection, reserving ID 0, creating the core proxy, and registering it with the object map. It also initializes the client proxy. ```rust pub(crate) fn new(context: &Context, properties: Properties) -> std::io::Result { debug!("Creating new core"); let this = Self { inner: new_refcounted(InnerCore::new(context, properties)), }; // Reserve id 0 because we are id 0 let id = this.inner.objects.write().unwrap().reserve(); let core_proxy = Proxy::new(0, &this); this.inner .proxy .write() .unwrap() .replace(core_proxy.clone()); this.inner .objects .write() .unwrap() .insert_at(id, Box::new(this.clone())); let client = proxy::client::Client::new(&this); let client_proxy = client.proxy(); this.inner.client.set_core(this.downgrade()); core_proxy.add_listener(ProxyEvents { destroy: some_closure!([this] { debug!("core destroy"); let mut destroyed = this.inner.destroyed.write().unwrap(); if *destroyed { return; } *destroyed = true; let mut objects = this.inner.objects.write().unwrap(); let client = objects.get(1).unwrap(); hasproxy_notify!(client, destroy); objects.clear(); this.inner.client.disconnect(); }), removed: some_closure!([this] { debug!("core removed"); for o in this .inner .objects .read() .unwrap() .iter() .skip(1) // first object is core, so skip it .map(|(_id, object)| object) { hasproxy_notify!(o, removed) } }), ..Default::default() }); this.add_listener(CoreEvents { info: some_closure!([this] info, { if let Some(props) = info.props { debug!("updating props {:?}", props); this.context() .update_properties(props, vec!["default.clock.quantum-limit"]); } }), done: some_closure!([core_proxy] id, seq, { debug!("got done: {id} {seq}"); let core = core_proxy.object().unwrap(); let proxies = core.inner.objects.read().unwrap(); if let Some(object) = proxies.get(id) { hasproxy_notify_unlocked!(object, proxies, done, seq); } }), error: some_closure!([core_proxy] id, seq, res, message, { debug!("got error: {id} {seq} {res} {message}"); let core = core_proxy.object().unwrap(); let proxies = core.inner.objects.read().unwrap(); ``` -------------------------------- ### Get Weak Reference to Registry Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/registry/struct.Registry.html Returns the type of a weak reference to the Registry object. ```rust type WeakRef = WeakRegistry ``` -------------------------------- ### Client Initialization and Connection Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/client.rs.html Provides details on creating a new client instance and establishing a connection to the PipeWire server. ```APIDOC ## Client::new() ### Description Creates a new client instance and sets up necessary event listeners for connection events. ### Method `new()` ### Returns `Self` - A new `Client` instance. ``` ```APIDOC ## Client::connect() ### Description Initiates a connection to the PipeWire server. It currently delegates to `connect_local_socket` and has a TODO for handling specific remote intentions. ### Method `connect( props: Option<&spa::dict::Dict>, done_cb: Option)>> )` ### Parameters - `props` (Option<&spa::dict::Dict>) - Optional properties for the connection. - `done_cb` (Option)>>) - A callback function to be executed upon connection completion. ### Returns `std::io::Result<()>` - Ok if the connection attempt was initiated successfully, otherwise an error. ``` -------------------------------- ### Get Client Proxy Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/client/struct.Client.html Retrieves a Proxy for the Client object, as required by the HasProxy trait. ```rust fn proxy(&self) -> Proxy ``` -------------------------------- ### Support::system Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Returns a reference to the initialized system interface. ```APIDOC ## Support::system ### Description Provides access to the initialized system interface (`spa::interface::system::SystemImpl`). This method assumes that `init_system()` has been called. ### Function Signature ```rust pub fn system(&self) -> &Arc>> ``` ### Returns A reference to the `Arc>>`. ### Panics Panics if the system interface has not been initialized. ``` -------------------------------- ### Generic Any TypeId Method Source: https://docs.rs/pipewire-native/latest/pipewire_native/core/struct.Core.html Gets the TypeId of the current object. This is part of the Any trait implementation. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Support::init_log Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Initializes the logging interface if it has not been already. ```APIDOC ## Support::init_log ### Description Initializes the PipeWire logging interface (`spa::interface::log::LogImpl`) if it hasn't been initialized yet. It retrieves the interface from the internal `spa::interface::Support`. ### Function Signature ```rust pub(super) fn init_log(&mut self) ``` ### Behavior - If `self.log` is `None`, it attempts to get the `spa::interface::LOG` interface and stores it in `self.log`. ``` -------------------------------- ### MainLoop::new Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Creates a new main loop instance with the given properties. Returns None if initialization fails. ```APIDOC ## MainLoop::new ### Description Creates a new main loop. ### Method `pub fn new(props: &Properties) -> Option` ### Parameters * `props` (*Properties*) - Properties to configure the main loop. ``` -------------------------------- ### Initialize PipeWire Native API Source: https://docs.rs/pipewire-native/latest/pipewire_native/fn.init.html This function must be called before using any other API from this crate. It initializes global support libraries and sets up logging. ```rust pub fn init() ``` -------------------------------- ### Retrieve Client Permissions Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/client/struct.Client.html Retrieves the permissions for a client, specifying the starting index and the number of permissions to fetch. ```rust pub fn permissions(&self, index: u32, num: u32) -> Result<()> ``` -------------------------------- ### Get CPU Interface Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Retrieves the CPU interface from the internal support. Returns an Arc>>. ```rust pub fn cpu(&self) -> Arc>> { let inner = self.inner.lock().unwrap(); inner .support .get_interface::(spa::interface::CPU) .unwrap() } ``` -------------------------------- ### MainLoop::new Source: https://docs.rs/pipewire-native/latest/pipewire_native/main_loop/struct.MainLoop.html Creates a new main loop instance with the specified properties. ```APIDOC ## MainLoop::new ### Description Create a new main loop. ### Signature `pub fn new(props: &Properties) -> Option` ``` -------------------------------- ### Get Object Reference Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/mod.rs.html Retrieves a reference-counted reference to the underlying proxy object. Returns None if the object has been dropped. ```rust pub fn object(&self) -> Option { Refcounted::upgrade(&self.inner.object) } ``` -------------------------------- ### Create a new MainLoop Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Initializes a new PipeWire main loop with provided properties. Returns `None` if initialization fails. ```rust pub fn new(props: &Properties) -> Option { let l = InnerMainLoop::new(props)?; debug!("Creating main loop"); Some(MainLoop { inner: new_refcounted(l), }) } ``` -------------------------------- ### Support::cpu Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Retrieves the CPU interface, initializing it if necessary. ```APIDOC ## Support::cpu ### Description Retrieves the CPU interface (`spa::interface::cpu::CpuImpl`). It attempts to get the interface from the internal `spa::interface::Support`. If the interface is not found, it will panic. ### Function Signature ```rust pub fn cpu(&self) -> Arc>> ``` ### Returns An `Arc>>` representing the CPU interface. ### Panics Panics if the CPU interface cannot be obtained from the internal support structure. ``` -------------------------------- ### Get Port Methods Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/port.rs.html Retrieves a clone of the port's methods, which are protected by an Arc and Mutex for thread-safe access. ```rust pub(crate) fn methods(&self) -> Arc>> { self.inner.methods.clone() } ``` -------------------------------- ### Getting PipeWire Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/core.rs.html Retrieves the current PipeWire context. This function expects the context to be valid and will panic if it has been dropped. ```rust pub(crate) fn context(&self) -> Context { self.inner .context .upgrade() .expect("Context should outlive core") } ``` -------------------------------- ### Device::new Constructor Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/device.rs.html Creates a new Device proxy instance, initializing its internal state and registering it with the core PipeWire service. ```rust impl Device { pub(crate) fn new(core: &Core) -> Self { let this = Self { inner: new_refcounted(InnerDevice::new(core)), }; let id = core.next_proxy_id(); this.inner .proxy .write() .unwrap() .replace(Proxy::new(id, &this)); core.add_proxy(&this, id); this } // ... other methods ``` -------------------------------- ### Initialize System Interface Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Initializes the system interface if it has not been already. Retrieves the SystemImpl from the internal support. ```rust pub(super) fn init_system(&mut self) { let inner = self.inner.lock().unwrap(); if self.system.is_none() { self.system = inner .support .get_interface::(spa::interface::SYSTEM); } } ``` -------------------------------- ### Get Main Loop Time Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Calculates the absolute time for a given timeout duration, used with `MainLoop::wait`. ```rust self.inner.support.loop_control.get_time(timeout) ``` -------------------------------- ### Rust: Initialize PipeWire Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Creates a new PipeWire context using the provided main loop and properties. Communication with the PipeWire server will occur on this main loop. ```rust impl Context { /// Creates a new context using the given main loop and properties. Communication with the /// PipeWire server in subsequent API calls will happen on the given main loop. pub fn new(main_loop: &MainLoop, properties: Properties) -> std::io::Result { let inner = InnerContext::new(main_loop.clone(), properties)?; let context = Context { inner: new_refcounted(inner), }; // Provide (weak) reference to inner descendants that need it context.inner.protocol.set_context(context.downgrade()); Ok(context) } } ``` -------------------------------- ### Get Property Value Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the string value associated with a given key. Returns `None` if the key is not found. ```rust pub fn get(&self, key: &str) -> Option<&str> { self.map.get(key).map(|s| s.as_str()) } ``` -------------------------------- ### Rust: Get Protocol from Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Returns a reference to the [Protocol] object associated with this context. This is used for internal communication. ```rust pub(crate) fn protocol(&self) -> &Protocol { &self.inner.protocol } ``` -------------------------------- ### Context::new Source: https://docs.rs/pipewire-native/latest/pipewire_native/context/struct.Context.html Creates a new context using the given main loop and properties. Communication with the PipeWire server in subsequent API calls will happen on the given main loop. ```APIDOC ## Context::new ### Description Creates a new context using the given main loop and properties. Communication with the PipeWire server in subsequent API calls will happen on the given main loop. ### Signature ```rust pub fn new(main_loop: &MainLoop, properties: Properties) -> Result ``` ### Parameters * `main_loop`: A reference to the `MainLoop` to be used for communication. * `properties`: The `Properties` to configure the context. ### Returns A `Result` containing the newly created `Context` or an error. ``` -------------------------------- ### Rust: Get MainLoop from Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Retrieves a clone of the [MainLoop] associated with this context. This loop is used for PipeWire communication. ```rust /// Retrieves the [MainLoop] associated with this context. pub fn main_loop(&self) -> MainLoop { self.inner.main_loop.clone() } ``` -------------------------------- ### Initialize Log Topics Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/log.rs.html Initializes all defined log topics with specified log levels. It iterates through provided levels, matches them against topic names, and sets the `LogTopic` for each. If a topic doesn't have a custom level, it defaults to `Warn`. ```rust pub fn init(levels: &[(String, spa::interface::log::LogLevel)]) { for topic in [ &CONF, &CONNECTION, &CONTEXT, &CORE, &MAIN_LOOP, &PROTOCOL, &SUPPORT, &THREAD_LOOP, ] { // TODO: implement glob matching let pattern = levels.iter().find(|v| { let stripped = &topic.0[0..topic.0.len() - 1]; v.0 == stripped }); let (level, has_custom_level) = match pattern { Some(&(_, level)) => (level, true), _ => (spa::interface::log::LogLevel::Warn, false), }; let _ = topic.1.set(spa::interface::log::LogTopic { topic: std::ffi::CStr::from_bytes_with_nul(topic.0.as_bytes()).unwrap(), level, has_custom_level, }); } } ``` -------------------------------- ### DeviceChangeMask Complement Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/device/struct.DeviceChangeMask.html Get the bitwise negation of a DeviceChangeMask, truncating any unknown bits. This is useful for inverting flag sets. ```rust pub const fn complement(self) -> Self ``` -------------------------------- ### Initialize New Connection Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/connection.rs.html Constructor for the `Connection` struct. It initializes a new connection with an optional `UnixStream` and sets up the internal state. ```rust pub(crate) fn new(stream: Option) -> Self { debug!("Creating new connection to {stream:?}"); Self { inner: new_refcounted(InnerConnection::new(stream)), } } ``` -------------------------------- ### Get Event Hooks Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/mod.rs.html Provides access to the internal hook list for proxy events. Used for advanced event management. ```rust pub(crate) fn events(&self) -> Arc>> { self.inner.hooks.clone() } ``` -------------------------------- ### Setting the Client Stream and I/O Source Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/client.rs.html Configures the client's communication stream (UnixStream) and sets up an I/O source for monitoring data from the PipeWire server. This involves associating the stream's file descriptor with the main loop for event-driven processing. ```rust pub(crate) fn set_stream(&self, stream: UnixStream) -> std::io::Result<()> { debug!("Setting fd on connection: {stream:?}"); let fd = stream.as_raw_fd(); self.inner .connection .set_stream(stream.try_clone().expect("unix stream should be cloneable")); self.inner.stream.write().unwrap().replace(stream); *self.inner.connected.write().unwrap() = false; let main_loop = self.core().context().main_loop(); let source = main_loop.add_io( fd, spa::flags::Io::all(), false, closure!([client <- self] fd, mask, { client.on_remote_data(fd, spa::flags::Io::from_bits_truncate(mask)); }), ); *self.inner.source.write().unwrap() = source; Ok(()) } ``` -------------------------------- ### Hello Method Structure Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/marshal/core.rs.html Represents the 'Hello' message in the PipeWire protocol, used for initial connection handshake. It contains the protocol version. ```rust #[derive(Debug, macros::PodStruct)] pub(crate) struct Hello { version: i32, } ``` -------------------------------- ### Get Port Events Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/port.rs.html Retrieves a clone of the port's event hooks, managed by an Arc and Mutex for thread-safe access. ```rust pub(crate) fn events(&self) -> Arc>> { self.inner.hooks.clone() } ``` -------------------------------- ### Get PipeWire Remote Name Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/core.rs.html Retrieves the PipeWire remote name from the environment variable PIPEWIRE_REMOTE, or from properties, defaulting to 'pipewire-0'. ```rust pub(crate) fn get_remote(props: Option<&spa::dict::Dict>) -> String { std::env::var("PIPEWIRE_REMOTE") .ok() .filter(|v| !v.is_empty()) .or_else(|| { props .and_then(|p| p.lookup(keys::REMOTE_NAME).to_owned()) .filter(|v| !v.is_empty()) .map(|s| s.to_owned()) }) .unwrap_or(DEFAULT_REMOTE.to_owned()) } ``` -------------------------------- ### Client Creation Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/client.rs.html Provides the `new` associated function for creating a new `Client` instance, initializing its proxy and registering it with the core. ```rust impl Client { pub(crate) fn new(core: &Core) -> Self { let this = Self { inner: new_refcounted(InnerClient::new(core)), }; let id = core.next_proxy_id(); this.inner .proxy .write() .unwrap() .replace(Proxy::new(id, &this)); core.add_proxy(&this, id); this } // ... other methods ... ``` -------------------------------- ### Get Main Loop File Descriptor Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/main_loop.rs.html Retrieves the file descriptor associated with the main loop's control mechanism. ```rust self.inner.support.loop_control.get_fd() as RawFd ``` -------------------------------- ### Generic Implementations Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/port/struct.PortChangeMask.html Demonstrates generic implementations that apply to PortChangeMask. ```APIDOC ## Generic Implementations ### `impl Any for T` #### `fn type_id(&self) -> TypeId` Gets the `TypeId` of `self`. ### `impl Borrow for T` #### `fn borrow(&self) -> &T` Immutably borrows from an owned value. ### `impl BorrowMut for T` #### `fn borrow_mut(&mut self) -> &mut T` Mutably borrows from an owned value. ### `impl CloneToUninit for T` #### `unsafe fn clone_to_uninit(&self, dest: *mut u8)` Performs copy-assignment from `self` to `dest`. ### `impl From for T` #### `fn from(t: T) -> T` Returns the argument unchanged. ### `impl Into for T` #### `fn into(self) -> U` Calls `U::from(self)`. ### `impl ToOwned for T` #### `type Owned = T` The resulting type after obtaining ownership. #### `fn to_owned(&self) -> T` Creates owned data from borrowed data, usually by cloning. #### `fn clone_into(&self, target: &mut T)` Uses borrowed data to replace owned data, usually by cloning. ### `impl TryFrom for T` #### `type Error = Infallible` The type returned in the event of a conversion error. #### `fn try_from(value: U) -> Result>::Error>` Performs the conversion. ### `impl TryInto for T` #### `type Error = >::Error` The type returned in the event of a conversion error. #### `fn try_into(self) -> Result>::Error>` Performs the conversion. ``` -------------------------------- ### Rust: Get Properties from Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Retrieves a clone of the [Properties] associated with this context. These properties define the context's configuration. ```rust /// Retrieves the [Properties] associated with this context. pub fn properties(&self) -> Properties { self.inner.properties.read().unwrap().clone() } ``` -------------------------------- ### Client Initialization and Event Handling Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/client.rs.html Initializes a new PipeWire client and sets up event listeners for connection events like destruction and the need for flushing. This is crucial for managing the client's lifecycle and responding to server-initiated actions. ```rust refcounted! { pub(crate) struct Client { core: RwLock>, stream: RwLock>, connection: Connection, connected: RwLock, need_flush: RwLock, last_in_seq: RwLock, source: RwLock>, hooks: RwLock>, } } impl Client { pub(crate) fn new() -> Self { debug!("Creating new client"); let this = Self { inner: new_refcounted(InnerClient::new()), }; let listener = this.inner.connection.add_listener(ConnectionEvents { destroy: some_closure!([this] { this.on_destroy(); }), error: None, need_flush: some_closure!([this] { this.on_need_flush(); }), start: None, }); this.inner.hooks.write().unwrap().replace(listener); this } // ... other methods ``` -------------------------------- ### Load PipeWire Configuration Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/conf.rs.html Loads a PipeWire configuration file based on a prefix and name. It validates the name, handles the 'null' config case, constructs the configuration path, and reads the file content into properties. Errors are returned for invalid names or if the file cannot be read. ```rust pub(crate) fn load( prefix: Option<&str>, name: &str, properties: &mut Properties, ) -> std::io::Result<()> { debug!("Trying to load config file: {prefix:?}/{name}"); if !is_valid_name(name) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, format!("Invalid config file name: {name}"), )); } if name == "null" { debug!("Null config, nothing to do"); return Ok(()); } let path = get_config_path(prefix, name)?; if let Some(prefix) = prefix { properties.set("config.prefix", prefix.to_string()); } properties.set("config.name", name.to_string()); properties.set("config.path", path.display().to_string()); read_file(&path, properties)?; debug!("Config loaded successfully from: {}", path.display()); // TODO: .d overrides Ok(()) } ``` -------------------------------- ### Support::log Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/support.rs.html Returns a reference to the initialized logging interface. ```APIDOC ## Support::log ### Description Provides access to the initialized logging interface (`spa::interface::log::LogImpl`). This method assumes that `init_log()` has been called. ### Function Signature ```rust pub fn log(&self) -> &Arc>> ``` ### Returns A reference to the `Arc>>`. ### Panics Panics if the log interface has not been initialized. ``` -------------------------------- ### ClientChangeMask Construction Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/client/struct.ClientChangeMask.html Methods for creating and initializing ClientChangeMask instances. ```APIDOC ## ClientChangeMask::empty() ### Description Get a flags value with all bits unset. ### Returns `Self` - An empty ClientChangeMask. ## ClientChangeMask::all() ### Description Get a flags value with all known bits set. ### Returns `Self` - A ClientChangeMask with all known bits set. ## ClientChangeMask::from_bits(bits: u32) -> Option ### Description Convert from a bits value. This method will return `None` if any unknown bits are set. ### Parameters - **bits** (u32) - The bits to convert. ### Returns `Option` - The constructed ClientChangeMask or `None` if unknown bits are present. ## ClientChangeMask::from_bits_truncate(bits: u32) -> Self ### Description Convert from a bits value, unsetting any unknown bits. ### Parameters - **bits** (u32) - The bits to convert. ### Returns `Self` - The constructed ClientChangeMask with unknown bits truncated. ## ClientChangeMask::from_bits_retain(bits: u32) -> Self ### Description Convert from a bits value exactly. ### Parameters - **bits** (u32) - The bits to convert. ### Returns `Self` - The constructed ClientChangeMask. ## ClientChangeMask::from_name(name: &str) -> Option ### Description Get a flags value with the bits of a flag with the given name set. This method will return `None` if `name` is empty or doesn’t correspond to any named flag. ### Parameters - **name** (&str) - The name of the flag. ### Returns `Option` - The ClientChangeMask with the specified flag set, or `None`. ``` -------------------------------- ### Get Client Methods Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/client.rs.html Provides access to the client's methods via `methods()`, returning an `Arc>>`. ```rust pub(crate) fn methods(&self) -> Arc>> { self.inner.methods.clone() } ``` -------------------------------- ### Get Next Sequence Number Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/protocol/connection.rs.html Retrieves the next available sequence number for outgoing messages. This is used to track message ordering. ```rust pub(crate) fn next_seq(&self) -> u32 { *self.inner.out_seq.read().unwrap() } ``` -------------------------------- ### Properties::new Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Initializes an empty `Properties` struct. ```APIDOC ## fn new() -> Self Create a new, empty properties structure. ``` -------------------------------- ### DeviceChangeMask Initialization Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/device/struct.DeviceChangeMask.html Methods for creating DeviceChangeMask instances. Use `empty` for no flags, `all` for all known flags, or `from_bits` variants to initialize from raw bit values. ```rust pub const fn empty() -> Self ``` ```rust pub const fn all() -> Self ``` ```rust pub const fn from_bits(bits: u32) -> Option ``` ```rust pub const fn from_bits_truncate(bits: u32) -> Self ``` ```rust pub const fn from_bits_retain(bits: u32) -> Self ``` -------------------------------- ### Get Property as bool Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the value for a key and interprets it as a boolean using `pipewire_native_spa::atob`. Returns `None` if the key is not found. ```rust pub fn get_bool(&self, key: &str) -> Option { self.get(key).map(pipewire_native_spa::atob) } ``` -------------------------------- ### Link Implementation - Constructor and Event Management Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/link.rs.html Handles the creation of a new Link proxy and provides methods for adding and removing event listeners. It registers the proxy with the core. ```rust impl Link { pub(crate) fn new(core: &Core) -> Self { let this = Self { inner: new_refcounted(InnerLink::new()), }; let id = core.next_proxy_id(); this.inner .proxy .write() .unwrap() .replace(Proxy::new(id, &this)); core.add_proxy(&this, id); this } /// Register for notifications of link events. pub fn add_listener(&self, events: LinkEvents) -> HookId { self.inner.hooks.lock().unwrap().append(events) } /// Remove a set of event listeners. pub fn remove_listener(&self, hook_id: HookId) { self.inner.hooks.lock().unwrap().remove(hook_id); } pub(crate) fn events(&self) -> Arc>> { self.inner.hooks.clone() } } ``` -------------------------------- ### Get Property as i64 Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the value for a key and attempts to parse it as an `i64`. Returns `None` if the key is not found or parsing fails. ```rust pub fn get_i64(&self, key: &str) -> Option { self.get(key).and_then(|v| v.parse::().ok()) } ``` -------------------------------- ### Get Property as u64 Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the value for a key and attempts to parse it as a `u64`. Returns `None` if the key is not found or parsing fails. ```rust pub fn get_u64(&self, key: &str) -> Option { self.get(key).and_then(|v| v.parse::().ok()) } ``` -------------------------------- ### Metadata Proxy Initialization Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/metadata.rs.html Constructs a new Metadata proxy instance associated with a Core instance. It initializes the proxy with a unique ID and registers it with the core. ```rust impl Metadata { pub(crate) fn new(core: &Core) -> Self { let this = Self { inner: new_refcounted(InnerMetadata::new(core)), }; let id = core.next_proxy_id(); this.inner .proxy .write() .unwrap() .replace(Proxy::new(id, &this)); core.add_proxy(&this, id); this } // ... other methods ... pub(crate) fn methods(&self) -> Arc>> { self.inner.methods.clone() } pub(crate) fn events(&self) -> Arc>> { self.inner.hooks.clone() } } impl InnerMetadata { fn new(core: &Core) -> Self { Self { proxy: RwLock::new(None), methods: Arc::new(Mutex::new(protocol::marshal::metadata::Methods::marshal( core.connection(), ))), hooks: spa::hook::HookList::new(), } } } ``` -------------------------------- ### Load PipeWire Configuration Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Loads the PipeWire configuration file. It prioritizes the PIPEWIRE_CONFIG_PREFIX environment variable, then the CONFIG_PREFIX property, and defaults to 'client.conf' for the configuration name, unless 'client-rt.conf' is specified. ```rust let conf_prefix = std::env::var("PIPEWIRE_CONFIG_PREFIX").ok().or_else(|| { self.properties .read() .unwrap() .get(keys::CONFIG_PREFIX) .map(String::from) }); let conf_name = std::env::var("PIPEWIRE_CONFIG_NAME") .ok() .or_else(|| { self.properties .read() .unwrap() .get(keys::CONFIG_NAME) .map(String::from) }) .and_then(|s| if s == "client-rt.conf" { None } else { Some(s) }) .unwrap_or("client.conf".to_string()); conf::load(conf_prefix.as_deref(), &conf_name, &mut self.conf)?; ``` -------------------------------- ### Get Property as i32 Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the value for a key and attempts to parse it as an `i32`. Returns `None` if the key is not found or parsing fails. ```rust pub fn get_i32(&self, key: &str) -> Option { self.get(key).and_then(|v| v.parse::().ok()) } ``` -------------------------------- ### WeakRegistry Clone From Source: https://docs.rs/pipewire-native/latest/pipewire_native/proxy/registry/struct.WeakRegistry.html Shows how to perform copy-assignment from another WeakRegistry instance. ```APIDOC ## fn clone_from(&mut self, source: &Self) ### Description Performs copy-assignment from `source`. ### Method clone_from ### Parameters - `&mut self`: A mutable reference to the WeakRegistry instance to be updated. - `source`: A reference to the WeakRegistry instance to copy from. ``` -------------------------------- ### Get Property as u32 Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/properties.rs.html Retrieves the value for a key and attempts to parse it as a `u32`. Returns `None` if the key is not found or parsing fails. ```rust pub fn get_u32(&self, key: &str) -> Option { self.get(key).and_then(|v| v.parse::().ok()) } ``` -------------------------------- ### Rust: Get Properties Dictionary from Context Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Retrieves the properties of the context as a spa::dict::Dict. This is a low-level representation for internal use. ```rust pub(crate) fn properties_dict(&self) -> spa::dict::Dict { self.inner.properties.read().unwrap().dict() } ``` -------------------------------- ### Locate configuration file in standard paths Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/conf.rs.html Searches for a configuration file by checking absolute paths, environment variables (`PIPEWIRE_CONFIG_DIR`, `XDG_CONFIG_HOME`), user home directory, and finally default system directories. It respects a global `no_config` flag. ```rust fn get_config_path(prefix: Option<&str>, name: &str) -> std::io::Result { let mut config_path = PathBuf::new(); if let Some(prefix) = prefix { config_path.push(prefix); } config_path.push(name); if let Some(Ok(abs_path)) = get_abs_path(&config_path) { return Ok(abs_path); } if super::GLOBAL_SUPPORT.get().unwrap().no_config { debug!("User config disabled via global no-config"); return get_configdatadir_path(&config_path); } if let Some(Ok(envconf_path)) = get_envconf_path(&config_path) { return Ok(envconf_path); } if let Some(Ok(home_path)) = get_homeconf_path(&config_path) { return Ok(home_path); } get_configdir_path(&config_path).or_else(|_| get_configdatadir_path(&config_path)) } ``` -------------------------------- ### Get Bound ID Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/mod.rs.html Retrieves the "global" ID associated with the proxy object. Returns None if no ID is currently bound. ```rust pub fn bound_id(&self) -> Option { *self.inner.bound_id.read().unwrap() } ``` -------------------------------- ### Rust: Connect to PipeWire Server Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/context.rs.html Attempts to establish a connection to the PipeWire server. Returns a [Core] object representing the connection, which can be used for further interactions. ```rust /// Attemps to create a connection to the PipeWire server. The connection is represented by the /// returned [Core], which can then be used for further interaction with the PipeWire server. pub fn connect(&self, properties: Option) -> std::io::Result { Core::new(self, properties.unwrap_or_default()) } ``` -------------------------------- ### Getting PipeWire Connection Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/core.rs.html Returns the underlying PipeWire protocol connection object. This allows direct interaction with the server's communication channel. ```rust pub(crate) fn connection(&self) -> protocol::connection::Connection { self.inner.client.connection() } ``` -------------------------------- ### Module Proxy Implementation Source: https://docs.rs/pipewire-native/latest/src/pipewire_native/proxy/module.rs.html Implements the `HasProxy` trait for `Module`, providing methods to get the object type, version, and the module's proxy. ```rust impl HasProxy for Module { fn type_(&self) -> types::ObjectType { types::interface::MODULE } fn version(&self) -> u32 { 3 } fn proxy(&self) -> Proxy { self.inner .proxy .read() .unwrap() .as_ref() .expect("Module proxy should be initialised on creation") .clone() } } ```