Skip to main content

AudioCapture

Struct AudioCapture 

Source
pub(crate) struct AudioCapture {
    pub(crate) shared: Arc<Shared>,
}
Expand description

Python-facing capture handle. Owns the Shared lifecycle state and exposes start_capture / stop_capture / update_audio_bitrate / is_capturing to Python.

Fields§

§shared: Arc<Shared>

Implementations§

Source§

impl AudioCapture

Source

pub(crate) fn inner(&self) -> &Arc<Inner>

Source§

impl AudioCapture

Source

pub(crate) fn new() -> Self

Source

pub(crate) fn start_capture( &self, py: Python<'_>, settings: &Bound<'_, PyAny>, callback: Py<PyAny>, ) -> PyResult<()>

Start (or restart) audio capture, delivering encoded frames to callback.

  1. Re-entrancy guard: if called on one of the run’s own threads — the delivery thread (where the Python callback actually executes) or the capture thread — it cannot join/recreate the run it is part of (the capture thread joins the delivery thread on teardown, so a join from either closes a cycle), so it just undoes a nested SELF-stop and returns. That undo is a compare-exchange that clears the stop ONLY if this thread still owns it — if an external stop stored STOP_EXTERNAL meanwhile, the CAS fails and that stop stands (clearing it would strand its in-flight join forever).
  2. Spawn with the GIL released: spawn_worker stops/joins any prior thread and spawns the new one via py.detach, because the lifecycle lock and join() must not be held while holding the GIL — joining the capture thread transitively joins the delivery thread, whose in-flight callback needs the GIL, so that would deadlock. The stop/clear ordering (the lost-stop invariant) lives in spawn_worker.
  3. Register the handle for the atexit sweep (best-effort), pruning dead weaks.
  4. Startup handshake (await_start): waits up to ~2 s (GIL released) for the thread to publish RUNNING or FAILED, returning Ok while it is still STARTING — the retry ladder can run longer than the window, so a later failure is observed through state / last_error. On FAILED, join_failed_start tears down ONLY the thread this call spawned (identity-checked) — a concurrent start may already own the slot with a live run that must survive — and last_error is raised.
Source

