1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
//! A cross-platform screen/window/audio capture library
//!
//! ## MacOS Docs
//!
//! Since we depend on the metal crate, our docs won't build for macos under docs.rs's linux containers. As a workaround, you can see our build of the docs for MacOS here:
//! [MacOS Documentation](https://augmendtech.github.io/CrabGrab/macos_docs/crabgrab/index.html)
//!
//! ## Feature flags
//!
//! ### GPU Inter-op
//!
//! - **`dx11`** - enables retrieving the surface of a video frame and getting the DX11 device instance for the stream (Windows only)
//! - **`dxgi`** - enables retrieving the surface of a video frame and getting the DXGI device instance for the stream (Windows only)
//! - **`metal`** - enables retrieving the Metal textures for a video frame and getting the Metal device instance for the stream (MacOS only)
//! - **`iosurface`** - enables retrieving the IOSurface for a video frame (MacOS only)
//! - **`wgpu`** - enables retrieving a Wgpu texture from a video frame and getting the Wgpu device instance wrapper for the stream
//!
//! ### Bitmap output
//!
//! - **`bitmap`** - enables creating raw bitmap copies of frames in system memory
//!
//! ### Screenshots
//!
//! - **`screenshot`** - provides an easy-to-use function wrapping `CaptureStream` for single-frame capture
//!
//! ## Example
//!
//! ```
//! use std::time::Duration;
//! use crabgrab::prelude::*;
//!
//! // spin up the async runtime
//! let runtime = tokio::runtime::Builder::new_multi_thread().build().unwrap();
//! // run our capture code in an async context
//! let future = runtime.spawn(async {
//! // ensure we have priveleges to capture content
//! let token = match CaptureStream::test_access(false) {
//! Some(token) => token,
//! None => CaptureStream::request_access(false).await.expect("Expected capture access")
//! };
//! // filter to normal windows
//! let filter = CapturableContentFilter::NORMAL_WINDOWS;
//! // get capturable content matching the filter
//! let content = CapturableContent::new(filter).await.unwrap();
//! // find the window we want to capture
//! let window = content.windows().filter(|window| {
//! let app_identifier = window.application().identifier();
//! app_identifier.to_lowercase().contains("finder") || app_identifier.to_lowercase().contains("explorer")
//! }).next();
//! match window {
//! Some(window) => {
//! println!("capturing window: {}", window.title());
//! // create a captuere config using the first supported pixel format
//! let config = CaptureConfig::with_window(window, CaptureStream::supported_pixel_formats()[0]).unwrap();
//! // create a capture stream with an event handler callback
//! let mut stream = CaptureStream::new(token, config, |stream_event| {
//! match stream_event {
//! Ok(event) => {
//! match event {
//! StreamEvent::Video(frame) => {
//! println!("Got frame: {}", frame.frame_id());
//! },
//! _ => {}
//! }
//! },
//! Err(error) => {
//! println!("Stream error: {:?}", error);
//! }
//! }
//! }).unwrap();
//! // wait for a while to capture some frames
//! tokio::task::block_in_place(|| std::thread::sleep(Duration::from_millis(4000)));
//! stream.stop().unwrap();
//! },
//! None => { println!("Failed to find window"); }
//! }
//! });
//! // wait for the future to complete
//! runtime.block_on(future).unwrap();
//! // shutdown the async runtime
//! runtime.shutdown_timeout(Duration::from_millis(10000));
//! ````
//!
/// Platform-specific extensions
pub mod platform;
/// Extension features
pub mod feature;
/// Geometry types
pub mod util;
/// Audio and video frames
pub mod frame;
/// The actual capture stream and related constructs
pub mod capture_stream;
/// Enumeration of capturable items
pub mod capturable_content;
/// Everything
pub mod prelude;