Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/pulse/src/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 14 kB image not shown  

Quelle  context.rs

  Sprache: Rust
 

// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use crate::util::UnwrapCStr;
use crate::*;
use std::ffi::CStr;
use std::mem::{forget, MaybeUninit};
use std::os::raw::{c_int, c_void};
use std::ptr;

// A note about `wrapped` functions
//
// C FFI demands `unsafe extern fn(*mut pa_context, ...) -> i32`, etc,
// but we want to allow such callbacks to be safe. This means no
// `unsafe` or `extern`, and callbacks should be called with a safe
// wrapper of `*mut pa_context`. Since the callback doesn't take
// ownership, this is `&Context`. `fn wrapped<T>(...)` defines a
// function that converts from our safe signature to the unsafe
// signature.
//
// Currently, we use a property of Rust, namely that each function
// gets its own unique type.  These unique types can't be written
// directly, so we use generic and a type parameter, and let the Rust
// compiler fill in the name for us:
//
// fn get_sink_input_info<CB>(&self, ..., _: CB, ...) -> ...
//     where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
//
// Because we aren't storing or passing any state, we assert, at run-time :-(,
// that our functions are zero-sized:
//
// assert!(mem::size_of::<F>() == 0);
//
// We need to obtain a value of type F in order to call it. Since we
// can't name the function, we have to unsafely construct that value
// somehow - we do this using mem::uninitialized. Then, we call that
// function with a reference to the Context, and save the result:
//
//              |       generate value        ||  call it  |
// let result = ::std::mem::uninitialized::<F>()(&mut object);
//
// Lastly, since our Object is an owned type, we need to avoid
// dropping it, then return the result we just generated.
//
// mem::forget(object);
// result

// For all clippy-ignored warnings in this file, see
// https://github.com/mozilla/cubeb-pulse-rs/issues/95 for the effort to fix.

// Aid in returning Operation from callbacks
macro_rules! op_or_err {
    ($self_:ident, $e:expr) => {{
        let o = unsafe { $e };
        if o.is_null() {
            Err(ErrorCode::from_error_code($self_.errno()))
        } else {
            Ok(unsafe { operation::from_raw_ptr(o) })
        }
    }};
}

#[repr(C)]
#[derive(Debug)]
pub struct Context(*mut ffi::pa_context);

impl Context {
    pub fn new<'a, OPT>(api: &MainloopApi, name: OPT) -> Option<Self>
    where
        OPT: Into<Option<&'a CStr>>,
    {
        let ptr = unsafe { ffi::pa_context_new(api.raw_mut(), name.unwrap_cstr()) };
        if ptr.is_null() {
            None
        } else {
            Some(Context(ptr))
        }
    }

    #[doc(hidden)]
    #[allow(clippy::mut_from_ref)]
    pub fn raw_mut(&self) -> &mut ffi::pa_context {
        unsafe { &mut *self.0 }
    }

    pub fn unref(self) {
        unsafe {
            ffi::pa_context_unref(self.raw_mut());
        }
    }

