Skip to main content

Sender

Struct Sender 

Source
pub struct Sender { /* private fields */ }

Implementations§

Source§

impl Sender

Source

pub fn new(ndi: &NDI, create_settings: &SenderOptions) -> Result<Self>

Creates a new NDI send instance.

§Errors

Returns an error if:

  • The sender name contains a null byte
  • The groups string contains a null byte
  • NDI fails to create the send instance
Source

pub fn send_video(&self, video_frame: &VideoFrame)

Send a video frame synchronously.

The SDK has released the input buffer when this returns; the caller may then reuse or release it. This also completes a previous async video send.

Source

pub fn send_video_async(&mut self, frame: VideoFrame) -> Option<VideoFrame>

Submit an owned frame without copying its pixel or metadata allocations.

The sender takes ownership before calling the SDK. The next async send synchronizes the previous send and returns its owned frame for reuse. The first send returns None. Owned and copied submissions share this recovery behavior. Call Self::finish_video_async to recover the final frame.

Synchronous sends and explicit flushes complete the operation but retain the owned frame for recovery by the next async send or finish call. No SDK completion callback is registered, including with Advanced SDK. If a Rust completion handler panics, the new frame remains retained and the synchronized previous frame is dropped rather than returned.

Source

pub fn finish_video_async(&mut self) -> Option<VideoFrame>

Drain the SDK and return the final owned frame, if any.

Frames submitted through either owned or copied sending are returned. Repeated calls return None and do not repeat completion notifications. If the completion handler panics, the completed frame is dropped instead of returned.

Source

