Skip to content

Commit

Permalink
Python Update 🎃
Browse files Browse the repository at this point in the history
	modified:   src/capture.rs
	modified:   src/graphics_capture_api.rs
	modified:   windows-capture-python/Cargo.toml
	modified:   windows-capture-python/README.md
	deleted:    windows-capture-python/rust-toolchain.toml
	deleted:    windows-capture-python/rustfmt.toml
	modified:   windows-capture-python/src/lib.rs
	modified:   windows-capture-python/windows_capture/__init__.py
	modified:   windows-capture-python/windows_capture/windows_capture.cp311-win_amd64.pyd
  • Loading branch information
NiiightmareXD committed Nov 23, 2023
1 parent 90b324a commit a8221a8
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 68 deletions.
65 changes: 54 additions & 11 deletions src/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::{
};

use log::{debug, info, trace, warn};
use parking_lot::Mutex;
use windows::{
Foundation::AsyncActionCompletedHandler,
Win32::{
Expand Down Expand Up @@ -39,24 +40,29 @@ use crate::{
pub enum CaptureControlError {
#[error("Failed To Join Thread")]
FailedToJoinThread,
#[error("Thread Handle Is Taken Out Of Struct")]
ThreadHandleIsTaken,
}

/// Struct Used To Control Capture Thread
pub struct CaptureControl {
pub struct CaptureControl<T: WindowsCaptureHandler + Send + 'static> {
thread_handle: Option<JoinHandle<Result<(), Box<dyn Error + Send + Sync>>>>,
halt_handle: Arc<AtomicBool>,
callback: Arc<Mutex<T>>,
}

impl CaptureControl {
impl<T: WindowsCaptureHandler + Send + 'static> CaptureControl<T> {
/// Create A New Capture Control Struct
#[must_use]
pub fn new(
thread_handle: JoinHandle<Result<(), Box<dyn Error + Send + Sync>>>,
halt_handle: Arc<AtomicBool>,
callback: Arc<Mutex<T>>,
) -> Self {
Self {
thread_handle: Some(thread_handle),
halt_handle,
callback,
}
}

Expand All @@ -68,6 +74,24 @@ impl CaptureControl {
.map_or(true, |thread_handle| thread_handle.is_finished())
}

/// Get The Halt Handle Used To Pause The Capture Thread
#[must_use]
pub fn into_thread_handle(self) -> JoinHandle<Result<(), Box<dyn Error + Send + Sync>>> {
self.thread_handle.unwrap()
}

/// Get The Halt Handle Used To Pause The Capture Thread
#[must_use]
pub fn halt_handle(&self) -> Arc<AtomicBool> {
self.halt_handle.clone()
}

/// Get The Callback Struct Used To Call Struct Methods Directly
#[must_use]
pub fn callback(&self) -> Arc<Mutex<T>> {
self.callback.clone()
}

/// Wait Until The Capturing Thread Stops
pub fn wait(mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
if let Some(thread_handle) = self.thread_handle.take() {
Expand All @@ -77,6 +101,8 @@ impl CaptureControl {
return Err(Box::new(CaptureControlError::FailedToJoinThread));
}
}
} else {
return Err(Box::new(CaptureControlError::ThreadHandleIsTaken));
}

Ok(())
Expand Down Expand Up @@ -116,6 +142,8 @@ impl CaptureControl {
return Err(Box::new(CaptureControlError::FailedToJoinThread));
}
}
} else {
return Err(Box::new(CaptureControlError::ThreadHandleIsTaken));
}

Ok(())
Expand Down Expand Up @@ -150,10 +178,10 @@ pub trait WindowsCaptureHandler: Sized {

// Start Capture
info!("Starting Capture Thread");
let trigger = Self::new(settings.flags)?;
let callback = Arc::new(Mutex::new(Self::new(settings.flags)?));
let mut capture = GraphicsCaptureApi::new(
settings.item,
trigger,
callback,
settings.capture_cursor,
settings.draw_border,
settings.color_format,
Expand Down Expand Up @@ -213,12 +241,13 @@ pub trait WindowsCaptureHandler: Sized {
/// Starts The Capture Without Taking Control Of The Current Thread
fn start_free_threaded(
settings: WindowsCaptureSettings<Self::Flags>,
) -> Result<CaptureControl, Box<dyn Error + Send + Sync>>
) -> Result<CaptureControl<Self>, Box<dyn Error + Send + Sync>>
where
Self: Send + 'static,
<Self as WindowsCaptureHandler>::Flags: Send,
{
let (sender, receiver) = mpsc::channel::<Arc<AtomicBool>>();
let (halt_sender, halt_receiver) = mpsc::channel::<Arc<AtomicBool>>();
let (callback_sender, callback_receiver) = mpsc::channel::<Arc<Mutex<Self>>>();

let thread_handle = thread::spawn(move || -> Result<(), Box<dyn Error + Send + Sync>> {
// Initialize WinRT
Expand All @@ -236,10 +265,10 @@ pub trait WindowsCaptureHandler: Sized {

// Start Capture
info!("Starting Capture Thread");
let trigger = Self::new(settings.flags)?;
let callback = Arc::new(Mutex::new(Self::new(settings.flags)?));
let mut capture = GraphicsCaptureApi::new(
settings.item,
trigger,
callback.clone(),
settings.capture_cursor,
settings.draw_border,
settings.color_format,
Expand All @@ -249,7 +278,11 @@ pub trait WindowsCaptureHandler: Sized {
// Send Halt Handle
trace!("Sending Halt Handle");
let halt_handle = capture.halt_handle();
sender.send(halt_handle)?;
halt_sender.send(halt_handle)?;

// Send Callback
trace!("Sending Callback");
callback_sender.send(callback)?;

// Debug Thread ID
debug!("Thread ID: {}", unsafe { GetCurrentThreadId() });
Expand Down Expand Up @@ -301,7 +334,7 @@ pub trait WindowsCaptureHandler: Sized {
Ok(())
});

let halt_handle = match receiver.recv() {
let halt_handle = match halt_receiver.recv() {
Ok(halt_handle) => halt_handle,
Err(_) => match thread_handle.join() {
Ok(result) => return Err(result.err().unwrap()),
Expand All @@ -311,7 +344,17 @@ pub trait WindowsCaptureHandler: Sized {
},
};

Ok(CaptureControl::new(thread_handle, halt_handle))
let callback = match callback_receiver.recv() {
Ok(callback_handle) => callback_handle,
Err(_) => match thread_handle.join() {
Ok(result) => return Err(result.err().unwrap()),
Err(_) => {
return Err(Box::new(CaptureControlError::FailedToJoinThread));
}
},
};

Ok(CaptureControl::new(thread_handle, halt_handle, callback))
}

/// Function That Will Be Called To Create The Struct The Flags Can Be
Expand Down
23 changes: 10 additions & 13 deletions src/graphics_capture_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub struct GraphicsCaptureApi {
_d3d_device_context: ID3D11DeviceContext,
frame_pool: Option<Arc<Direct3D11CaptureFramePool>>,
session: Option<GraphicsCaptureSession>,
closed: Arc<AtomicBool>,
halt: Arc<AtomicBool>,
active: bool,
capture_cursor: Option<bool>,
draw_border: Option<bool>,
Expand All @@ -85,7 +85,7 @@ impl GraphicsCaptureApi {
/// Create A New Graphics Capture Api Struct
pub fn new<T: WindowsCaptureHandler + Send + 'static>(
item: GraphicsCaptureItem,
callback: T,
callback: Arc<Mutex<T>>,
capture_cursor: Option<bool>,
draw_border: Option<bool>,
color_format: ColorFormat,
Expand Down Expand Up @@ -123,21 +123,18 @@ impl GraphicsCaptureApi {
trace!("Preallocating Memory");
let mut buffer = vec![0u8; 3840 * 2160 * 4];

// Trigger Struct
let callback = Arc::new(Mutex::new(callback));

// Indicates If The Capture Is Closed
let closed = Arc::new(AtomicBool::new(false));
let halt = Arc::new(AtomicBool::new(false));

// Set Capture Session Closed Event
item.Closed(
&TypedEventHandler::<GraphicsCaptureItem, IInspectable>::new({
// Init
let callback_closed = callback.clone();
let closed_item = closed.clone();
let halt_closed = halt.clone();

move |_, _| {
closed_item.store(true, atomic::Ordering::Relaxed);
halt_closed.store(true, atomic::Ordering::Relaxed);

// To Stop Messge Loop
unsafe { PostQuitMessage(0) };
Expand All @@ -159,7 +156,7 @@ impl GraphicsCaptureApi {
&TypedEventHandler::<Direct3D11CaptureFramePool, IInspectable>::new({
// Init
let frame_pool_recreate = frame_pool.clone();
let closed_frame_pool = closed.clone();
let halt_frame_pool = halt.clone();
let d3d_device_frame_pool = d3d_device.clone();
let context = d3d_device_context.clone();

Expand All @@ -169,7 +166,7 @@ impl GraphicsCaptureApi {

move |frame, _| {
// Return Early If The Capture Is Closed
if closed_frame_pool.load(atomic::Ordering::Relaxed) {
if halt_frame_pool.load(atomic::Ordering::Relaxed) {
return Ok(());
}

Expand Down Expand Up @@ -245,7 +242,7 @@ impl GraphicsCaptureApi {
.replace(Some(result))
.expect("Failed To Replace RESULT");

closed_frame_pool.store(true, atomic::Ordering::Relaxed);
halt_frame_pool.store(true, atomic::Ordering::Relaxed);

// To Stop Messge Loop
unsafe { PostQuitMessage(0) };
Expand All @@ -263,7 +260,7 @@ impl GraphicsCaptureApi {
_d3d_device_context: d3d_device_context,
frame_pool: Some(frame_pool),
session: Some(session),
closed,
halt,
active: false,
capture_cursor,
draw_border,
Expand Down Expand Up @@ -328,7 +325,7 @@ impl GraphicsCaptureApi {
/// Get Halt Handle
#[must_use]
pub fn halt_handle(&self) -> Arc<AtomicBool> {
self.closed.clone()
self.halt.clone()
}

/// Check If Windows Graphics Capture Api Is Supported
Expand Down
3 changes: 1 addition & 2 deletions windows-capture-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ version = "1.0.32"
authors = ["NiiightmareXD"]
edition = "2021"
description = "Fastest Windows Screen Capture Library For Python 🔥"
documentation = "https://docs.rs/windows-capture"
readme = "README.md"
repository = "https://github.com/NiiightmareXD/windows-capture"
repository = "https://github.com/NiiightmareXD/windows-capture/tree/main/windows-capture-python"
license = "MIT"
keywords = ["screen", "capture", "screenshot", "graphics", "windows"]
categories = [
Expand Down
6 changes: 3 additions & 3 deletions windows-capture-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ from windows_capture import WindowsCapture, Frame, InternalCaptureControl

# Every Error From on_closed and on_frame_arrived Will End Up Here
capture = WindowsCapture(
capture_cursor=True,
draw_border=False,
monitor_index=0,
capture_cursor=None,
draw_border=None,
monitor_index=None,
window_name=None,
)

Expand Down
3 changes: 0 additions & 3 deletions windows-capture-python/rust-toolchain.toml

This file was deleted.

12 changes: 0 additions & 12 deletions windows-capture-python/rustfmt.toml

This file was deleted.

Loading

0 comments on commit a8221a8

Please sign in to comment.