pipewire/main_loop/
box_.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use std::{ops::Deref, ptr};
5
6use crate::Error;
7
8use super::MainLoop;
9
10/// Smart pointer providing unique ownership of a PipeWire [main loop](super).
11///
12/// For shared ownership, see [`MainLoopRc`](super::MainLoopRc).
13///
14/// For an explanation of these, see [Smart pointers to PipeWire objects](crate#smart-pointers-to-pipewire-objects).
15#[derive(Debug)]
16pub struct MainLoopBox {
17    ptr: std::ptr::NonNull<pw_sys::pw_main_loop>,
18}
19
20impl MainLoopBox {
21    /// Initialize Pipewire and create a new [`MainLoopBox`]
22    pub fn new(properties: Option<&spa::utils::dict::DictRef>) -> Result<Self, Error> {
23        crate::init();
24
25        unsafe {
26            let props = properties
27                .map_or(ptr::null(), |props| props.as_raw())
28                .cast_mut();
29
30            let raw = pw_sys::pw_main_loop_new(props);
31            let ptr = ptr::NonNull::new(raw).ok_or(Error::CreationFailed)?;
32
33            Ok(Self::from_raw(ptr))
34        }
35    }
36
37    /// Create a new main loop from a raw [`pw_main_loop`](`pw_sys::pw_main_loop`), taking ownership of it.
38    ///
39    /// # Safety
40    /// The provided pointer must point to a valid, well aligned [`pw_main_loop`](`pw_sys::pw_main_loop`).
41    ///
42    /// The raw loop should not be manually destroyed or moved, as the new [`MainLoopBox`] takes ownership of it.
43    pub unsafe fn from_raw(ptr: ptr::NonNull<pw_sys::pw_main_loop>) -> Self {
44        Self { ptr }
45    }
46
47    pub fn into_raw(self) -> std::ptr::NonNull<pw_sys::pw_main_loop> {
48        // Use ManuallyDrop to give up ownership of the managed struct and not run the destructor.
49        std::mem::ManuallyDrop::new(self).ptr
50    }
51}
52
53impl std::ops::Deref for MainLoopBox {
54    type Target = MainLoop;
55
56    fn deref(&self) -> &Self::Target {
57        unsafe { self.ptr.cast::<MainLoop>().as_ref() }
58    }
59}
60
61impl AsRef<MainLoop> for MainLoopBox {
62    fn as_ref(&self) -> &MainLoop {
63        self.deref()
64    }
65}
66
67impl std::ops::Drop for MainLoopBox {
68    fn drop(&mut self) {
69        unsafe {
70            pw_sys::pw_main_loop_destroy(self.as_raw_ptr());
71        }
72    }
73}