pub fn send_video_async_copy( &mut self, frame: &BorrowedVideoFrame<'_>, ) -> Result<Option<VideoFrame>>

Copy borrowed pixels and metadata, then submit the owned copy asynchronously.

This uses the same pipeline as Self::send_video_async, returning the previous completed frame whether it was submitted by ownership or copying. The caller may immediately reuse or release the source buffer and metadata. Recover the final copy with Self::finish_video_async.

§Errors

Returns an error if the borrowed frame cannot be represented as a supported owned video layout. No pending send is changed when validation fails.

Source

pub fn send_audio(&self, audio_frame: &AudioFrame)

Sends an audio frame synchronously.

The SDK has released the input buffer when this returns, so the caller may then reuse or release it. This calls NDIlib_send_send_audio_v3.

See the NDI SDK documentation section on NDIlib_send_send_audio_v3 for more details.

§Example
let mut audio_buffer = vec![0.0f32; 48000 * 2]; // 1 second of stereo audio

// Fill buffer with audio data...
let frame = AudioFrame::builder()
    .sample_rate(48000)
    .channels(2)
    .samples(48000)
    .data(audio_buffer.clone())
    .build()?;
sender.send_audio(&frame);

// Buffer can be reused immediately
audio_buffer.fill(0.5);
let frame2 = AudioFrame::builder()
    .sample_rate(48000)
    .channels(2)
    .samples(48000)
    .data(audio_buffer)
    .build()?;
sender.send_audio(&frame2);
Source

pub fn send_metadata(&self, metadata_frame: &MetadataFrame)

Sends a metadata frame.

Source

pub fn tally(&self, timeout: Duration) -> Result<Option<Tally>>

Get the current tally state for this sender.

§Arguments
  • timeout - Maximum time to wait for tally information. Must not exceed crate::MAX_TIMEOUT (~49.7 days).
§Returns

Ok(Some(tally)) if tally was successfully retrieved, Ok(None) on timeout.

§Errors

Returns Error::InvalidConfiguration if timeout exceeds crate::MAX_TIMEOUT.

§Examples
let ndi = NDI::new()?;
let options = SenderOptions::builder("Test Sender").build();
let sender = grafton_ndi::Sender::new(&ndi, &options)?;

// Try to get tally with 1 second timeout
if let Some(tally) = sender.tally(Duration::from_secs(1))? {
    println!("On program: {}, On preview: {}", tally.on_program, tally.on_preview);
} else {
    println!("Tally request timed out");
}
Source

pub fn connection_count(&self, timeout: Duration) -> Result<u32>

Get the number of active connections to this sender.

§Arguments
  • timeout - Maximum time to wait for connection count. Must not exceed crate::MAX_TIMEOUT (~49.7 days).
§Returns

Number of active connections as a u32.

§Errors

Returns Error::Timeout if the SDK returns a negative value (indicating timeout or error). Returns Error::InvalidConfiguration if timeout exceeds crate::MAX_TIMEOUT.

§Examples
let ndi = NDI::new()?;
let options = SenderOptions::builder("Test Sender").build();
let sender = grafton_ndi::Sender::new(&ndi, &options)?;

// Get connection count with 1 second timeout
let count = sender.connection_count(Duration::from_secs(1))?;
println!("Active connections: {}", count);
Source

pub fn clear_connection_metadata(&self)

Source

pub fn add_connection_metadata(&self, metadata_frame: &MetadataFrame)

Adds connection metadata.

Source

pub fn set_failover(&self, source: &Source) -> Result<()>

Sets failover source.

§Errors

Returns an error if source conversion fails.

Source

pub fn clear_failover(&self)

Clear the failover source previously configured with Self::set_failover.

Source

pub fn source(&self) -> Result<Source>

Get the source information for this sender.

§Errors

Returns Error::NullPointer if the NDI SDK returns a null pointer or if the source data contains null pointers.

§Examples
let ndi = NDI::new()?;
let options = SenderOptions::builder("Test Sender").build();
let sender = grafton_ndi::Sender::new(&ndi, &options)?;
let source = sender.source()?;
println!("Sender source: {source}");
Source

pub fn on_async_video_done<F>(&mut self, handler: F)
where F: Fn(usize) + Send + Sync + 'static,

Replace the completion handler receiving the submitted pixel-buffer length.

It runs on the calling thread after SDK synchronization, outside internal locks, at most once per submitted frame. Completion is observed by the next video send, flush, finish, or sender destruction. Owned and copied sends share this handler. State is updated before invocation, so panic or reentry cannot repeat a notification. If sender destruction runs during unwinding, a handler panic is suppressed to avoid a second panic.

Replaces the previous handler. The current handler observes completion of a frame still in flight, including one submitted before registration. Frames completed before registration are not notified retroactively.

Source

pub fn clear_async_video_done(&mut self)

Remove the completion handler. Pending frame ownership is unchanged.

Source

pub fn flush_async_blocking(&self)

Flush pending async video operations synchronously.

Sends a true NULL video frame pointer to the SDK, blocking until all pending async video operations are complete.

After this returns, the SDK has released the pending buffer. The sender retains the frame; use Self::finish_video_async or the next async submission to recover it without copying.

Trait Implementations§

Source§

impl Debug for Sender

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Send for Sender

§Safety

The NDI 6 SDK documentation specifically marks these send functions as thread-safe:

  • NDIlib_send_send_video_v2 and NDIlib_send_send_video_async_v2
  • NDIlib_send_send_audio_v3 (no async variant exists)
  • NDIlib_send_send_metadata (no async variant exists)
  • NDIlib_send_get_tally
  • NDIlib_send_get_no_connections

Inner holds an opaque NDI pointer and owned CStrings that are automatically freed in Drop, making it safe to move between threads.

Ownership prevents destruction while SDK calls still borrow the sender; creation and destruction may occur on different threads.

Source§

impl Sync for Sender

§Safety

The NDI 6 SDK guarantees that multiple threads can safely call send methods concurrently. The SDK uses internal synchronization for:

  • Video sending (both sync and async)
  • Audio sending (sync only)
  • Metadata sending
  • Status queries (tally, connections)

Video ownership and synchronizing SDK calls are serialized by the mutex. Exclusive ownership prevents concurrent instance destruction.

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.

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.