Files
zed/crates/media/src/media.rs
Mohamad Khani b72a46db68
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
logiguard fork: GPUI xdg-activation keyboard-focus serial fix
Single-commit orphan branch: full zed-industries/zed @ 8c74db0 source tree
with a 3-file patch applied (no upstream history).

Patch (crates/gpui_linux/src/linux/wayland/):
  - serial.rs: add SerialKind::KeyboardEnter
  - client.rs: store wl_keyboard.enter serial; add latest_serial_of()
  - window.rs: activate() uses keyboard-enter serial (Mutter focus gate)

Mutter honors window activation only when the token carries the keyboard-
focus serial from wl_keyboard.enter; GPUI used a stale mouse-press serial.
See docs/tray-window-focus-wayland.md in logiguard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:22:17 +03:30

353 lines
12 KiB
Rust

#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
mod bindings;
#[cfg(target_os = "macos")]
pub mod core_media {
#![allow(non_snake_case)]
pub use crate::bindings::{
CMItemIndex, CMSampleTimingInfo, CMTime, CMTimeMake, CMVideoCodecType,
kCMSampleAttachmentKey_NotSync, kCMTimeInvalid, kCMVideoCodecType_H264,
};
use anyhow::Result;
use core_foundation::{
array::{CFArray, CFArrayRef},
base::{CFTypeID, OSStatus, TCFType},
declare_TCFType,
dictionary::CFDictionary,
impl_CFTypeDescription, impl_TCFType,
string::CFString,
};
use core_video::image_buffer::{CVImageBuffer, CVImageBufferRef};
use std::{ffi::c_void, ptr};
#[repr(C)]
pub struct __CMSampleBuffer(c_void);
// The ref type must be a pointer to the underlying struct.
pub type CMSampleBufferRef = *const __CMSampleBuffer;
declare_TCFType!(CMSampleBuffer, CMSampleBufferRef);
impl_TCFType!(CMSampleBuffer, CMSampleBufferRef, CMSampleBufferGetTypeID);
impl_CFTypeDescription!(CMSampleBuffer);
impl CMSampleBuffer {
pub fn attachments(&self) -> Vec<CFDictionary<CFString>> {
unsafe {
let attachments =
CMSampleBufferGetSampleAttachmentsArray(self.as_concrete_TypeRef(), true);
CFArray::<CFDictionary>::wrap_under_get_rule(attachments)
.into_iter()
.map(|attachments| {
CFDictionary::wrap_under_get_rule(attachments.as_concrete_TypeRef())
})
.collect()
}
}
pub fn image_buffer(&self) -> Option<CVImageBuffer> {
unsafe {
let ptr = CMSampleBufferGetImageBuffer(self.as_concrete_TypeRef());
if ptr.is_null() {
None
} else {
Some(CVImageBuffer::wrap_under_get_rule(ptr))
}
}
}
pub fn sample_timing_info(&self, index: usize) -> Result<CMSampleTimingInfo> {
unsafe {
let mut timing_info = CMSampleTimingInfo {
duration: kCMTimeInvalid,
presentationTimeStamp: kCMTimeInvalid,
decodeTimeStamp: kCMTimeInvalid,
};
let result = CMSampleBufferGetSampleTimingInfo(
self.as_concrete_TypeRef(),
index as CMItemIndex,
&mut timing_info,
);
anyhow::ensure!(
result == 0,
"error getting sample timing info, code {result}"
);
Ok(timing_info)
}
}
pub fn format_description(&self) -> CMFormatDescription {
unsafe {
CMFormatDescription::wrap_under_get_rule(CMSampleBufferGetFormatDescription(
self.as_concrete_TypeRef(),
))
}
}
pub fn data(&self) -> CMBlockBuffer {
unsafe {
CMBlockBuffer::wrap_under_get_rule(CMSampleBufferGetDataBuffer(
self.as_concrete_TypeRef(),
))
}
}
}
#[link(name = "CoreMedia", kind = "framework")]
unsafe extern "C" {
fn CMSampleBufferGetTypeID() -> CFTypeID;
fn CMSampleBufferGetSampleAttachmentsArray(
buffer: CMSampleBufferRef,
create_if_necessary: bool,
) -> CFArrayRef;
fn CMSampleBufferGetImageBuffer(buffer: CMSampleBufferRef) -> CVImageBufferRef;
fn CMSampleBufferGetSampleTimingInfo(
buffer: CMSampleBufferRef,
index: CMItemIndex,
timing_info_out: *mut CMSampleTimingInfo,
) -> OSStatus;
fn CMSampleBufferGetFormatDescription(buffer: CMSampleBufferRef) -> CMFormatDescriptionRef;
fn CMSampleBufferGetDataBuffer(sample_buffer: CMSampleBufferRef) -> CMBlockBufferRef;
}
#[repr(C)]
pub struct __CMFormatDescription(c_void);
pub type CMFormatDescriptionRef = *const __CMFormatDescription;
declare_TCFType!(CMFormatDescription, CMFormatDescriptionRef);
impl_TCFType!(
CMFormatDescription,
CMFormatDescriptionRef,
CMFormatDescriptionGetTypeID
);
impl_CFTypeDescription!(CMFormatDescription);
impl CMFormatDescription {
pub fn h264_parameter_set_count(&self) -> usize {
unsafe {
let mut count = 0;
let result = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
self.as_concrete_TypeRef(),
0,
ptr::null_mut(),
ptr::null_mut(),
&mut count,
ptr::null_mut(),
);
assert_eq!(result, 0);
count
}
}
pub fn h264_parameter_set_at_index(&self, index: usize) -> Result<&[u8]> {
unsafe {
let mut bytes = ptr::null();
let mut len = 0;
let result = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
self.as_concrete_TypeRef(),
index,
&mut bytes,
&mut len,
ptr::null_mut(),
ptr::null_mut(),
);
anyhow::ensure!(result == 0, "error getting parameter set, code: {result}");
Ok(std::slice::from_raw_parts(bytes, len))
}
}
}
#[link(name = "CoreMedia", kind = "framework")]
unsafe extern "C" {
fn CMFormatDescriptionGetTypeID() -> CFTypeID;
fn CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
video_desc: CMFormatDescriptionRef,
parameter_set_index: usize,
parameter_set_pointer_out: *mut *const u8,
parameter_set_size_out: *mut usize,
parameter_set_count_out: *mut usize,
NALUnitHeaderLengthOut: *mut isize,
) -> OSStatus;
}
#[repr(C)]
pub struct __CMBlockBuffer(c_void);
pub type CMBlockBufferRef = *const __CMBlockBuffer;
declare_TCFType!(CMBlockBuffer, CMBlockBufferRef);
impl_TCFType!(CMBlockBuffer, CMBlockBufferRef, CMBlockBufferGetTypeID);
impl_CFTypeDescription!(CMBlockBuffer);
impl CMBlockBuffer {
pub fn bytes(&self) -> &[u8] {
unsafe {
let mut bytes = ptr::null();
let mut len = 0;
let result = CMBlockBufferGetDataPointer(
self.as_concrete_TypeRef(),
0,
&mut 0,
&mut len,
&mut bytes,
);
assert!(result == 0, "could not get block buffer data");
std::slice::from_raw_parts(bytes, len)
}
}
}
#[link(name = "CoreMedia", kind = "framework")]
unsafe extern "C" {
fn CMBlockBufferGetTypeID() -> CFTypeID;
fn CMBlockBufferGetDataPointer(
buffer: CMBlockBufferRef,
offset: usize,
length_at_offset_out: *mut usize,
total_length_out: *mut usize,
data_pointer_out: *mut *const u8,
) -> OSStatus;
}
}
#[cfg(target_os = "macos")]
pub mod core_video {
#![allow(non_snake_case)]
#[cfg(target_os = "macos")]
use core_foundation::{
base::{CFTypeID, TCFType},
declare_TCFType, impl_CFTypeDescription, impl_TCFType,
};
#[cfg(target_os = "macos")]
use std::ffi::c_void;
use crate::bindings::{CVReturn, kCVReturnSuccess};
pub use crate::bindings::{
kCVPixelFormatType_32BGRA, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, kCVPixelFormatType_420YpCbCr8Planar,
};
use anyhow::Result;
use core_foundation::{
base::kCFAllocatorDefault, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef,
};
use foreign_types::ForeignTypeRef;
use metal::{MTLDevice, MTLPixelFormat};
use std::ptr;
#[repr(C)]
pub struct __CVMetalTextureCache(c_void);
pub type CVMetalTextureCacheRef = *const __CVMetalTextureCache;
declare_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef);
impl_TCFType!(
CVMetalTextureCache,
CVMetalTextureCacheRef,
CVMetalTextureCacheGetTypeID
);
impl_CFTypeDescription!(CVMetalTextureCache);
impl CVMetalTextureCache {
/// # Safety
///
/// metal_device must be valid according to CVMetalTextureCacheCreate
pub unsafe fn new(metal_device: *mut MTLDevice) -> Result<Self> {
let mut this = ptr::null();
let result = unsafe {
CVMetalTextureCacheCreate(
kCFAllocatorDefault,
ptr::null(),
metal_device,
ptr::null(),
&mut this,
)
};
anyhow::ensure!(
result == kCVReturnSuccess,
"could not create texture cache, code: {result}"
);
unsafe { Ok(CVMetalTextureCache::wrap_under_create_rule(this)) }
}
/// # Safety
///
/// The arguments to this function must be valid according to CVMetalTextureCacheCreateTextureFromImage
pub unsafe fn create_texture_from_image(
&self,
source: ::core_video::image_buffer::CVImageBufferRef,
texture_attributes: CFDictionaryRef,
pixel_format: MTLPixelFormat,
width: usize,
height: usize,
plane_index: usize,
) -> Result<CVMetalTexture> {
let mut this = ptr::null();
let result = unsafe {
CVMetalTextureCacheCreateTextureFromImage(
kCFAllocatorDefault,
self.as_concrete_TypeRef(),
source,
texture_attributes,
pixel_format,
width,
height,
plane_index,
&mut this,
)
};
anyhow::ensure!(
result == kCVReturnSuccess,
"could not create texture, code: {result}"
);
unsafe { Ok(CVMetalTexture::wrap_under_create_rule(this)) }
}
}
#[link(name = "CoreVideo", kind = "framework")]
unsafe extern "C" {
fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
fn CVMetalTextureCacheCreate(
allocator: CFAllocatorRef,
cache_attributes: CFDictionaryRef,
metal_device: *const MTLDevice,
texture_attributes: CFDictionaryRef,
cache_out: *mut CVMetalTextureCacheRef,
) -> CVReturn;
fn CVMetalTextureCacheCreateTextureFromImage(
allocator: CFAllocatorRef,
texture_cache: CVMetalTextureCacheRef,
source_image: ::core_video::image_buffer::CVImageBufferRef,
texture_attributes: CFDictionaryRef,
pixel_format: MTLPixelFormat,
width: usize,
height: usize,
plane_index: usize,
texture_out: *mut CVMetalTextureRef,
) -> CVReturn;
}
#[repr(C)]
pub struct __CVMetalTexture(c_void);
pub type CVMetalTextureRef = *const __CVMetalTexture;
declare_TCFType!(CVMetalTexture, CVMetalTextureRef);
impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
impl_CFTypeDescription!(CVMetalTexture);
impl CVMetalTexture {
pub fn as_texture_ref(&self) -> &metal::TextureRef {
unsafe {
let texture = CVMetalTextureGetTexture(self.as_concrete_TypeRef());
metal::TextureRef::from_ptr(texture as *mut _)
}
}
}
#[link(name = "CoreVideo", kind = "framework")]
unsafe extern "C" {
fn CVMetalTextureGetTypeID() -> CFTypeID;
fn CVMetalTextureGetTexture(texture: CVMetalTextureRef) -> *mut c_void;
}
}