pub(crate) fn stop_capture(&self, py: Python<'_>)

Stop audio capture, joining the capture thread.

A re-entrant stop from one of the run’s own threads — the delivery thread (where the Python callback executes) or the capture thread — only records a self-stop: a join from inside the run would cycle (the capture thread joins the delivery thread on teardown). It must not clobber an external stop already in effect, which has to win the join. Otherwise it takes the lifecycle lock and joins with the GIL released (via py.detach): joining the capture thread transitively joins the delivery thread, whose in-flight callback needs the GIL, so holding it would deadlock. The authoritative external stop is set INSIDE the lock immediately before the join, so it wins over any concurrent self-stop.

Source

pub(crate) fn update_audio_bitrate(&self, bps: i32)

Set the live Opus target bitrate (bits/s) via the atomic mirror; the capture loop applies it on the next frame, without a restart. Values are clamped to the valid Opus range so an out-of-range request can never wedge the encoder.

Source

pub(crate) fn is_capturing(&self) -> bool

True while a capture worker is connected and running with no stop pending; false while still starting and after a failure — see state to tell those apart.

Source

pub(crate) fn state(&self) -> &'static str

Lifecycle phase: "idle", "starting", "running" or "failed". A run that fails after start_capture returned (its retry ladder gave up, or a mid-run reconnect budget was spent) reads "failed" with the reason in last_error.

Source

pub(crate) fn last_error(&self) -> Option<String>

Why the last run failed, or None while no run has failed since the last start.

Trait Implementations§

Source§

impl DerefToPyAny for AudioCapture

Source§

impl Drop for AudioCapture

Source§

fn drop(&mut self)

Best-effort stop on GC/dealloc: the re-entrant case (running on the run’s own delivery or capture thread) records a self-stop only (never clobbering a pending external stop); otherwise it takes the lifecycle lock and joins the capture thread with the GIL released, matching stop_capture.

Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl ExtractPyClassWithClone for AudioCapture

Source§

impl<'py> IntoPyObject<'py> for AudioCapture

Source§

type Target = AudioCapture

The Python output type
Source§

type Output = Bound<'py, <AudioCapture as IntoPyObject<'py>>::Target>

The smart pointer type to use. Read more
Source§

type Error = PyErr

The type returned in the event of a conversion error.
Source§

fn into_pyobject( self, py: Python<'py>, ) -> Result<<Self as IntoPyObject<'_>>::Output, <Self as IntoPyObject<'_>>::Error>

Performs the conversion.
Source§

impl PyClass for AudioCapture

Source§

const NAME: &str = "AudioCapture"

Name of the class. Read more
Source§

type Frozen = False

Whether the pyclass is frozen. Read more
Source§

impl PyClassImpl for AudioCapture

Source§

const MODULE: Option<&str> = ::core::option::Option::None

Module which the class will be associated with. Read more
Source§

const IS_BASETYPE: bool = false

#[pyclass(subclass)]
Source§

const IS_SUBCLASS: bool = false

#[pyclass(extends=…)]
Source§

const IS_MAPPING: bool = false

#[pyclass(mapping)]
Source§

const IS_SEQUENCE: bool = false

#[pyclass(sequence)]
Source§

const IS_IMMUTABLE_TYPE: bool = false

#[pyclass(immutable_type)]
Source§

const RAW_DOC: &'static CStr = c"Python-facing capture handle. Owns the `Shared` lifecycle state and exposes\n`start_capture` / `stop_capture` / `update_audio_bitrate` / `is_capturing` to Python.\x00"

Docstring for the class provided on the struct or enum. Read more
Source§

const DOC: &'static CStr

Fully rendered class doc, including the text_signature if a constructor is defined. Read more
Source§

type Layout = <<AudioCapture as PyClassImpl>::BaseNativeType as PyClassBaseType>::Layout<AudioCapture>

Description of how this class is laid out in memory
Source§

type BaseType = PyAny

Base class
Source§

type ThreadChecker = NoopThreadChecker

This handles following two situations: Read more
Source§

type PyClassMutability = <<PyAny as PyClassBaseType>::PyClassMutability as PyClassMutability>::MutableChild

Immutable or mutable
Source§

type Dict = PyClassDummySlot

Specify this class has #[pyclass(dict)] or not.
Source§

type WeakRef = PyClassDummySlot

Specify this class has #[pyclass(weakref)] or not.
Source§

type BaseNativeType = PyAny

The closest native ancestor. This is PyAny by default, and when you declare #[pyclass(extends=PyDict)], it’s PyDict.
Source§

fn items_iter() -> PyClassItemsIter

Source§

fn lazy_type_object() -> &'static LazyTypeObject<Self>

§

fn dict_offset() -> Option<PyObjectOffset>

Used to provide the dictoffset slot (equivalent to tp_dictoffset)
§

fn weaklist_offset() -> Option<PyObjectOffset>

Used to provide the weaklistoffset slot (equivalent to tp_weaklistoffset
Source§

impl PyClassNewTextSignature for AudioCapture

Source§

const TEXT_SIGNATURE: &'static str = "()"

Source§

impl PyMethods<AudioCapture> for PyClassImplCollector<AudioCapture>

Source§

fn py_methods(self) -> &'static PyClassItems

Source§

impl PyTypeInfo for AudioCapture

Source§

const NAME: &str = <Self as ::pyo3::PyClass>::NAME

👎Deprecated since 0.28.0:

prefer using ::type_object(py).name() to get the correct runtime value

Class name.
Source§

const MODULE: Option<&str> = <Self as ::pyo3::impl_::pyclass::PyClassImpl>::MODULE

👎Deprecated since 0.28.0:

prefer using ::type_object(py).module() to get the correct runtime value

Module name, if any.
Source§

fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject

Returns the PyTypeObject instance for this type.
§

fn type_object(py: Python<'_>) -> Bound<'_, PyType>

Returns the safe abstraction over the type object.
§

fn is_type_of(object: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of this type or a subclass of this type.
§

fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of this type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<'py, T> IntoPyObjectExt<'py> for T
where T: IntoPyObject<'py>,

§

fn into_bound_py_any(self, py: Python<'py>) -> Result<Bound<'py, PyAny>, PyErr>

Converts self into an owned Python object, dropping type information.
§

fn into_py_any(self, py: Python<'py>) -> Result<Py<PyAny>, PyErr>

Converts self into an owned Python object, dropping type information and unbinding it from the 'py lifetime.
§

fn into_pyobject_or_pyerr(self, py: Python<'py>) -> Result<Self::Output, PyErr>

Converts self into a Python object. Read more
§

impl<T> PyErrArguments for T
where T: for<'py> IntoPyObject<'py> + Send + Sync,

§

fn arguments(self, py: Python<'_>) -> Py<PyAny>

Arguments for exception
§

impl<T> PyTypeCheck for T
where T: PyTypeInfo,

§

fn type_check(object: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of Self, which may include a subtype. Read more
§

fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>

Returns the expected type as a possible argument for the isinstance and issubclass function. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Ungil for T
where T: Send,