pub struct Sender { /* private fields */ }Implementations§
Source§impl Sender
impl Sender
Sourcepub fn new(ndi: &NDI, create_settings: &SenderOptions) -> Result<Self>
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
Sourcepub fn send_video(&self, video_frame: &VideoFrame)
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.
Sourcepub fn send_video_async(&mut self, frame: VideoFrame) -> Option<VideoFrame>
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.
Sourcepub fn finish_video_async(&mut self) -> Option<VideoFrame>
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.
Sourcepub fn send_video_async_copy(
&mut self,
frame: &BorrowedVideoFrame<'_>,
) -> Result<Option<VideoFrame>>
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.
Sourcepub fn send_audio(&self, audio_frame: &AudioFrame)
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);Sourcepub fn send_metadata(&self, metadata_frame: &MetadataFrame)
pub fn send_metadata(&self, metadata_frame: &MetadataFrame)
Sends a metadata frame.
Sourcepub fn tally(&self, timeout: Duration) -> Result<Option<Tally>>
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 exceedcrate::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");
}Sourcepub fn connection_count(&self, timeout: Duration) -> Result<u32>
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 exceedcrate::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);pub fn clear_connection_metadata(&self)
Sourcepub fn add_connection_metadata(&self, metadata_frame: &MetadataFrame)
pub fn add_connection_metadata(&self, metadata_frame: &MetadataFrame)
Adds connection metadata.
Sourcepub fn set_failover(&self, source: &Source) -> Result<()>
pub fn set_failover(&self, source: &Source) -> Result<()>
Sourcepub fn clear_failover(&self)
pub fn clear_failover(&self)
Clear the failover source previously configured with Self::set_failover.
Sourcepub fn source(&self) -> Result<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}");Sourcepub fn on_async_video_done<F>(&mut self, handler: F)
pub fn on_async_video_done<F>(&mut self, handler: F)
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.
Sourcepub fn clear_async_video_done(&mut self)
pub fn clear_async_video_done(&mut self)
Remove the completion handler. Pending frame ownership is unchanged.
Sourcepub fn flush_async_blocking(&self)
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§
impl Send for Sender
§Safety
The NDI 6 SDK documentation specifically marks these send functions as thread-safe:
NDIlib_send_send_video_v2andNDIlib_send_send_video_async_v2NDIlib_send_send_audio_v3(no async variant exists)NDIlib_send_send_metadata(no async variant exists)NDIlib_send_get_tallyNDIlib_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.
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.