### Example: Initializing VecCapturer in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.VecCapturer Demonstrates how to initialize a `VecCapturer` by first obtaining a `Monitor` object and then converting it into a `VecCapturer`. This is a common starting point for screen capture operations. ```rust use rusty_duplication::{Scanner, VecCapturer}; let monitor = Scanner::new().unwrap().next().unwrap(); let mut capturer: VecCapturer = monitor.try_into().unwrap(); ``` -------------------------------- ### Example Usage of Scanner for Monitor Discovery - Rust Source: https://docs.rs/rusty-duplication/latest/src/rusty_duplication/scanner.rs_search= This example demonstrates how to use the `Scanner` to find available monitors. It creates a new scanner instance and then calls `next()` to retrieve the first available monitor. This is a basic usage pattern for initiating screen capture or duplication. ```Rust use rusty_duplication::Scanner; // create a new scanner let mut scanner = Scanner::new().unwrap(); // get the next available monitor let ctx = scanner.next().unwrap(); ``` -------------------------------- ### Example Usage of VecCapturer in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.VecCapturer_search= This example demonstrates how to initialize and use the VecCapturer. It involves creating a Scanner to find available monitors, selecting one, and then converting it into a VecCapturer instance. This sets up the capturer to store screen data in a Vec. ```rust use rusty_duplication::{Scanner, VecCapturer}; let monitor = Scanner::new().unwrap().next().unwrap(); let mut capturer: VecCapturer = monitor.try_into().unwrap(); ``` -------------------------------- ### Initialize Scanner and Get Monitor Contexts (Rust) Source: https://docs.rs/rusty-duplication/latest/src/rusty_duplication/scanner.rs_search=std%3A%3Avec This code demonstrates how to initialize a Scanner object, which is used to iterate over available monitors for screen capturing. It utilizes Windows DirectX APIs to create a device and factory, then provides an example of how to retrieve the next available monitor context. ```rust use crate::{Error, Monitor, Result}; use std::ptr::null_mut; use windows::core::Interface; use windows::Win32::Graphics::Direct3D11::* use windows::Win32::Graphics::Dxgi::*; // ... (Scanner struct definition and impl Scanner block) ... /// Scan for [`Monitor`]s. /// # Examples /// ``` /// use rusty_duplication::Scanner; /// /// // create a new scanner /// let mut scanner = Scanner::new().unwrap(); /// // get the next available monitor /// let ctx = scanner.next().unwrap(); /// ``` #[derive(Debug, Clone)] pub struct Scanner { next_adapter_index: u32, next_output_index: u32, factory: IDXGIFactory1, adapter: IDXGIAdapter1, device: ID3D11Device, device_context: ID3D11DeviceContext, } impl Scanner { /// Try to create a new scanner. /// Return [`Err`] if no adapter is found. pub fn new() -> Result { let factory = unsafe { CreateDXGIFactory1::() } .map_err(Error::from_win_err(stringify!(CreateDXGIFactory1)))?; let adapter_index = 0; let (adapter, device, device_context) = get_adapter(&factory, adapter_index)?; Ok(Self { next_adapter_index: adapter_index + 1, next_output_index: 0, factory, adapter, device, device_context, }) } fn get_current_ctx(&mut self) -> Option { let output_index = self.next_output_index; self.next_output_index += 1; // TODO: add debug log for Result::ok() let output = unsafe { self.adapter.EnumOutputs(output_index) }.ok()?; let output = output.cast::().unwrap(); let output_duplication = unsafe { output.DuplicateOutput(&self.device) }.ok()?; Some(Monitor::new( self.device.clone(), self.device_context.clone(), output, output_duplication, )) } } impl Iterator for Scanner { type Item = Monitor; fn next(&mut self) -> Option { loop { if let Some(ctx) = self.get_current_ctx() { return Some(ctx); } // no more available outputs, try next adapter let adapter_index = self.next_adapter_index; self.next_adapter_index += 1; let Ok((adapter, device, device_context)) = get_adapter(&self.factory, adapter_index) else { break; }; self.adapter = adapter; self.device = device; self.device_context = device_context; self.next_output_index = 0; } None } } fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### Monitor Struct and Methods Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/struct.Monitor_search=std%3A%3Avec Documentation for the Monitor struct, including how to get monitor information, primary status, and DXGI descriptions. ```APIDOC ## Struct Monitor ### Description Monitor context for screen duplication. This is stateless and immutable. To create a new instance, use `Scanner`. ### Methods #### `monitor_info(&self) -> Result` ##### Description This is usually used to check if the monitor is primary. ##### Examples ```rust use rusty_duplication::{Scanner, MonitorInfoExt}; let monitor = Scanner::new().unwrap().next().unwrap(); monitor.monitor_info().unwrap().is_primary(); ``` #### `dxgi_output_desc(&self) -> Result` ##### Description This is usually used to get the screen’s position and size. ##### Examples ```rust use rusty_duplication::{Scanner, OutputDescExt}; let monitor = Scanner::new().unwrap().next().unwrap(); let desc = monitor.dxgi_output_desc().unwrap(); println!("{}x{{}}", desc.width(), desc.height()); ``` #### `dxgi_outdupl_desc(&self) -> DXGI_OUTDUPL_DESC` ##### Description This is usually used to get the screen’s pixel width/height and buffer size. ``` -------------------------------- ### Rust: Define and Initialize Scanner Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/struct.Scanner Demonstrates the definition of the Scanner struct and provides an example of how to create a new instance. The `Scanner::new()` function returns a `Result`, indicating potential errors if no adapter is found. ```rust pub struct Scanner { /* private fields */ } use rusty_duplication::Scanner; // create a new scanner let mut scanner = Scanner::new().unwrap(); ``` -------------------------------- ### Create and Use Scanner in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search= Demonstrates how to instantiate a new Scanner and retrieve the next available monitor. This involves creating a mutable scanner instance and calling the `next()` method to get the monitor context. ```rust use rusty_duplication::Scanner; // create a new scanner let mut scanner = Scanner::new().unwrap(); // get the next available monitor let ctx = scanner.next().unwrap(); ``` -------------------------------- ### Get DXGI Output Description in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Monitor_search= Retrieves the DXGI output description for a monitor, which includes the screen's position and size. This allows for programmatic access to screen dimensions. ```rust use rusty_duplication::{Scanner, OutputDescExt}; let monitor = Scanner::new().unwrap().next().unwrap(); let desc = monitor.dxgi_output_desc().unwrap(); println!("{}x{}", desc.width(), desc.height()); ``` -------------------------------- ### Get DXGI Output Description (Rust) Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/struct.Monitor_search=u32+-%3E+bool Obtains the DXGI output description for a monitor, which includes the screen's position and size. This function returns a Result containing DXGI_OUTPUT_DESC. ```rust use rusty_duplication::{Scanner, OutputDescExt}; let monitor = Scanner::new().unwrap().next().unwrap(); let desc = monitor.dxgi_output_desc().unwrap(); println!("{}x বিশুদ্ধ", desc.width(), desc.height()); ``` -------------------------------- ### Get Screen Position and Size in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Monitor Obtains the screen's position and size using DXGI output descriptions. This method returns a Result containing DXGI_OUTPUT_DESC or an error. ```rust pub fn dxgi_output_desc(&self) -> Result ``` -------------------------------- ### Get Type ID of a Value (Rust) Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Gets the TypeId of `self`, which can be used for runtime type reflection. This is part of the 'Any' trait implementation. ```rust fn type_id(&self) -> TypeId { // Implementation details would go here unimplemented!() } ``` -------------------------------- ### TryFrom for VecCapturer Implementation Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/type.VecCapturer_search=u32+-%3E+bool Details on how to convert a Monitor into a VecCapturer. ```APIDOC ### impl TryFrom for VecCapturer #### `type Error = Error` Indicates the type returned in the event of a conversion error. #### `fn try_from(monitor: Monitor) -> Result` Performs the conversion from a `Monitor` to a `VecCapturer`. ``` -------------------------------- ### Get Type ID for Any Type in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Monitor_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Implements the Any trait for generic types, providing a way to get the `TypeId` of a value. This is useful for dynamic type introspection and downcasting. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Initialize DXGI Factory, Adapter, and D3D11 Device in Rust Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs_search=std%3A%3Avec This Rust code snippet shows the process of creating a DXGI factory, enumerating adapters, and then creating a Direct3D 11 device and device context associated with a specific adapter. It utilizes Windows API functions like `CreateDXGIFactory1` and `D3D11CreateDevice`. Errors during these operations are mapped to a custom `Error` type. ```rust use crate::{Error, Result}; use std::ptr::null_mut; use windows::{ core::Interface, Win32::Graphics::Direct3D11::*, Win32::Graphics::Dxgi::*, Win32::Foundation::HMODULE }; fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### VecCapturer Initialization and Usage Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.VecCapturer Demonstrates how to initialize VecCapturer from a Monitor and perform screen captures. ```APIDOC ## Type Alias: VecCapturer ### Description `VecCapturer` is a type alias for `Capturer>`, designed to capture screen content into a byte vector. ### Method Type Alias ### Endpoint N/A ### Request Body N/A ### Response N/A ### Examples ```rust use rusty_duplication::{Scanner, VecCapturer}; let monitor = Scanner::new().unwrap().next().unwrap(); let mut capturer: VecCaptiner = monitor.try_into().unwrap(); ``` ## Struct: VecCapturer ### Description Represents a screen capturer that stores captured frames in a `Vec`. ### Fields - **pointer_shape_buffer** (`Vec`) - Stores the pointer shape data if updated. - **buffer** (`Vec`) - The main buffer to store the captured frame data in BGRA32 format. - **timeout_ms** (`u32`) - Timeout in milliseconds for capturing the next frame. Defaults to 300ms. ## Implementations: Capturer ### `new(monitor: Monitor, buffer_factory: impl FnOnce(usize) -> Result) -> Result` #### Description Creates a new capturer instance associated with a specific monitor. It uses a provided `buffer_factory` closure to create the underlying buffer, which takes the required buffer size in bytes as an argument. #### Parameters - **monitor** (`Monitor`) - The monitor to capture from. - **buffer_factory** (`impl FnOnce(usize) -> Result`) - A closure that creates the buffer for storing captured frames. #### Returns - `Result` - A new `Capturer` instance on success, or an error. ### `monitor(&self) -> &Monitor` #### Description Returns a reference to the `Monitor` associated with this capturer. #### Returns - `&Monitor` - A reference to the monitor. ### `check_buffer(&self) -> Result<()>` #### Description Ensures that the internal buffer (`Self::buffer`) is sufficiently large to hold the next captured frame. This is crucial for preventing buffer overflows. #### Returns - `Result<()>` - Ok(()) if the buffer is large enough, or an error otherwise. ### `capture_unchecked(&mut self) -> Result` #### Description Captures the screen content without performing a size check on the buffer. The captured pixel data is stored in `Self::buffer`. This method is marked as `unsafe` because the caller must guarantee that `Self::buffer` is large enough. #### Safety The caller must ensure `Self::buffer` is large enough to hold the frame. `Self::check_buffer` can be used for validation. #### Returns - `Result` - Frame information on success, or an error. The pixel data is in `Self::buffer`. ### `capture(&mut self) -> Result` #### Description Captures the screen content. This method first calls `Self::check_buffer` to ensure the buffer is adequately sized before proceeding with the capture. The pixel data is stored in `Self::buffer`. #### Returns - `Result` - Frame information on success, or an error. The pixel data is in `Self::buffer`. ### `capture_with_pointer_shape_unchecked(&mut self) -> Result<(DXGI_OUTDUPL_FRAME_INFO, Option` #### Description Captures the screen content and its pointer shape without a buffer size check. Pixel data goes into `Self::buffer`, and pointer shape data (if updated) goes into `Self::pointer_shape_buffer`. Marked `unsafe` as the caller must ensure buffer sizes. #### Safety The caller must ensure `Self::buffer` is large enough to hold the frame. `Self::check_buffer` can be used for validation. #### Returns - `Result<(DXGI_OUTDUPL_FRAME_INFO, Option)>` - Frame info and optional pointer shape info on success, or an error. ### `capture_with_pointer_shape(&mut self) -> Result<(DXGI_OUTDUPL_FRAME_INFO, Option)>` #### Description Captures the screen content and its pointer shape. This method first checks the buffer size using `Self::check_buffer`. Pixel data is stored in `Self::buffer`, and updated pointer shape information is stored in `Self::pointer_shape_buffer`. #### Returns - `Result<(DXGI_OUTDUPL_FRAME_INFO, Option)>` - Frame info and optional pointer shape info on success, or an error. ## Trait Implementation: `TryFrom for VecCapturer` ### Description Allows conversion from a `Monitor` type into a `VecCapturer` instance. ### Method `try_from` ### Endpoint N/A ### Parameters - **monitor** (`Monitor`) - The source monitor to convert. ### Returns - `Result` - A `VecCapturer` instance on success, or an `Error` on failure. ## Trait Implementation: `Clone for Capturer` ### Description Provides cloning capabilities for `Capturer` instances where the `Buffer` type also implements `Clone`. ### Method `clone`, `clone_from` ### Endpoint N/A ### Parameters - **source** (`&Self`) - The capturer instance to clone from. ### Returns - `Capturer` - A cloned instance of the capturer. ## Trait Implementation: `Debug for Capturer` ### Description Enables debug formatting for `Capturer` instances where the `Buffer` type implements `Debug`. ### Method `fmt` ### Endpoint N/A ### Parameters - **f** (`&mut Formatter<'_>`) - The formatter to use. ### Returns - `Result<()>` - The result of the formatting operation. ``` -------------------------------- ### Initialize Direct3D Device and Context (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs_search=u32+-%3E+bool Initializes a Direct3D 11 device and device context for a given DXGI adapter. This function is crucial for enabling screen capture functionalities. It uses the D3D11CreateDevice API from the Windows crate. ```rust use crate::{Error, Result}; use std::ptr::null_mut; use windows::Win32::Graphics::Direct3D11::* use windows::Win32::Graphics::Dxgi::IDXGIAdapter1; use windows::Win32::Foundation::HMODULE; fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### By Reference Iterator Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=u32+-%3E+bool Provides a way to get a mutable reference to the iterator itself. ```APIDOC ## Iterator Adapters: By Reference ### `by_ref(&mut self)` **Description**: Creates a reference adapter for the iterator, allowing methods to be called on `&mut Self`. **Method**: `by_ref` **Parameters**: None. ### Request Example ```json { "example": "No request body applicable for this iterator adapter." } ``` ### Response #### Success Response (Iterator Reference) - **&mut Self** - A mutable reference to the iterator itself. ``` -------------------------------- ### Create and Use Scanner for Monitors (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs_search= Demonstrates how to create a Scanner to find available display monitors. It initializes DirectX devices and factories to enumerate adapters and outputs. The scanner iterates through monitors, returning a `Monitor` context for each. ```Rust use crate::{Error, Monitor, Result}; use std::ptr::null_mut; use windows::core::Interface; use windows::Win32::Foundation::HMODULE; use windows::Win32::Graphics::Direct3D::D3D_DRIVER_TYPE_UNKNOWN; use windows::Win32::Graphics::Direct3D11::* use windows::Win32::Graphics::Dxgi::*; /// Scan for [`Monitor`]s. /// # Examples /// ``` /// use rusty_duplication::Scanner; /// /// // create a new scanner /// let mut scanner = Scanner::new().unwrap(); /// // get the next available monitor /// let ctx = scanner.next().unwrap(); /// ``` #[derive(Debug, Clone)] pub struct Scanner { next_adapter_index: u32, next_output_index: u32, factory: IDXGIFactory1, adapter: IDXGIAdapter1, device: ID3D11Device, device_context: ID3D11DeviceContext, } impl Scanner { /// Try to create a new scanner. /// Return [`Err`] if no adapter is found. pub fn new() -> Result { let factory = unsafe { CreateDXGIFactory1::() } .map_err(Error::from_win_err(stringify!(CreateDXGIFactory1)))?; let adapter_index = 0; let (adapter, device, device_context) = get_adapter(&factory, adapter_index)?; Ok(Self { next_adapter_index: adapter_index + 1, next_output_index: 0, factory, adapter, device, device_context, }) } fn get_current_ctx(&mut self) -> Option { let output_index = self.next_output_index; self.next_output_index += 1; // TODO: add debug log for Result::ok() let output = unsafe { self.adapter.EnumOutputs(output_index) }.ok()?; let output = output.cast::().unwrap(); let output_duplication = unsafe { output.DuplicateOutput(&self.device) }.ok()?; Some(Monitor::new( self.device.clone(), self.device_context.clone(), output, output_duplication, )) } } impl Iterator for Scanner { type Item = Monitor; fn next(&mut self) -> Option { loop { if let Some(ctx) = self.get_current_ctx() { return Some(ctx); } // no more available outputs, try next adapter let adapter_index = self.next_adapter_index; self.next_adapter_index += 1; let Ok((adapter, device, device_context)) = get_adapter(&self.factory, adapter_index) else { break; }; self.adapter = adapter; self.device = device; self.device_context = device_context; self.next_output_index = 0; } None } } fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } #[cfg(test)] mod tests { use super::*; use serial_test::serial; #[test] #[serial] fn manager() { let mut factory = Scanner::new().unwrap(); assert!(factory.next().is_some()); } } ``` -------------------------------- ### Get Last Scanner Item in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows the `last` method for the Scanner iterator, which consumes the iterator and returns the final item, if any. ```rust fn last(self) -> Option ``` -------------------------------- ### Create Iterator from Value (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=std%3A%3Avec Creates an iterator from a value that itself implements `Iterator`. This is the standard way to get an iterator from a collection or other iterable types. ```rust fn into_iter(self) -> I where I: Iterator ``` -------------------------------- ### Initialize Scanner for Monitor Discovery - Rust Source: https://docs.rs/rusty-duplication/latest/src/rusty_duplication/scanner.rs_search= This code initializes the `Scanner` struct, which is responsible for discovering available monitors on the system. It creates a DXGI factory and retrieves the first available adapter and its associated D3D11 device and context. This is the entry point for iterating through display outputs. ```Rust use crate::{Error, Monitor, Result}; use windows::Dxgi::IDXGIFactory1; // Assuming get_adapter is defined elsewhere in the crate // fn get_adapter(factory: &IDXGIFactory1, adapter_index: u32) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)>; #[derive(Debug, Clone)] pub struct Scanner { next_adapter_index: u32, next_output_index: u32, factory: IDXGIFactory1, adapter: IDXGIAdapter1, // Assuming IDXGIAdapter1 is correctly imported and used device: ID3D11Device, device_context: ID3D11DeviceContext, } impl Scanner { /// Try to create a new scanner. /// Return [`Err`] if no adapter is found. pub fn new() -> Result { let factory = unsafe { CreateDXGIFactory1::() } .map_err(Error::from_win_err(stringify!(CreateDXGIFactory1)))?; let adapter_index = 0; let (adapter, device, device_context) = get_adapter(&factory, adapter_index)?; Ok(Self { next_adapter_index: adapter_index + 1, next_output_index: 0, factory, adapter, device, device_context, }) } // ... other methods like get_current_ctx ... } ``` -------------------------------- ### Create DXGI Factory and Device (Rust) Source: https://docs.rs/rusty-duplication/latest/src/rusty_duplication/scanner.rs_search=std%3A%3Avec This snippet shows the core Windows DirectX initialization process. It creates a DXGI factory to enumerate adapters and then uses D3D11CreateDevice to create a Direct3D 11 device and device context associated with a specific adapter. Error handling is included for robustness. ```rust use crate::{Error, Result}; use std::ptr::null_mut; use windows::core::Interface; use windows::Win32::Foundation::HMODULE; use windows::Win32::Graphics::Direct3D::D3D_DRIVER_TYPE_UNKNOWN; use windows::Win32::Graphics::Direct3D11::*; use windows::Win32::Graphics::Dxgi::*; fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### Get Scanner Size Hint in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows the `size_hint` method for the Scanner iterator, returning the lower and upper bounds of the remaining elements. ```rust fn size_hint(&self) -> (usize, Option) ``` -------------------------------- ### Get Nth Scanner Item in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows the `nth` method for the Scanner iterator, which returns the nth element of the iterator after skipping the preceding elements. ```rust fn nth(&mut self, n: usize) -> Option ``` -------------------------------- ### Initialize Direct3D Device and Context (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Provides a function to create a Direct3D 11 device and device context from a DXGI adapter. This is a core utility for interacting with the graphics hardware on Windows. It utilizes `windows-sys` for low-level Win32 API calls, specifically `D3D11CreateDevice`. ```Rust use crate::{Error, Result}; use std::ptr::null_mut; use windows::Win32::Graphics::Direct3D11::*; use windows::Win32::Graphics::Dxgi::IDXGIAdapter1; use windows::core::Interface; fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### Get Next Scanner Chunk in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Illustrates the nightly-only experimental `next_chunk` method for Scanner, which returns an array of N items. This method is unstable. ```rust fn next_chunk( &mut self, ) -> Result<[Self::Item; N], IntoIter> ``` -------------------------------- ### Get Monitor Information in Rust Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/type.SharedMemoryCapturer_search=std%3A%3Avec A constant function `monitor` that returns an immutable reference to the `Monitor` associated with the `Capturer`. This allows inspection of the display output being captured. ```rust pub const fn monitor(&self) -> &Monitor ``` -------------------------------- ### Scanner Struct and Initialization Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=std%3A%3Avec Provides information on the Scanner struct and how to create a new instance. ```APIDOC ## Struct Scanner ### Description Scan for `Monitor`s. ### Source ```rust pub struct Scanner { /* private fields */ } ``` ### Examples ```rust use rusty_duplication::Scanner; // create a new scanner let mut scanner = Scanner::new().unwrap(); // get the next available monitor let ctx = scanner.next().unwrap(); ``` ## impl Scanner ### pub fn new() -> Result #### Description Try to create a new scanner. Return `Err` if no adapter is found. #### Method `new` #### Returns `Result`: A new scanner instance or an error if no adapter is found. ``` -------------------------------- ### Capturer Initialization with Buffer Factory in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.VecCapturer Shows how to create a new `Capturer` instance using a monitor and a buffer factory. The `buffer_factory` closure is responsible for allocating the buffer of a specified size. ```rust pub fn new( monitor: Monitor, buffer_factory: impl FnOnce(usize) -> Result, ) -> Result ``` -------------------------------- ### Get ExitCode from Result in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.Result_search= Returns the representation of the Result value as an ExitCode, which is then returned to the operating system. This method is part of the Termination trait implementation for Result. ```rust fn report(self) -> ExitCode ``` -------------------------------- ### Folding Iterator Elements into a Single Value Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Reduces the iterator's elements into a single value by repeatedly applying a closure. It starts with an initial value and updates it with each element. ```rust fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, ``` -------------------------------- ### Capturer Implementations Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Capturer_search= APIs for creating, opening, and managing screen capture instances. ```APIDOC ## Implementations for Capturer ### `impl Capturer` #### `pub fn create(monitor: Monitor, name: &str) -> Result` Create an instance by creating a new shared memory with the provided name. #### `pub fn open(monitor: Monitor, name: &str) -> Result` Create an instance by opening an existing shared memory with the provided name. ### `impl Capturer` #### `pub fn new(monitor: Monitor, buffer_factory: impl FnOnce(usize) -> Result) -> Result` Create a new capturer with the provided monitor and buffer factory. The parameter of `buffer_factory` is the size of the buffer, in bytes. #### `pub const fn monitor(&self) -> &Monitor` Returns a reference to the monitor associated with this capturer. #### `pub fn check_buffer(&self) -> Result<()>` where Buffer: CapturerBuffer, Ensure `Self::buffer` is large enough to hold the frame. #### `pub unsafe fn capture_unchecked(&mut self) -> Result` where Buffer: CapturerBuffer, Capture the screen and return the frame info. The pixel data is stored in the `Self::buffer`. ##### Safety You have to ensure `Self::buffer` is large enough to hold the frame. You can use `Self::check_buffer` to check the buffer size. #### `pub fn capture(&mut self) -> Result` where Buffer: CapturerBuffer, Capture the screen and return the frame info. The pixel data is stored in the `Self::buffer`. This will call `Self::check_buffer` to check the buffer size. #### `pub unsafe fn capture_with_pointer_shape_unchecked(&mut self) -> Result<(DXGI_OUTDUPL_FRAME_INFO, Option)>` where Buffer: CapturerBuffer, Capture the screen and return the frame info. The pixel data is stored in the `Self::buffer`. If the pointer shape is updated, the `Option` will be `Some`. The pointer shape is stored in the `Self::pointer_shape_buffer`. ##### Safety You have to ensure `Self::buffer` is large enough to hold the frame. You can use `Self::check_buffer` to check the buffer size. #### `pub fn capture_with_pointer_shape(&mut self) -> Result<(DXGI_OUTDUPL_FRAME_INFO, Option)>` where Buffer: CapturerBuffer, Check buffer size before capture. The pixel data is stored in the `Self::buffer`. If mouse is updated, the `Option` is Some. The pointer shape is stored in the `Self::pointer_shape_buffer`. This will call `Self::check_buffer` to check the buffer size. ``` -------------------------------- ### Termination Report Method Source: https://docs.rs/rusty-duplication/latest/rusty_duplication/type.Result_search=u32+-%3E+bool The `report` method is part of the `Termination` trait for `Result`. It is called to get the representation of the value as a status code, which is then returned to the operating system. ```APIDOC ## POST /websites/rs_rusty-duplication/report ### Description Returns the `Result` as an `ExitCode` status code to the operating system. ### Method POST ### Endpoint /websites/rs_rusty-duplication/report ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **self** (Result)* - The Result value to report. ### Request Example ```json { "self": "Ok(0)" } ``` ### Response #### Success Response (200) - **ExitCode** (ExitCode) - The exit code representing the Result. #### Response Example ```json { "exit_code": 0 } ``` ``` -------------------------------- ### Create DXGI Factory and D3D11 Device - Rust Source: https://docs.rs/rusty-duplication/latest/src/rusty_duplication/scanner.rs_search= This code snippet demonstrates the creation of a DXGI factory and a D3D11 device and device context. It's a crucial step for interacting with graphics hardware on Windows for screen capture functionalities. It requires the 'windows' crate for API access. ```Rust use crate::{Error, Result}; use std::ptr::null_mut; use windows::{ core::Interface, Win32::{ Foundation::HMODULE, Graphics::{ Direct3D::D3D_DRIVER_TYPE_UNKNOWN, Direct3D11::{ D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, D3D11_CREATE_DEVICE_FLAG, D3D11_SDK_VERSION, }, Dxgi::{CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1}, }, }, }; fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } ``` -------------------------------- ### Create DXGI Factory and Enumerate Adapters (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs_search=u32+-%3E+bool Creates a DXGI factory to enumerate hardware adapters. This is a prerequisite for initializing Direct3D devices and accessing display outputs. It relies on the `CreateDXGIFactory1` function from the Windows crate. ```rust use crate::Error; use windows::Win32::Graphics::Dxgi::* // ... inside Scanner::new() ... let factory = unsafe { CreateDXGIFactory1::() } .map_err(Error::from_win_err(stringify!(CreateDXGIFactory1)))?; ``` -------------------------------- ### Get Monitor Information in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Monitor Retrieves information about the monitor, primarily used to check if it's the primary display. This function returns a Result containing MONITORINFO or an error. ```rust pub fn monitor_info(&self) -> Result ``` -------------------------------- ### Initialize Screen Scanner (Rust) Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/scanner.rs Creates a new scanner instance to find and iterate over available display monitors. It initializes Direct3D device and factory components. Returns an error if no graphics adapter is found. ```Rust use crate::{Error, Monitor, Result}; use std::ptr::null_mut; use windows::{ core::Interface, Win32::{ Foundation::HMODULE, Graphics::{ Direct3D::D3D_DRIVER_TYPE_UNKNOWN, Direct3D11::{ D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, D3D11_CREATE_DEVICE_FLAG, D3D11_SDK_VERSION, }, Dxgi::{CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1, IDXGIOutput1}, }, }, }; /// Scan for [`Monitor`]s. /// # Examples /// ``` /// use rusty_duplication::Scanner; /// /// // create a new scanner /// let mut scanner = Scanner::new().unwrap(); /// // get the next available monitor /// let ctx = scanner.next().unwrap(); /// ``` #[derive(Debug, Clone)] pub struct Scanner { next_adapter_index: u32, next_output_index: u32, factory: IDXGIFactory1, adapter: IDXGIAdapter1, device: ID3D11Device, device_context: ID3D11DeviceContext, } impl Scanner { /// Try to create a new scanner. /// Return [`Err`] if no adapter is found. pub fn new() -> Result { let factory = unsafe { CreateDXGIFactory1::() } .map_err(Error::from_win_err(stringify!(CreateDXGIFactory1)))?; let adapter_index = 0; let (adapter, device, device_context) = get_adapter(&factory, adapter_index)?; Ok(Self { next_adapter_index: adapter_index + 1, next_output_index: 0, factory, adapter, device, device_context, }) } fn get_current_ctx(&mut self) -> Option { let output_index = self.next_output_index; self.next_output_index += 1; // TODO: add debug log for Result::ok() let output = unsafe { self.adapter.EnumOutputs(output_index) }.ok()?; let output = output.cast::().unwrap(); let output_duplication = unsafe { output.DuplicateOutput(&self.device) }.ok()?; Some(Monitor::new( self.device.clone(), self.device_context.clone(), output, output_duplication, )) } } impl Iterator for Scanner { type Item = Monitor; fn next(&mut self) -> Option { loop { if let Some(ctx) = self.get_current_ctx() { return Some(ctx); } // no more available outputs, try next adapter let adapter_index = self.next_adapter_index; self.next_adapter_index += 1; let Ok((adapter, device, device_context)) = get_adapter(&self.factory, adapter_index) else { break; }; self.adapter = adapter; self.device = device; self.device_context = device_context; self.next_output_index = 0; } None } } fn get_adapter( factory: &IDXGIFactory1, adapter_index: u32, ) -> Result<(IDXGIAdapter1, ID3D11Device, ID3D11DeviceContext)> { let adapter = unsafe { factory.EnumAdapters1(adapter_index) } .map_err(Error::from_win_err(stringify!(IDXGIFactory1.EnumAdapters1)))?; let mut device: Option = None; let mut device_context: Option = None; unsafe { D3D11CreateDevice( &adapter, D3D_DRIVER_TYPE_UNKNOWN, HMODULE(null_mut()), D3D11_CREATE_DEVICE_FLAG(0), None, D3D11_SDK_VERSION, Some(&mut device), None, Some(&mut device_context), ) } .map_err(Error::from_win_err(stringify!(D3D11CreateDevice)))?; Ok((adapter, device.unwrap(), device_context.unwrap())) } #[cfg(test)] mod tests { use super::*; use serial_test::serial; #[test] #[serial] fn manager() { let mut factory = Scanner::new().unwrap(); assert!(factory.next().is_some()); } } ``` -------------------------------- ### Get Monitor Information in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Monitor_search= Retrieves information about a monitor, primarily used to check if the monitor is the primary display. Requires creating a Scanner instance and obtaining a Monitor object. ```rust use rusty_duplication::{Scanner, MonitorInfoExt}; let monitor = Scanner::new().unwrap().next().unwrap(); monitor.monitor_info().unwrap().is_primary(); ``` -------------------------------- ### Generic Capturer Initialization and Info Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/type.SharedMemoryCapturer_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This section details the generic `Capturer` struct's initialization and methods for retrieving information. `new` creates a capturer with a provided monitor and a buffer factory. `monitor` returns a reference to the configured monitor. ```rust pub fn new( monitor: Monitor, buffer_factory: impl FnOnce(usize) -> Result, ) -> Result; pub const fn monitor(&self) -> &Monitor; ``` -------------------------------- ### Get Next Scanner Item in Rust Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Provides the signature for the next method of the Iterator trait as implemented for Scanner. It returns an Option containing the next 'Monitor' or None if the iterator is exhausted. ```rust fn next(&mut self) -> Option ``` -------------------------------- ### Scanner::new() Source: https://docs.rs/rusty-duplication/0.6.1/rusty_duplication/struct.Scanner_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Attempts to create a new Scanner instance. Returns an error if no adapter is found. ```APIDOC ## fn new() -> Result ### Description Try to create a new scanner. Return `Err` if no adapter is found. ### Method `new` ### Parameters None ### Request Body None ### Response #### Success Response (Result) - **Scanner**: A new instance of the Scanner. - **Error**: An error if no adapter is found. ### Response Example ```rust // On success Ok(Scanner { ... }) // On failure Err(Error::NoAdapterFound) ``` ``` -------------------------------- ### Implementations for MONITORINFO in Rust Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/ext.rs_search= Adds an extension method to MONITORINFO to check if a monitor is the primary display. This is determined by examining the dwFlags field for the MONITORINFOF_PRIMARY flag. This functionality is useful in multi-monitor setups. ```Rust use windows::Win32::Graphics::{ Dxgi::{DXGI_OUTDUPL_DESC, DXGI_OUTDUPL_FRAME_INFO, DXGI_OUTPUT_DESC}, Gdi::MONITORINFO, }; pub trait MonitorInfoExt { fn is_primary(&self) -> bool; } impl MonitorInfoExt for MONITORINFO { #[inline] fn is_primary(&self) -> bool { self.dwFlags == 0x01 // MONITORINFOF_PRIMARY } } ``` -------------------------------- ### Implement TryFrom Monitor for VecCapturer Source: https://docs.rs/rusty-duplication/0.6.1/src/rusty_duplication/capturer/vec.rs Implements the `TryFrom` trait for `VecCapturer`. This allows creating a `VecCapturer` instance from a `Monitor` object, initializing the buffer with a vector of zeros matching the screen size. It returns a `Result` to handle potential errors during creation. ```rust impl TryFrom for VecCapturer { type Error = Error; fn try_from(monitor: Monitor) -> Result { Capturer::new(monitor, |size| Ok(vec![0u8; size])) } } ```