    pub fn clear_state_callback(&self) {
        unsafe {
            ffi::pa_context_set_state_callback(self.raw_mut(), None, ptr::null_mut());
        }
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn set_state_callback<CB>(&self, _: CB, userdata: *mut c_void)
    where
        CB: Fn(&Context, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, userdata: *mut c_void)
        where
            F: Fn(&Context, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        unsafe {
            ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), userdata);
        }
    }

    pub fn errno(&self) -> ffi::pa_error_code_t {
        unsafe { ffi::pa_context_errno(self.raw_mut()) }
    }

    pub fn get_state(&self) -> ContextState {
        ContextState::try_from(unsafe { ffi::pa_context_get_state(self.raw_mut()) })
            .expect("pa_context_get_state returned invalid ContextState")
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn connect<'a, OPT>(
        &self,
        server: OPT,
        flags: ContextFlags,
        api: *const ffi::pa_spawn_api,
    ) -> Result<()>
    where
        OPT: Into<Option<&'a CStr>>,
    {
        let r = unsafe {
            ffi::pa_context_connect(
                self.raw_mut(),
                server.into().unwrap_cstr(),
                flags.into(),
                api,
            )
        };
        error_result!((), r)
    }

    pub fn disconnect(&self) {
        unsafe {
            ffi::pa_context_disconnect(self.raw_mut());
        }
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn drain<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
    where
        CB: Fn(&Context, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(c: *mut ffi::pa_context, userdata: *mut c_void)
        where
            F: Fn(&Context, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata)
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn rttime_new<CB>(
        &self,
        usec: USec,
        _: CB,
        userdata: *mut c_void,
    ) -> *mut ffi::pa_time_event
    where
        CB: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            a: *mut ffi::pa_mainloop_api,
            e: *mut ffi::pa_time_event,
            tv: *const TimeVal,
            userdata: *mut c_void,
        ) where
            F: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void),
        {
            let api = mainloop_api::from_raw_ptr(a);
            let timeval = &*tv;
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&api, e, timeval, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(api);
        }

        unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::<CB>), userdata) }
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn get_server_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
    where
        CB: Fn(&Context, Option<&ServerInfo>, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            i: *const ffi::pa_server_info,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, Option<&ServerInfo>, *mut c_void),
        {
            let info = if i.is_null() { None } else { Some(&*i) };
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, info, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata)
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn get_sink_info_by_name<'str, CS, CB>(
        &self,
        name: CS,
        _: CB,
        userdata: *mut c_void,
    ) -> Result<Operation>
    where
        CB: Fn(&Context, *const SinkInfo, i32, *mut c_void),
        CS: Into<Option<&'str CStr>>,
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            info: *const ffi::pa_sink_info,
            eol: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, *const SinkInfo, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, info, eol, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_get_sink_info_by_name(
                self.raw_mut(),
                name.into().unwrap_cstr(),
                Some(wrapped::<CB>),
                userdata
            )
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn get_sink_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
    where
        CB: Fn(&Context, *const SinkInfo, i32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            info: *const ffi::pa_sink_info,
            eol: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, *const SinkInfo, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, info, eol, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata)
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn get_sink_input_info<CB>(
        &self,
        idx: u32,
        _: CB,
        userdata: *mut c_void,
    ) -> Result<Operation>
    where
        CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            info: *const ffi::pa_sink_input_info,
            eol: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, *const SinkInputInfo, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, info, eol, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata)
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn get_source_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
    where
        CB: Fn(&Context, *const SourceInfo, i32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            info: *const ffi::pa_source_info,
            eol: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, *const SourceInfo, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, info, eol, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata)
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn set_sink_input_volume<CB>(
        &self,
        idx: u32,
        volume: &CVolume,
        _: CB,
        userdata: *mut c_void,
    ) -> Result<Operation>
    where
        CB: Fn(&Context, i32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            success: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, success, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_set_sink_input_volume(
                self.raw_mut(),
                idx,
                volume,
                Some(wrapped::<CB>),
                userdata
            )
        )
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn subscribe<CB>(
        &self,
        m: SubscriptionMask,
        _: CB,
        userdata: *mut c_void,
    ) -> Result<Operation>
    where
        CB: Fn(&Context, i32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            success: c_int,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, i32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, success, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        op_or_err!(
            self,
            ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), userdata)
        )
    }

    pub fn clear_subscribe_callback(&self) {
        unsafe {
            ffi::pa_context_set_subscribe_callback(self.raw_mut(), None, ptr::null_mut());
        }
    }

    #[allow(clippy::not_unsafe_ptr_arg_deref)]
    pub fn set_subscribe_callback<CB>(&self, _: CB, userdata: *mut c_void)
    where
        CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void),
    {
        assert_eq!(::std::mem::size_of::<CB>(), 0);

        // See: A note about `wrapped` functions
        unsafe extern "C" fn wrapped<F>(
            c: *mut ffi::pa_context,
            t: ffi::pa_subscription_event_type_t,
            idx: u32,
            userdata: *mut c_void,
        ) where
            F: Fn(&Context, SubscriptionEvent, u32, *mut c_void),
        {
            let ctx = context::from_raw_ptr(c);
            let event = SubscriptionEvent::try_from(t)
                .expect("pa_context_subscribe_cb_t passed invalid pa_subscription_event_type_t");
            let cb = MaybeUninit::<F>::uninit();
            (*cb.as_ptr())(&ctx, event, idx, userdata);
            #[allow(clippy::forget_non_drop)]
            forget(ctx);
        }

        unsafe {
            ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::<CB>), userdata);
        }
    }
}

#[doc(hidden)]
pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_context) -> Context {
    Context(ptr)
}

Messung V0.5 in Prozent
C=78 H=92 G=84

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.